blob: aff2cdb659c9e24e52c2ad4897dde46069eb6977 [file] [log] [blame]
Jaeden Ameroe54e6932018-08-06 16:19:58 +01001/*
2 * HMAC_DRBG implementation (NIST SP 800-90)
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of Mbed Crypto (https://tls.mbed.org)
20 */
21
22/*
23 * The NIST SP 800-90A DRBGs are described in the following publication.
24 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
25 * References below are based on rev. 1 (January 2012).
26 */
27
28#if !defined(MBEDCRYPTO_CONFIG_FILE)
29#include "mbedcrypto/config.h"
30#else
31#include MBEDCRYPTO_CONFIG_FILE
32#endif
33
34#if defined(MBEDCRYPTO_HMAC_DRBG_C)
35
36#include "mbedcrypto/hmac_drbg.h"
37#include "mbedcrypto/platform_util.h"
38
39#include <string.h>
40
41#if defined(MBEDCRYPTO_FS_IO)
42#include <stdio.h>
43#endif
44
45#if defined(MBEDCRYPTO_SELF_TEST)
46#if defined(MBEDCRYPTO_PLATFORM_C)
47#include "mbedcrypto/platform.h"
48#else
49#include <stdio.h>
50#define mbedcrypto_printf printf
51#endif /* MBEDCRYPTO_SELF_TEST */
52#endif /* MBEDCRYPTO_PLATFORM_C */
53
54/*
55 * HMAC_DRBG context initialization
56 */
57void mbedcrypto_hmac_drbg_init( mbedcrypto_hmac_drbg_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedcrypto_hmac_drbg_context ) );
60
61#if defined(MBEDCRYPTO_THREADING_C)
62 mbedcrypto_mutex_init( &ctx->mutex );
63#endif
64}
65
66/*
67 * HMAC_DRBG update, using optional additional data (10.1.2.2)
68 */
69void mbedcrypto_hmac_drbg_update( mbedcrypto_hmac_drbg_context *ctx,
70 const unsigned char *additional, size_t add_len )
71{
72 size_t md_len = mbedcrypto_md_get_size( ctx->md_ctx.md_info );
73 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
74 unsigned char sep[1];
75 unsigned char K[MBEDCRYPTO_MD_MAX_SIZE];
76
77 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
78 {
79 /* Step 1 or 4 */
80 mbedcrypto_md_hmac_reset( &ctx->md_ctx );
81 mbedcrypto_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
82 mbedcrypto_md_hmac_update( &ctx->md_ctx, sep, 1 );
83 if( rounds == 2 )
84 mbedcrypto_md_hmac_update( &ctx->md_ctx, additional, add_len );
85 mbedcrypto_md_hmac_finish( &ctx->md_ctx, K );
86
87 /* Step 2 or 5 */
88 mbedcrypto_md_hmac_starts( &ctx->md_ctx, K, md_len );
89 mbedcrypto_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
90 mbedcrypto_md_hmac_finish( &ctx->md_ctx, ctx->V );
91 }
92}
93
94/*
95 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
96 */
97int mbedcrypto_hmac_drbg_seed_buf( mbedcrypto_hmac_drbg_context *ctx,
98 const mbedcrypto_md_info_t * md_info,
99 const unsigned char *data, size_t data_len )
100{
101 int ret;
102
103 if( ( ret = mbedcrypto_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
104 return( ret );
105
106 /*
107 * Set initial working state.
108 * Use the V memory location, which is currently all 0, to initialize the
109 * MD context with an all-zero key. Then set V to its initial value.
110 */
111 mbedcrypto_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedcrypto_md_get_size( md_info ) );
112 memset( ctx->V, 0x01, mbedcrypto_md_get_size( md_info ) );
113
114 mbedcrypto_hmac_drbg_update( ctx, data, data_len );
115
116 return( 0 );
117}
118
119/*
120 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
121 */
122int mbedcrypto_hmac_drbg_reseed( mbedcrypto_hmac_drbg_context *ctx,
123 const unsigned char *additional, size_t len )
124{
125 unsigned char seed[MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT];
126 size_t seedlen;
127
128 /* III. Check input length */
129 if( len > MBEDCRYPTO_HMAC_DRBG_MAX_INPUT ||
130 ctx->entropy_len + len > MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT )
131 {
132 return( MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG );
133 }
134
135 memset( seed, 0, MBEDCRYPTO_HMAC_DRBG_MAX_SEED_INPUT );
136
137 /* IV. Gather entropy_len bytes of entropy for the seed */
138 if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 )
139 return( MBEDCRYPTO_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
140
141 seedlen = ctx->entropy_len;
142
143 /* 1. Concatenate entropy and additional data if any */
144 if( additional != NULL && len != 0 )
145 {
146 memcpy( seed + seedlen, additional, len );
147 seedlen += len;
148 }
149
150 /* 2. Update state */
151 mbedcrypto_hmac_drbg_update( ctx, seed, seedlen );
152
153 /* 3. Reset reseed_counter */
154 ctx->reseed_counter = 1;
155
156 /* 4. Done */
157 return( 0 );
158}
159
160/*
161 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
162 */
163int mbedcrypto_hmac_drbg_seed( mbedcrypto_hmac_drbg_context *ctx,
164 const mbedcrypto_md_info_t * md_info,
165 int (*f_entropy)(void *, unsigned char *, size_t),
166 void *p_entropy,
167 const unsigned char *custom,
168 size_t len )
169{
170 int ret;
171 size_t entropy_len, md_size;
172
173 if( ( ret = mbedcrypto_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
174 return( ret );
175
176 md_size = mbedcrypto_md_get_size( md_info );
177
178 /*
179 * Set initial working state.
180 * Use the V memory location, which is currently all 0, to initialize the
181 * MD context with an all-zero key. Then set V to its initial value.
182 */
183 mbedcrypto_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size );
184 memset( ctx->V, 0x01, md_size );
185
186 ctx->f_entropy = f_entropy;
187 ctx->p_entropy = p_entropy;
188
189 ctx->reseed_interval = MBEDCRYPTO_HMAC_DRBG_RESEED_INTERVAL;
190
191 /*
192 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
193 * each hash function, then according to SP800-90A rev1 10.1 table 2,
194 * min_entropy_len (in bits) is security_strength.
195 *
196 * (This also matches the sizes used in the NIST test vectors.)
197 */
198 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
199 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
200 32; /* better (256+) -> 256 bits */
201
202 /*
203 * For initialisation, use more entropy to emulate a nonce
204 * (Again, matches test vectors.)
205 */
206 ctx->entropy_len = entropy_len * 3 / 2;
207
208 if( ( ret = mbedcrypto_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
209 return( ret );
210
211 ctx->entropy_len = entropy_len;
212
213 return( 0 );
214}
215
216/*
217 * Set prediction resistance
218 */
219void mbedcrypto_hmac_drbg_set_prediction_resistance( mbedcrypto_hmac_drbg_context *ctx,
220 int resistance )
221{
222 ctx->prediction_resistance = resistance;
223}
224
225/*
226 * Set entropy length grabbed for reseeds
227 */
228void mbedcrypto_hmac_drbg_set_entropy_len( mbedcrypto_hmac_drbg_context *ctx, size_t len )
229{
230 ctx->entropy_len = len;
231}
232
233/*
234 * Set reseed interval
235 */
236void mbedcrypto_hmac_drbg_set_reseed_interval( mbedcrypto_hmac_drbg_context *ctx, int interval )
237{
238 ctx->reseed_interval = interval;
239}
240
241/*
242 * HMAC_DRBG random function with optional additional data:
243 * 10.1.2.5 (arabic) + 9.3 (Roman)
244 */
245int mbedcrypto_hmac_drbg_random_with_add( void *p_rng,
246 unsigned char *output, size_t out_len,
247 const unsigned char *additional, size_t add_len )
248{
249 int ret;
250 mbedcrypto_hmac_drbg_context *ctx = (mbedcrypto_hmac_drbg_context *) p_rng;
251 size_t md_len = mbedcrypto_md_get_size( ctx->md_ctx.md_info );
252 size_t left = out_len;
253 unsigned char *out = output;
254
255 /* II. Check request length */
256 if( out_len > MBEDCRYPTO_HMAC_DRBG_MAX_REQUEST )
257 return( MBEDCRYPTO_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
258
259 /* III. Check input length */
260 if( add_len > MBEDCRYPTO_HMAC_DRBG_MAX_INPUT )
261 return( MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG );
262
263 /* 1. (aka VII and IX) Check reseed counter and PR */
264 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
265 ( ctx->prediction_resistance == MBEDCRYPTO_HMAC_DRBG_PR_ON ||
266 ctx->reseed_counter > ctx->reseed_interval ) )
267 {
268 if( ( ret = mbedcrypto_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
269 return( ret );
270
271 add_len = 0; /* VII.4 */
272 }
273
274 /* 2. Use additional data if any */
275 if( additional != NULL && add_len != 0 )
276 mbedcrypto_hmac_drbg_update( ctx, additional, add_len );
277
278 /* 3, 4, 5. Generate bytes */
279 while( left != 0 )
280 {
281 size_t use_len = left > md_len ? md_len : left;
282
283 mbedcrypto_md_hmac_reset( &ctx->md_ctx );
284 mbedcrypto_md_hmac_update( &ctx->md_ctx, ctx->V, md_len );
285 mbedcrypto_md_hmac_finish( &ctx->md_ctx, ctx->V );
286
287 memcpy( out, ctx->V, use_len );
288 out += use_len;
289 left -= use_len;
290 }
291
292 /* 6. Update */
293 mbedcrypto_hmac_drbg_update( ctx, additional, add_len );
294
295 /* 7. Update reseed counter */
296 ctx->reseed_counter++;
297
298 /* 8. Done */
299 return( 0 );
300}
301
302/*
303 * HMAC_DRBG random function
304 */
305int mbedcrypto_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
306{
307 int ret;
308 mbedcrypto_hmac_drbg_context *ctx = (mbedcrypto_hmac_drbg_context *) p_rng;
309
310#if defined(MBEDCRYPTO_THREADING_C)
311 if( ( ret = mbedcrypto_mutex_lock( &ctx->mutex ) ) != 0 )
312 return( ret );
313#endif
314
315 ret = mbedcrypto_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
316
317#if defined(MBEDCRYPTO_THREADING_C)
318 if( mbedcrypto_mutex_unlock( &ctx->mutex ) != 0 )
319 return( MBEDCRYPTO_ERR_THREADING_MUTEX_ERROR );
320#endif
321
322 return( ret );
323}
324
325/*
326 * Free an HMAC_DRBG context
327 */
328void mbedcrypto_hmac_drbg_free( mbedcrypto_hmac_drbg_context *ctx )
329{
330 if( ctx == NULL )
331 return;
332
333#if defined(MBEDCRYPTO_THREADING_C)
334 mbedcrypto_mutex_free( &ctx->mutex );
335#endif
336 mbedcrypto_md_free( &ctx->md_ctx );
337 mbedcrypto_platform_zeroize( ctx, sizeof( mbedcrypto_hmac_drbg_context ) );
338}
339
340#if defined(MBEDCRYPTO_FS_IO)
341int mbedcrypto_hmac_drbg_write_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path )
342{
343 int ret;
344 FILE *f;
345 unsigned char buf[ MBEDCRYPTO_HMAC_DRBG_MAX_INPUT ];
346
347 if( ( f = fopen( path, "wb" ) ) == NULL )
348 return( MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR );
349
350 if( ( ret = mbedcrypto_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
351 goto exit;
352
353 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
354 {
355 ret = MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR;
356 goto exit;
357 }
358
359 ret = 0;
360
361exit:
362 fclose( f );
363 mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
364
365 return( ret );
366}
367
368int mbedcrypto_hmac_drbg_update_seed_file( mbedcrypto_hmac_drbg_context *ctx, const char *path )
369{
370 int ret = 0;
371 FILE *f;
372 size_t n;
373 unsigned char buf[ MBEDCRYPTO_HMAC_DRBG_MAX_INPUT ];
374
375 if( ( f = fopen( path, "rb" ) ) == NULL )
376 return( MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR );
377
378 fseek( f, 0, SEEK_END );
379 n = (size_t) ftell( f );
380 fseek( f, 0, SEEK_SET );
381
382 if( n > MBEDCRYPTO_HMAC_DRBG_MAX_INPUT )
383 {
384 fclose( f );
385 return( MBEDCRYPTO_ERR_HMAC_DRBG_INPUT_TOO_BIG );
386 }
387
388 if( fread( buf, 1, n, f ) != n )
389 ret = MBEDCRYPTO_ERR_HMAC_DRBG_FILE_IO_ERROR;
390 else
391 mbedcrypto_hmac_drbg_update( ctx, buf, n );
392
393 fclose( f );
394
395 mbedcrypto_platform_zeroize( buf, sizeof( buf ) );
396
397 if( ret != 0 )
398 return( ret );
399
400 return( mbedcrypto_hmac_drbg_write_seed_file( ctx, path ) );
401}
402#endif /* MBEDCRYPTO_FS_IO */
403
404
405#if defined(MBEDCRYPTO_SELF_TEST)
406
407#if !defined(MBEDCRYPTO_SHA1_C)
408/* Dummy checkup routine */
409int mbedcrypto_hmac_drbg_self_test( int verbose )
410{
411 (void) verbose;
412 return( 0 );
413}
414#else
415
416#define OUTPUT_LEN 80
417
418/* From a NIST PR=true test vector */
419static const unsigned char entropy_pr[] = {
420 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
421 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
422 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
423 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
424 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
425static const unsigned char result_pr[OUTPUT_LEN] = {
426 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
427 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
428 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
429 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
430 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
431 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
432 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
433
434/* From a NIST PR=false test vector */
435static const unsigned char entropy_nopr[] = {
436 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
437 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
438 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
439 0xe9, 0x9d, 0xfe, 0xdf };
440static const unsigned char result_nopr[OUTPUT_LEN] = {
441 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
442 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
443 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
444 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
445 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
446 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
447 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
448
449/* "Entropy" from buffer */
450static size_t test_offset;
451static int hmac_drbg_self_test_entropy( void *data,
452 unsigned char *buf, size_t len )
453{
454 const unsigned char *p = data;
455 memcpy( buf, p + test_offset, len );
456 test_offset += len;
457 return( 0 );
458}
459
460#define CHK( c ) if( (c) != 0 ) \
461 { \
462 if( verbose != 0 ) \
463 mbedcrypto_printf( "failed\n" ); \
464 return( 1 ); \
465 }
466
467/*
468 * Checkup routine for HMAC_DRBG with SHA-1
469 */
470int mbedcrypto_hmac_drbg_self_test( int verbose )
471{
472 mbedcrypto_hmac_drbg_context ctx;
473 unsigned char buf[OUTPUT_LEN];
474 const mbedcrypto_md_info_t *md_info = mbedcrypto_md_info_from_type( MBEDCRYPTO_MD_SHA1 );
475
476 mbedcrypto_hmac_drbg_init( &ctx );
477
478 /*
479 * PR = True
480 */
481 if( verbose != 0 )
482 mbedcrypto_printf( " HMAC_DRBG (PR = True) : " );
483
484 test_offset = 0;
485 CHK( mbedcrypto_hmac_drbg_seed( &ctx, md_info,
486 hmac_drbg_self_test_entropy, (void *) entropy_pr,
487 NULL, 0 ) );
488 mbedcrypto_hmac_drbg_set_prediction_resistance( &ctx, MBEDCRYPTO_HMAC_DRBG_PR_ON );
489 CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
490 CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
491 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
492 mbedcrypto_hmac_drbg_free( &ctx );
493
494 mbedcrypto_hmac_drbg_free( &ctx );
495
496 if( verbose != 0 )
497 mbedcrypto_printf( "passed\n" );
498
499 /*
500 * PR = False
501 */
502 if( verbose != 0 )
503 mbedcrypto_printf( " HMAC_DRBG (PR = False) : " );
504
505 mbedcrypto_hmac_drbg_init( &ctx );
506
507 test_offset = 0;
508 CHK( mbedcrypto_hmac_drbg_seed( &ctx, md_info,
509 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
510 NULL, 0 ) );
511 CHK( mbedcrypto_hmac_drbg_reseed( &ctx, NULL, 0 ) );
512 CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
513 CHK( mbedcrypto_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
514 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
515 mbedcrypto_hmac_drbg_free( &ctx );
516
517 mbedcrypto_hmac_drbg_free( &ctx );
518
519 if( verbose != 0 )
520 mbedcrypto_printf( "passed\n" );
521
522 if( verbose != 0 )
523 mbedcrypto_printf( "\n" );
524
525 return( 0 );
526}
527#endif /* MBEDCRYPTO_SHA1_C */
528#endif /* MBEDCRYPTO_SELF_TEST */
529
530#endif /* MBEDCRYPTO_HMAC_DRBG_C */