5 * Created on 05/09/2014
7 * Copyright (c) 2014,2015 Apple Inc. All rights reserved.
10 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
12 * This file contains Original Code and/or Modifications of Original Code
13 * as defined in and that are subject to the Apple Public Source License
14 * Version 2.0 (the 'License'). You may not use this file except in
15 * compliance with the License. The rights granted to you under the License
16 * may not be used to create, or enable the creation or redistribution of,
17 * unlawful or unlicensed copies of an Apple operating system, or to
18 * circumvent, violate, or enable the circumvention or violation of, any
19 * terms of an Apple operating system software license agreement.
21 * Please obtain a copy of the License at
22 * http://www.opensource.apple.com/apsl/ and read it before using this file.
24 * The Original Code and all software distributed under the License are
25 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
26 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
27 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
28 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
29 * Please see the License for the specific language governing rights and
30 * limitations under the License.
32 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
35 #include <corecrypto/ccdrbg.h>
36 #include <corecrypto/cchmac.h>
37 #include <corecrypto/ccsha2.h>
38 #include <corecrypto/cc_priv.h>
39 #include <corecrypto/cc_macros.h>
42 // http://csrc.nist.gov/groups/STM/cavp/#05
43 // http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
47 This HMAC DBRG is described in:
49 SP 800-90 A Rev. 1 (2nd Draft)
50 DRAFT Recommendation for Random Number Generation Using Deterministic Random Bit Generators
55 - 10.1.2 HMAC_DRBG (p 45)
56 - B.2 HMAC_DRBGExample (p 83)
58 We support maximum security strength of 256 bits
59 Note that the example in B.2 is very limited, refer to §10.1.2 for more
63 The Get_entropy_input function is specified in pseudocode in [SP 800-90C] for various RBG constructions;
64 however, in general, the function has the following meaning:
65 Get_entropy_input: A function that is used to obtain entropy input. The function call is:
66 (status, entropy_input) = Get_entropy_input (min_entropy, min_ length, max_ length, prediction_resistance_request),
67 which requests a string of bits (entropy_input) with at least min_entropy bits of entropy. The length for the string
68 shall be equal to or greater than min_length bits, and less than or equal to max_length bits. The
69 prediction_resistance_request parameter indicates whether or not prediction resistance is to be provided during the request
70 (i.e., whether fresh entropy is required). A status code is also returned from the function.
74 Check the validity of the input parameters.
75 1. If (requested_instantiation_security_strength > 256), then Return (“Invalid
76 requested_instantiation_security_strength”, −1).
77 2. If (len (personalization_string) > 160), then Return (“Personalization_string
79 Comment: Set the security_strength to one of the valid security strengths.
80 3. If (requested_security_strength ≤ 112), then security_strength = 112 Else (requested_ security_strength ≤ 128), then security_strength = 128 Else (requested_ security_strength ≤ 192), then security_strength = 192 Else security_strength = 256.
81 Comment: Get the entropy_input and the nonce.
82 4. min_entropy = 1.5 × security_strength.
83 5. (status, entropy_input) = Get_entropy_input (min_entropy, 1000).
84 6. If (status ≠ “Success”), then Return (status, −1).
88 1. highest_supported_security_strength = 256.
89 2. Output block (outlen) = 256 bits.
90 3. Required minimum entropy for the entropy input at instantiation = 3/2 security_strength (this includes the entropy required for the nonce).
91 4. Seed length (seedlen) = 440 bits.
92 5. Maximum number of bits per request (max_number_of_bits_per_request) = 7500
94 6. Reseed_interval (reseed_ interval) = 10,000 requests.
95 7. Maximum length of the personalization string (max_personalization_string_length) = 160 bits.
96 8. Maximum length of the entropy input (max _length) = 1000 bits.
100 // Defines below based on 10.1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p 39)
103 #define NH_MAX_OUTPUT_BLOCK_SIZE (CCSHA512_OUTPUT_SIZE) // 512 bits, i.e. 64 bytes (CCSHA512_OUTPUT_SIZE)
104 #define NH_MAX_KEY_SIZE (CCSHA512_OUTPUT_SIZE) // 512 bits, i.e. 64 bytes (CCSHA512_OUTPUT_SIZE)
106 #define MIN_REQ_ENTROPY(di) ((di)->output_size/2)
108 struct ccdrbg_nisthmac_state
{
109 const struct ccdrbg_nisthmac_custom
*custom
; //ccdrbg_nisthmac_state does not need to store ccdrbg_info. ccdrbg_nisthmac_custom is sufficient
111 uint64_t reseed_counter
; // the reseed counter should be able to hole 2^^48. size_t might be smaller than 48 bits
114 uint8_t v
[2*NH_MAX_OUTPUT_BLOCK_SIZE
];
117 uint8_t key
[NH_MAX_KEY_SIZE
];
120 #define DRBG_NISTHMAC_DEBUG 0
123 #if DRBG_NISTHMAC_DEBUG
124 #include "cc_debug.h"
126 static void dumpState(const char *label
, struct ccdrbg_nisthmac_state
*state
) {
127 //cc_print(label, state->vsize, state->nextvptr);
128 cc_print(label
, state
->vsize
, state
->vptr
);
129 cc_print(label
, state
->keysize
, state
->key
);
134 static void done(struct ccdrbg_state
*drbg
);
137 NIST SP 800-90A, Rev. 1 HMAC_DRBG April 2014, p 46
139 HMAC_DRBG_Update (provided_data, K, V):
140 1. provided_data: The data to be used.
141 2. K: The current value of Key.
142 3. V: The current value of V.
144 1. K: The new value for Key.
145 2. V: The new value for V.
147 HMAC_DRBG Update Process:
149 1. K = HMAC (K, V || 0x00 || provided_data).
151 3. If (provided_data = Null), then return K and V.
152 4. K = HMAC (K, V || 0x01 || provided_data).
157 // was: size_t providedDataLength, const void *providedData
160 To handle the case where we have three strings that are concatenated,
161 we pass in three (ptr, len) pairs
164 static int hmac_dbrg_update(struct ccdrbg_state
*drbg
,
165 size_t daLen
, const void *da
,
166 size_t dbLen
, const void *db
,
167 size_t dcLen
, const void *dc
170 int rc
=CCDRBG_STATUS_ERROR
;
171 struct ccdrbg_nisthmac_state
*state
= (struct ccdrbg_nisthmac_state
*)drbg
;
172 const struct ccdigest_info
*di
= state
->custom
->di
;
174 const unsigned char cZero
= 0x00;
175 const unsigned char cOne
= 0x01;
177 cchmac_ctx_decl(di
->state_size
, di
->block_size
, ctx
);
178 cchmac_init(di
, ctx
, state
->keysize
, state
->key
);
180 // 1. K = HMAC (K, V || 0x00 || provided_data).
181 cchmac_update(di
, ctx
, state
->vsize
, state
->vptr
);
182 cchmac_update(di
, ctx
, 1, &cZero
);
183 if (da
&& daLen
) cchmac_update(di
, ctx
, daLen
, da
);
184 if (db
&& dbLen
) cchmac_update(di
, ctx
, dbLen
, db
);
185 if (dc
&& dcLen
) cchmac_update(di
, ctx
, dcLen
, dc
);
186 cchmac_final(di
, ctx
, state
->key
);
188 // One parameter must be non-empty, or return
189 if (((da
&& daLen
) || (db
&& dbLen
) || (dc
&& dcLen
))) {
191 cchmac(di
, state
->keysize
, state
->key
, state
->vsize
, state
->vptr
, state
->vptr
);
192 // 4. K = HMAC (K, V || 0x01 || provided_data).
193 cchmac_init(di
, ctx
, state
->keysize
, state
->key
);
194 cchmac_update(di
, ctx
, state
->vsize
, state
->vptr
);
195 cchmac_update(di
, ctx
, 1, &cOne
);
196 if (da
&& daLen
) cchmac_update(di
, ctx
, daLen
, da
);
197 if (db
&& dbLen
) cchmac_update(di
, ctx
, dbLen
, db
);
198 if (dc
&& dcLen
) cchmac_update(di
, ctx
, dcLen
, dc
);
199 cchmac_final(di
, ctx
, state
->key
);
201 // If additional data 5. V=HMAC(K,V)
202 // If no addtional data, this is step 2. V=HMAC(K,V).
203 state
->bytesLeft
= 0;
205 // FIPS 140-2 4.9.2 Conditional Tests
206 // "the first n-bit block generated after power-up, initialization, or reset shall not be used, but shall be saved for comparison with the next n-bit block to be generated"
207 // Generate the first block and the second block. Compare for FIPS and discard the first block
208 // We keep the second block as the first set of data to be returned
209 cchmac(di
, state
->keysize
, state
->key
, state
->vsize
, state
->vptr
, state
->vptr
); // First block
210 cchmac(di
, state
->keysize
, state
->key
, state
->vsize
, state
->vptr
, state
->nextvptr
); // First to be returned
211 if (0==cc_cmp_safe(state
->vsize
, state
->vptr
, state
->nextvptr
)) {
212 //The world as we know it has come to an end
213 //the DRBG data structure is zeroized. subsequent calls to
214 //DRBG ends up in NULL dereferencing and/or unpredictable state.
215 //catastrophic error in SP 800-90A
217 rc
=CCDRBG_STATUS_ABORT
;
226 //make sure state is initialized, before calling this function
227 static int validate_inputs(struct ccdrbg_nisthmac_state
*state
,
228 size_t entropyLength
,
229 size_t additionalInputLength
,
233 const struct ccdrbg_nisthmac_custom
*custom
=state
->custom
;
234 const struct ccdigest_info
*di
= custom
->di
;
236 rc
=CCDRBG_STATUS_ERROR
;
238 cc_require (di
->output_size
<=sizeof(state
->v
)/2, end
); //digest size too long
239 cc_require (di
->output_size
<=sizeof(state
->key
), end
); //digest size too long
241 //NIST SP800 compliance checks
242 //the following maximum checks are redundant if long is 32 bits.
244 rc
=CCDRBG_STATUS_PARAM_ERROR
;
245 cc_require (psLength
<= CCDRBG_MAX_PSINPUT_SIZE
, end
); //personalization string too long
246 cc_require (entropyLength
<= CCDRBG_MAX_ENTROPY_SIZE
, end
); //supplied too much entropy
247 cc_require (additionalInputLength
<= CCDRBG_MAX_ADDITIONALINPUT_SIZE
, end
); //additional input too long
248 cc_require (entropyLength
>= MIN_REQ_ENTROPY(di
), end
); //supplied too litle entropy
250 cc_require(di
->output_size
<=NH_MAX_OUTPUT_BLOCK_SIZE
, end
); //the requested security strength is not supported
258 NIST SP 800-90A, Rev. 1 April 2014 B.2.2, p 84
260 HMAC_DRBG_Instantiate_algorithm (...):
261 Input: bitstring (entropy_input, personalization_string).
262 Output: bitstring (V, Key), integer reseed_counter.
265 1. seed_material = entropy_input || personalization_string.
266 2. Set Key to outlen bits of zeros.
267 3. Set V to outlen/8 bytes of 0x01.
268 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V).
269 5. reseed_counter = 1.
270 6. Return (V, Key, reseed_counter).
273 // This version does not do memory allocation
274 //SP800-90 A: Required minimum entropy for instantiate and reseed=security_strength
276 static int hmac_dbrg_instantiate_algorithm(struct ccdrbg_state
*drbg
,
277 size_t entropyLength
, const void *entropy
,
278 size_t nonceLength
, const void *nonce
,
279 size_t psLength
, const void *ps
)
281 // TODO: The NIST code passes nonce (i.e. HMAC key) to generate, but cc interface isn't set up that way
282 struct ccdrbg_nisthmac_state
*state
= (struct ccdrbg_nisthmac_state
*)drbg
;
284 // 1. seed_material = entropy_input || nonce || personalization_string.
286 // 2. Set Key to outlen bits of zeros.
287 cc_zero(state
->keysize
, state
->key
);
289 // 3. Set V to outlen/8 bytes of 0x01.
290 CC_MEMSET(state
->vptr
, 0x01, state
->vsize
);
292 // 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V).
293 hmac_dbrg_update(drbg
, entropyLength
, entropy
, nonceLength
, nonce
, psLength
, ps
);
295 // 5. reseed_counter = 1.
296 state
->reseed_counter
= 1;
298 return CCDRBG_STATUS_OK
;
301 // In NIST terminology, the nonce is the HMAC key and ps is the personalization string
302 // We assume that the caller has passed in
303 // min_entropy = NH_REQUIRED_MIN_ENTROPY(security_strength)
306 static int init(const struct ccdrbg_info
*info
, struct ccdrbg_state
*drbg
,
307 size_t entropyLength
, const void* entropy
,
308 size_t nonceLength
, const void* nonce
,
309 size_t psLength
, const void* ps
)
311 struct ccdrbg_nisthmac_state
*state
=(struct ccdrbg_nisthmac_state
*)drbg
;
312 state
->bytesLeft
= 0;
313 state
->custom
= info
->custom
; //we only need to get the custom parameter from the info structure.
315 int rc
= validate_inputs(state
, entropyLength
, 0, psLength
);
316 if(rc
!=CCDRBG_STATUS_OK
){
317 //clear everything if cannot initialize. The idea is that if the caller doesn't check the output of init() and init() fails,
318 //the system crashes by NULL dereferencing after a call to generate, rather than generating bad random numbers.
323 const struct ccdigest_info
*di
= state
->custom
->di
;
324 state
->vsize
= di
->output_size
;
325 state
->keysize
= di
->output_size
;
326 state
->vptr
=state
->v
;
327 state
->nextvptr
=state
->v
+state
->vsize
;
329 // 7. (V, Key, reseed_counter) = HMAC_DRBG_Instantiate_algorithm (entropy_input, personalization_string).
330 hmac_dbrg_instantiate_algorithm(drbg
, entropyLength
, entropy
, nonceLength
, nonce
, psLength
, ps
);
332 #if DRBG_NISTHMAC_DEBUG
333 dumpState("Init: ", state
);
335 return CCDRBG_STATUS_OK
;
340 10.1.2.4 Reseeding an HMAC_DRBG Instantiation
341 Notes for the reseed function specified in Section 9.2:
342 The reseeding of an HMAC_DRBG instantiation requires a call to the Reseed_function specified in Section 9.2.
343 Process step 6 of that function calls the reseed algorithm specified in this section. The values for min_length
344 are provided in Table 2 of Section 10.1.
346 The reseed algorithm:
347 Let HMAC_DRBG_Update be the function specified in Section 10.1.2.2. The following process or its equivalent
348 shall be used as the reseed algorithm for this DRBG mechanism (see step 6 of the reseed process in Section 9.2):
350 HMAC_DRBG_Reseed_algorithm (working_state, entropy_input, additional_input):
351 1. working_state: The current values for V, Key and reseed_counter (see Section 10.1.2.1).
352 2. entropy_input: The string of bits obtained from the source of entropy input.
353 3. additional_input: The additional input string received from the consuming application.
354 Note that the length of the additional_input string may be zero.
357 1. new_working_state: The new values for V, Key and reseed_counter. HMAC_DRBG Reseed Process:
358 1. seed_material = entropy_input || additional_input.
359 2. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V). 3. reseed_counter = 1.
360 4. Return V, Key and reseed_counter as the new_working_state.
364 reseed(struct ccdrbg_state
*drbg
,
365 size_t entropyLength
, const void *entropy
,
366 size_t additionalLength
, const void *additional
)
369 struct ccdrbg_nisthmac_state
*state
= (struct ccdrbg_nisthmac_state
*)drbg
;
370 int rc
= validate_inputs(state
, entropyLength
, additionalLength
, 0);
371 if(rc
!=CCDRBG_STATUS_OK
) return rc
;
373 int rx
= hmac_dbrg_update(drbg
, entropyLength
, entropy
, additionalLength
, additional
, 0, NULL
);
374 state
->reseed_counter
= 1;
376 #if DRBG_NISTHMAC_DEBUG
377 dumpState("Reseed: ", state
);
383 HMAC_DRBG_Generate_algorithm:
384 Input: bitstring (V, Key), integer (reseed_counter, requested_number_of_bits).
385 Output: string status, bitstring (pseudorandom_bits, V, Key), integer reseed_counter.
388 1. If (reseed_counter ≥ 10,000), then Return (“Reseed required”, Null, V, Key, reseed_counter).
390 3. While (len (temp) < requested_no_of_bits) do:
391 3.1 V = HMAC (Key, V).
392 3.2 temp = temp || V.
393 4. pseudorandom_bits = Leftmost (requested_no_of_bits) of temp.
394 5. (Key, V) = HMAC_DRBG_Update (Null, Key, V).
395 6. reseed_counter = reseed_counter + 1.
396 7. Return (“Success”, pseudorandom_bits, V, Key, reseed_counter).
399 static int validate_gen_params(uint64_t reseed_counter
, size_t dataOutLength
, size_t additionalLength
)
402 int rc
=CCDRBG_STATUS_PARAM_ERROR
;
404 // Zero byte in one request is a valid use-case (21208820)
405 cc_require (dataOutLength
<= CCDRBG_MAX_REQUEST_SIZE
, end
); //Requested too many bytes in one request
406 cc_require (additionalLength
<=CCDRBG_MAX_ADDITIONALINPUT_SIZE
, end
); //Additional input too long
408 // 1. If (reseed_counter > 2^^48), then Return (“Reseed required”, Null, V, Key, reseed_counter).
409 rc
= CCDRBG_STATUS_NEED_RESEED
;
410 cc_require (reseed_counter
<= CCDRBG_RESEED_INTERVAL
, end
); //Reseed required
418 static int generate(struct ccdrbg_state
*drbg
, size_t dataOutLength
, void *dataOut
,
419 size_t additionalLength
, const void *additional
)
421 struct ccdrbg_nisthmac_state
*state
= (struct ccdrbg_nisthmac_state
*)drbg
;
422 const struct ccdrbg_nisthmac_custom
*custom
= state
->custom
;
423 const struct ccdigest_info
*di
= custom
->di
;
425 int rc
= validate_gen_params(state
->reseed_counter
, dataOutLength
, additional
==NULL
?0:additionalLength
);
426 if(rc
!=CCDRBG_STATUS_OK
) return rc
;
428 // 2. If additional_input ≠ Null, then (Key, V) = HMAC_DRBG_Update (additional_input, Key, V).
429 if (additional
&& additionalLength
)
430 hmac_dbrg_update(drbg
, additionalLength
, additional
, 0, NULL
, 0, NULL
);
432 // hmac_dbrg_generate_algorithm
433 char *outPtr
= (char *) dataOut
;
434 while (dataOutLength
> 0) {
435 if (!state
->bytesLeft
) {
437 cchmac(di
, state
->keysize
, state
->key
, state
->vsize
, state
->nextvptr
, state
->vptr
); // Won't be returned
438 // FIPS 140-2 4.9.2 Conditional Tests
439 // "Each subsequent generation of an n-bit block shall be compared with the previously generated block. The test shall fail if any two compared n-bit blocks are equal."
440 if (0==cc_cmp_safe(state
->vsize
, state
->vptr
, state
->nextvptr
)) {
441 //The world as we know it has come to an end
442 //the DRBG data structure is zeroized. subsequent calls to
443 //DRBG ends up in NULL dereferencing and/or unpredictable state.
444 //catastrophic error in SP 800-90A
446 rc
=CCDRBG_STATUS_ABORT
;
450 CC_SWAP(state
->nextvptr
, state
->vptr
);
451 state
->bytesLeft
= state
->vsize
;
452 #if DRBG_NISTHMAC_DEBUG
453 cc_print("generate blk: ", state
->vsize
, state
->vptr
);
456 size_t outLength
= dataOutLength
> state
->bytesLeft
? state
->bytesLeft
: dataOutLength
;
457 CC_MEMCPY(outPtr
, state
->vptr
, outLength
);
458 state
->bytesLeft
-= outLength
;
460 dataOutLength
-= outLength
;
463 // 6. (Key, V) = HMAC_DRBG_Update (additional_input, Key, V).
464 hmac_dbrg_update(drbg
, additionalLength
, additional
, 0, NULL
, 0, NULL
);
466 // 7. reseed_counter = reseed_counter + 1.
467 state
->reseed_counter
++;
469 #if DRBG_NISTHMAC_DEBUG
470 dumpState("generate end: ", state
);
471 cc_print("generate end nxt: ", state
->vsize
, state
->nextvptr
);
478 static void done(struct ccdrbg_state
*drbg
)
480 struct ccdrbg_nisthmac_state
*state
=(struct ccdrbg_nisthmac_state
*)drbg
;
481 cc_clear(sizeof(struct ccdrbg_nisthmac_state
), state
); //clear v, key as well as internal variables
484 struct ccdrbg_info ccdrbg_nisthmac_info
= {
485 .size
= sizeof(struct ccdrbg_nisthmac_state
) + sizeof(struct ccdrbg_nisthmac_custom
),
488 .generate
= generate
,
493 /* This initializes an info object with the right options */
494 void ccdrbg_factory_nisthmac(struct ccdrbg_info
*info
, const struct ccdrbg_nisthmac_custom
*custom
)
496 info
->size
= sizeof(struct ccdrbg_nisthmac_state
) + sizeof(struct ccdrbg_nisthmac_custom
);
498 info
->generate
= generate
;
499 info
->reseed
= reseed
;
501 info
->custom
= custom
;