blob: 5516301497309193ac664567fc61b285cda9802c [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
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +010041#if defined(POLARSSL_FS_IO)
42#include <stdio.h>
43#endif
44
Rich Evans00ab4702015-02-06 13:43:58 +000045#if defined(POLARSSL_SELF_TEST)
Paul Bakker7dc4c442014-02-01 22:50:26 +010046#if defined(POLARSSL_PLATFORM_C)
47#include "polarssl/platform.h"
48#else
Rich Evans00ab4702015-02-06 13:43:58 +000049#include <stdio.h>
Paul Bakker7dc4c442014-02-01 22:50:26 +010050#define polarssl_printf printf
Rich Evans00ab4702015-02-06 13:43:58 +000051#endif /* POLARSSL_SELF_TEST */
52#endif /* POLARSSL_PLATFORM_C */
Paul Bakker7dc4c442014-02-01 22:50:26 +010053
Paul Bakker34617722014-06-13 17:20:13 +020054/* Implementation that should never be optimized out by the compiler */
55static void polarssl_zeroize( void *v, size_t n ) {
56 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
57}
58
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010059/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010060 * HMAC_DRBG update, using optional additional data (10.1.2.2)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010061 */
62void hmac_drbg_update( hmac_drbg_context *ctx,
63 const unsigned char *additional, size_t add_len )
64{
65 size_t md_len = ctx->md_ctx.md_info->size;
66 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
67 unsigned char sep[1];
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010068 unsigned char K[POLARSSL_MD_MAX_SIZE];
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010069
70 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
71 {
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010072 /* Step 1 or 4 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010073 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010074 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
75 md_hmac_update( &ctx->md_ctx, sep, 1 );
76 if( rounds == 2 )
77 md_hmac_update( &ctx->md_ctx, additional, add_len );
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010078 md_hmac_finish( &ctx->md_ctx, K );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010079
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +010080 /* Step 2 or 5 */
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +010081 md_hmac_starts( &ctx->md_ctx, K, md_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010082 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
83 md_hmac_finish( &ctx->md_ctx, ctx->V );
84 }
85}
86
87/*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010088 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010089 */
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +010090int hmac_drbg_init_buf( hmac_drbg_context *ctx,
91 const md_info_t * md_info,
92 const unsigned char *data, size_t data_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +010093{
94 int ret;
95
96 memset( ctx, 0, sizeof( hmac_drbg_context ) );
97
Paul Bakker84bbeb52014-07-01 14:53:22 +020098 md_init( &ctx->md_ctx );
99
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100100 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
101 return( ret );
102
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100103 /*
104 * Set initial working state.
105 * Use the V memory location, which is currently all 0, to initialize the
106 * MD context with an all-zero key. Then set V to its initial value.
107 */
108 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100109 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100110
111 hmac_drbg_update( ctx, data, data_len );
112
113 return( 0 );
114}
115
116/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100117 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100118 */
119int hmac_drbg_reseed( hmac_drbg_context *ctx,
120 const unsigned char *additional, size_t len )
121{
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100122 unsigned char seed[POLARSSL_HMAC_DRBG_MAX_SEED_INPUT];
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100123 size_t seedlen;
124
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100125 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100126 if( len > POLARSSL_HMAC_DRBG_MAX_INPUT ||
127 ctx->entropy_len + len > POLARSSL_HMAC_DRBG_MAX_SEED_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100128 {
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100129 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100130 }
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100131
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100132 memset( seed, 0, POLARSSL_HMAC_DRBG_MAX_SEED_INPUT );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100133
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100134 /* IV. Gather entropy_len bytes of entropy for the seed */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100135 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
136 return( POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
137
138 seedlen = ctx->entropy_len;
139
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100140 /* 1. Concatenate entropy and additional data if any */
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100141 if( additional != NULL && len != 0 )
142 {
143 memcpy( seed + seedlen, additional, len );
144 seedlen += len;
145 }
146
147 /* 2. Update state */
148 hmac_drbg_update( ctx, seed, seedlen );
149
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100150 /* 3. Reset reseed_counter */
151 ctx->reseed_counter = 1;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100152
153 /* 4. Done */
154 return( 0 );
155}
156
157/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100158 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100159 */
160int hmac_drbg_init( hmac_drbg_context *ctx,
161 const md_info_t * md_info,
162 int (*f_entropy)(void *, unsigned char *, size_t),
163 void *p_entropy,
164 const unsigned char *custom,
165 size_t len )
166{
167 int ret;
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100168 size_t entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100169
170 memset( ctx, 0, sizeof( hmac_drbg_context ) );
171
Paul Bakker84bbeb52014-07-01 14:53:22 +0200172 md_init( &ctx->md_ctx );
173
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100174 if( ( ret = md_init_ctx( &ctx->md_ctx, md_info ) ) != 0 )
175 return( ret );
176
Manuel Pégourié-Gonnardb05db2a2014-02-01 11:38:05 +0100177 /*
178 * Set initial working state.
179 * Use the V memory location, which is currently all 0, to initialize the
180 * MD context with an all-zero key. Then set V to its initial value.
181 */
182 md_hmac_starts( &ctx->md_ctx, ctx->V, md_info->size );
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100183 memset( ctx->V, 0x01, md_info->size );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100184
185 ctx->f_entropy = f_entropy;
186 ctx->p_entropy = p_entropy;
187
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100188 ctx->reseed_interval = POLARSSL_HMAC_DRBG_RESEED_INTERVAL;
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100189
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100190 /*
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100191 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
192 * each hash function, then according to SP800-90A rev1 10.1 table 2,
193 * min_entropy_len (in bits) is security_strength.
194 *
195 * (This also matches the sizes used in the NIST test vectors.)
196 */
197 entropy_len = md_info->size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
198 md_info->size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
199 32; /* better (256+) -> 256 bits */
200
201 /*
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100202 * For initialisation, use more entropy to emulate a nonce
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100203 * (Again, matches test vectors.)
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 * 3 / 2;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100206
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100207 if( ( ret = hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
208 return( ret );
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100209
Manuel Pégourié-Gonnard8fc484d2014-01-30 18:28:09 +0100210 ctx->entropy_len = entropy_len;
Manuel Pégourié-Gonnardfe34a5f2014-01-30 15:06:40 +0100211
212 return( 0 );
213}
214
215/*
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100216 * Set prediction resistance
217 */
218void hmac_drbg_set_prediction_resistance( hmac_drbg_context *ctx,
219 int resistance )
220{
221 ctx->prediction_resistance = resistance;
222}
223
224/*
Manuel Pégourié-Gonnard4e669c62014-01-30 18:06:08 +0100225 * Set entropy length grabbed for reseeds
226 */
227void hmac_drbg_set_entropy_len( hmac_drbg_context *ctx, size_t len )
228{
229 ctx->entropy_len = len;
230}
231
232/*
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100233 * Set reseed interval
234 */
235void hmac_drbg_set_reseed_interval( hmac_drbg_context *ctx, int interval )
236{
237 ctx->reseed_interval = interval;
238}
239
240/*
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100241 * HMAC_DRBG random function with optional additional data:
242 * 10.1.2.5 (arabic) + 9.3 (Roman)
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100243 */
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100244int hmac_drbg_random_with_add( void *p_rng,
245 unsigned char *output, size_t out_len,
246 const unsigned char *additional, size_t add_len )
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100247{
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100248 int ret;
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100249 hmac_drbg_context *ctx = (hmac_drbg_context *) p_rng;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100250 size_t md_len = md_get_size( ctx->md_ctx.md_info );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100251 size_t left = out_len;
252 unsigned char *out = output;
253
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100254 /* II. Check request length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100255 if( out_len > POLARSSL_HMAC_DRBG_MAX_REQUEST )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100256 return( POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
257
258 /* III. Check input length */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100259 if( add_len > POLARSSL_HMAC_DRBG_MAX_INPUT )
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100260 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
261
262 /* 1. (aka VII and IX) Check reseed counter and PR */
Manuel Pégourié-Gonnardefc8d802014-01-30 19:36:22 +0100263 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
264 ( ctx->prediction_resistance == POLARSSL_HMAC_DRBG_PR_ON ||
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100265 ctx->reseed_counter > ctx->reseed_interval ) )
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100266 {
267 if( ( ret = hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
268 return( ret );
Manuel Pégourié-Gonnard6e897c22014-01-30 19:29:04 +0100269
270 add_len = 0; /* VII.4 */
Manuel Pégourié-Gonnardaf786ff2014-01-30 18:44:18 +0100271 }
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100272
273 /* 2. Use additional data if any */
274 if( additional != NULL && add_len != 0 )
275 hmac_drbg_update( ctx, additional, add_len );
276
277 /* 3, 4, 5. Generate bytes */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100278 while( left != 0 )
279 {
280 size_t use_len = left > md_len ? md_len : left;
281
Manuel Pégourié-Gonnardd742a032014-01-30 19:07:22 +0100282 md_hmac_reset( &ctx->md_ctx );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100283 md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
284 md_hmac_finish( &ctx->md_ctx, ctx->V );
285
286 memcpy( out, ctx->V, use_len );
287 out += use_len;
288 left -= use_len;
289 }
290
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100291 /* 6. Update */
292 hmac_drbg_update( ctx, additional, add_len );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100293
Manuel Pégourié-Gonnard658dbed2014-01-30 19:03:45 +0100294 /* 7. Update reseed counter */
295 ctx->reseed_counter++;
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100296
297 /* 8. Done */
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100298 return( 0 );
299}
300
301/*
Manuel Pégourié-Gonnard8208d162014-01-30 12:19:26 +0100302 * HMAC_DRBG random function
303 */
304int hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
305{
306 return( hmac_drbg_random_with_add( p_rng, output, out_len, NULL, 0 ) );
307}
308
309/*
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100310 * Free an HMAC_DRBG context
311 */
312void hmac_drbg_free( hmac_drbg_context *ctx )
313{
314 if( ctx == NULL )
315 return;
316
317 md_free_ctx( &ctx->md_ctx );
318
Paul Bakker34617722014-06-13 17:20:13 +0200319 polarssl_zeroize( ctx, sizeof( hmac_drbg_context ) );
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100320}
321
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100322#if defined(POLARSSL_FS_IO)
323int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path )
324{
Manuel Pégourié-Gonnard446ee662014-02-01 10:02:32 +0100325 int ret;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100326 FILE *f;
327 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
328
329 if( ( f = fopen( path, "wb" ) ) == NULL )
330 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
331
332 if( ( ret = hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
333 goto exit;
334
335 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
336 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100337 ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
338 goto exit;
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100339 }
340
341 ret = 0;
342
343exit:
344 fclose( f );
345 return( ret );
346}
347
348int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
349{
350 FILE *f;
351 size_t n;
352 unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
353
354 if( ( f = fopen( path, "rb" ) ) == NULL )
355 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
356
357 fseek( f, 0, SEEK_END );
358 n = (size_t) ftell( f );
359 fseek( f, 0, SEEK_SET );
360
361 if( n > POLARSSL_HMAC_DRBG_MAX_INPUT )
362 {
363 fclose( f );
364 return( POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG );
365 }
366
367 if( fread( buf, 1, n, f ) != n )
368 {
Paul Bakker4c284c92014-03-26 15:33:05 +0100369 fclose( f );
370 return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
Manuel Pégourié-Gonnard48bc3e82014-01-30 21:11:16 +0100371 }
372
373 fclose( f );
374
375 hmac_drbg_update( ctx, buf, n );
376
377 return( hmac_drbg_write_seed_file( ctx, path ) );
378}
379#endif /* POLARSSL_FS_IO */
380
Manuel Pégourié-Gonnard490bdf32014-01-27 14:03:10 +0100381
382#if defined(POLARSSL_SELF_TEST)
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 */