]> git.saurik.com Git - apple/xnu.git/blob - osfmk/corecrypto/ccdbrg/src/ccdrbg_nisthmac.c
xnu-4903.270.47.tar.gz
[apple/xnu.git] / osfmk / corecrypto / ccdbrg / src / ccdrbg_nisthmac.c
1 /*
2 * ccdrbg_nisthmac.c
3 * corecrypto
4 *
5 * Created on 05/09/2014
6 *
7 * Copyright (c) 2014,2015 Apple Inc. All rights reserved.
8 *
9 *
10 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
11 *
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.
20 *
21 * Please obtain a copy of the License at
22 * http://www.opensource.apple.com/apsl/ and read it before using this file.
23 *
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.
31 *
32 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
33 */
34
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>
40
41 // Test vectors at:
42 // http://csrc.nist.gov/groups/STM/cavp/#05
43 // http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
44 //
45
46 /*
47 * This HMAC DBRG is described in:
48 *
49 * SP 800-90 A Rev. 1 (2nd Draft)
50 * DRAFT Recommendation for Random Number Generation Using Deterministic Random Bit Generators
51 * April 2014
52 *
53 *
54 * See in particular
55 * - 10.1.2 HMAC_DRBG (p 45)
56 * - B.2 HMAC_DRBGExample (p 83)
57 *
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
60 */
61
62 /*
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.
71 */
72
73 /*
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
78 * too long”, −1)
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).
85 */
86
87 /*
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
93 * bits.
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.
97 */
98
99 //
100 // Defines below based on 10.1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p 39)
101 //
102
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)
105
106 #define MIN_REQ_ENTROPY(di) ((di)->output_size/2)
107
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
110 size_t bytesLeft;
111 uint64_t reseed_counter; // the reseed counter should be able to hole 2^^48. size_t might be smaller than 48 bits
112 size_t vsize;
113 size_t keysize;
114 uint8_t v[2 * NH_MAX_OUTPUT_BLOCK_SIZE];
115 uint8_t *vptr;
116 uint8_t *nextvptr;
117 uint8_t key[NH_MAX_KEY_SIZE];
118 };
119
120 #define DRBG_NISTHMAC_DEBUG 0
121
122
123 #if DRBG_NISTHMAC_DEBUG
124 #include "cc_debug.h"
125
126 static void
127 dumpState(const char *label, struct ccdrbg_nisthmac_state *state)
128 {
129 //cc_print(label, state->vsize, state->nextvptr);
130 cc_print(label, state->vsize, state->vptr);
131 cc_print(label, state->keysize, state->key);
132 }
133 #endif
134
135
136 static void done(struct ccdrbg_state *drbg);
137
138 /*
139 * NIST SP 800-90A, Rev. 1 HMAC_DRBG April 2014, p 46
140 *
141 * HMAC_DRBG_Update (provided_data, K, V):
142 * 1. provided_data: The data to be used.
143 * 2. K: The current value of Key.
144 * 3. V: The current value of V.
145 * Output:
146 * 1. K: The new value for Key.
147 * 2. V: The new value for V.
148 *
149 * HMAC_DRBG Update Process:
150 *
151 * 1. K = HMAC (K, V || 0x00 || provided_data).
152 * 2. V=HMAC(K,V).
153 * 3. If (provided_data = Null), then return K and V.
154 * 4. K = HMAC (K, V || 0x01 || provided_data).
155 * 5. V=HMAC(K,V).
156 * 6. Return K and V.
157 */
158
159 // was: size_t providedDataLength, const void *providedData
160
161 /*
162 * To handle the case where we have three strings that are concatenated,
163 * we pass in three (ptr, len) pairs
164 */
165
166 static int
167 hmac_dbrg_update(struct ccdrbg_state *drbg,
168 size_t daLen, const void *da,
169 size_t dbLen, const void *db,
170 size_t dcLen, const void *dc
171 )
172 {
173 int rc = CCDRBG_STATUS_ERROR;
174 struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg;
175 const struct ccdigest_info *di = state->custom->di;
176
177 const unsigned char cZero = 0x00;
178 const unsigned char cOne = 0x01;
179
180 cchmac_ctx_decl(di->state_size, di->block_size, ctx);
181 cchmac_init(di, ctx, state->keysize, state->key);
182
183 // 1. K = HMAC (K, V || 0x00 || provided_data).
184 cchmac_update(di, ctx, state->vsize, state->vptr);
185 cchmac_update(di, ctx, 1, &cZero);
186 if (da && daLen) {
187 cchmac_update(di, ctx, daLen, da);
188 }
189 if (db && dbLen) {
190 cchmac_update(di, ctx, dbLen, db);
191 }
192 if (dc && dcLen) {
193 cchmac_update(di, ctx, dcLen, dc);
194 }
195 cchmac_final(di, ctx, state->key);
196
197 // One parameter must be non-empty, or return
198 if (((da && daLen) || (db && dbLen) || (dc && dcLen))) {
199 // 2. V=HMAC(K,V).
200 cchmac(di, state->keysize, state->key, state->vsize, state->vptr, state->vptr);
201 // 4. K = HMAC (K, V || 0x01 || provided_data).
202 cchmac_init(di, ctx, state->keysize, state->key);
203 cchmac_update(di, ctx, state->vsize, state->vptr);
204 cchmac_update(di, ctx, 1, &cOne);
205 if (da && daLen) {
206 cchmac_update(di, ctx, daLen, da);
207 }
208 if (db && dbLen) {
209 cchmac_update(di, ctx, dbLen, db);
210 }
211 if (dc && dcLen) {
212 cchmac_update(di, ctx, dcLen, dc);
213 }
214 cchmac_final(di, ctx, state->key);
215 }
216 // If additional data 5. V=HMAC(K,V)
217 // If no addtional data, this is step 2. V=HMAC(K,V).
218 state->bytesLeft = 0;
219
220 // FIPS 140-2 4.9.2 Conditional Tests
221 // "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"
222 // Generate the first block and the second block. Compare for FIPS and discard the first block
223 // We keep the second block as the first set of data to be returned
224 cchmac(di, state->keysize, state->key, state->vsize, state->vptr, state->vptr); // First block
225 cchmac(di, state->keysize, state->key, state->vsize, state->vptr, state->nextvptr); // First to be returned
226 if (0 == cc_cmp_safe(state->vsize, state->vptr, state->nextvptr)) {
227 //The world as we know it has come to an end
228 //the DRBG data structure is zeroized. subsequent calls to
229 //DRBG ends up in NULL dereferencing and/or unpredictable state.
230 //catastrophic error in SP 800-90A
231 done(drbg);
232 rc = CCDRBG_STATUS_ABORT;
233 cc_try_abort(NULL);
234 goto errOut;
235 }
236 rc = CCDRBG_STATUS_OK;
237 errOut:
238 return rc;
239 }
240
241 //make sure state is initialized, before calling this function
242 static int
243 validate_inputs(struct ccdrbg_nisthmac_state *state,
244 size_t entropyLength,
245 size_t additionalInputLength,
246 size_t psLength)
247 {
248 int rc;
249 const struct ccdrbg_nisthmac_custom *custom = state->custom;
250 const struct ccdigest_info *di = custom->di;
251
252 rc = CCDRBG_STATUS_ERROR;
253 //buffer size checks
254 cc_require(di->output_size <= sizeof(state->v) / 2, end); //digest size too long
255 cc_require(di->output_size <= sizeof(state->key), end); //digest size too long
256
257 //NIST SP800 compliance checks
258 //the following maximum checks are redundant if long is 32 bits.
259
260 rc = CCDRBG_STATUS_PARAM_ERROR;
261 cc_require(psLength <= CCDRBG_MAX_PSINPUT_SIZE, end); //personalization string too long
262 cc_require(entropyLength <= CCDRBG_MAX_ENTROPY_SIZE, end); //supplied too much entropy
263 cc_require(additionalInputLength <= CCDRBG_MAX_ADDITIONALINPUT_SIZE, end); //additional input too long
264 cc_require(entropyLength >= MIN_REQ_ENTROPY(di), end); //supplied too litle entropy
265
266 cc_require(di->output_size <= NH_MAX_OUTPUT_BLOCK_SIZE, end); //the requested security strength is not supported
267
268 rc = CCDRBG_STATUS_OK;
269 end:
270 return rc;
271 }
272
273 /*
274 * NIST SP 800-90A, Rev. 1 April 2014 B.2.2, p 84
275 *
276 * HMAC_DRBG_Instantiate_algorithm (...):
277 * Input: bitstring (entropy_input, personalization_string).
278 * Output: bitstring (V, Key), integer reseed_counter.
279 *
280 * Process:
281 * 1. seed_material = entropy_input || personalization_string.
282 * 2. Set Key to outlen bits of zeros.
283 * 3. Set V to outlen/8 bytes of 0x01.
284 * 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V).
285 * 5. reseed_counter = 1.
286 * 6. Return (V, Key, reseed_counter).
287 */
288
289 // This version does not do memory allocation
290 //SP800-90 A: Required minimum entropy for instantiate and reseed=security_strength
291
292 static int
293 hmac_dbrg_instantiate_algorithm(struct ccdrbg_state *drbg,
294 size_t entropyLength, const void *entropy,
295 size_t nonceLength, const void *nonce,
296 size_t psLength, const void *ps)
297 {
298 // TODO: The NIST code passes nonce (i.e. HMAC key) to generate, but cc interface isn't set up that way
299 struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg;
300
301 // 1. seed_material = entropy_input || nonce || personalization_string.
302
303 // 2. Set Key to outlen bits of zeros.
304 cc_zero(state->keysize, state->key);
305
306 // 3. Set V to outlen/8 bytes of 0x01.
307 CC_MEMSET(state->vptr, 0x01, state->vsize);
308
309 // 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V).
310 hmac_dbrg_update(drbg, entropyLength, entropy, nonceLength, nonce, psLength, ps);
311
312 // 5. reseed_counter = 1.
313 state->reseed_counter = 1;
314
315 return CCDRBG_STATUS_OK;
316 }
317
318 // In NIST terminology, the nonce is the HMAC key and ps is the personalization string
319 // We assume that the caller has passed in
320 // min_entropy = NH_REQUIRED_MIN_ENTROPY(security_strength)
321 // bytes of entropy
322
323 static int
324 init(const struct ccdrbg_info *info, struct ccdrbg_state *drbg,
325 size_t entropyLength, const void* entropy,
326 size_t nonceLength, const void* nonce,
327 size_t psLength, const void* ps)
328 {
329 struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg;
330 state->bytesLeft = 0;
331 state->custom = info->custom; //we only need to get the custom parameter from the info structure.
332
333 int rc = validate_inputs(state, entropyLength, 0, psLength);
334 if (rc != CCDRBG_STATUS_OK) {
335 //clear everything if cannot initialize. The idea is that if the caller doesn't check the output of init() and init() fails,
336 //the system crashes by NULL dereferencing after a call to generate, rather than generating bad random numbers.
337 done(drbg);
338 return rc;
339 }
340
341 const struct ccdigest_info *di = state->custom->di;
342 state->vsize = di->output_size;
343 state->keysize = di->output_size;
344 state->vptr = state->v;
345 state->nextvptr = state->v + state->vsize;
346
347 // 7. (V, Key, reseed_counter) = HMAC_DRBG_Instantiate_algorithm (entropy_input, personalization_string).
348 hmac_dbrg_instantiate_algorithm(drbg, entropyLength, entropy, nonceLength, nonce, psLength, ps);
349
350 #if DRBG_NISTHMAC_DEBUG
351 dumpState("Init: ", state);
352 #endif
353 return CCDRBG_STATUS_OK;
354 }
355
356 /*
357 * 10.1.2.4 Reseeding an HMAC_DRBG Instantiation
358 * Notes for the reseed function specified in Section 9.2:
359 * The reseeding of an HMAC_DRBG instantiation requires a call to the Reseed_function specified in Section 9.2.
360 * Process step 6 of that function calls the reseed algorithm specified in this section. The values for min_length
361 * are provided in Table 2 of Section 10.1.
362 *
363 * The reseed algorithm:
364 * Let HMAC_DRBG_Update be the function specified in Section 10.1.2.2. The following process or its equivalent
365 * shall be used as the reseed algorithm for this DRBG mechanism (see step 6 of the reseed process in Section 9.2):
366 *
367 * HMAC_DRBG_Reseed_algorithm (working_state, entropy_input, additional_input):
368 * 1. working_state: The current values for V, Key and reseed_counter (see Section 10.1.2.1).
369 * 2. entropy_input: The string of bits obtained from the source of entropy input.
370 * 3. additional_input: The additional input string received from the consuming application.
371 * Note that the length of the additional_input string may be zero.
372 *
373 * Output:
374 * 1. new_working_state: The new values for V, Key and reseed_counter. HMAC_DRBG Reseed Process:
375 * 1. seed_material = entropy_input || additional_input.
376 * 2. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V). 3. reseed_counter = 1.
377 * 4. Return V, Key and reseed_counter as the new_working_state.
378 */
379
380 static int
381 reseed(struct ccdrbg_state *drbg,
382 size_t entropyLength, const void *entropy,
383 size_t additionalLength, const void *additional)
384 {
385 struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg;
386 int rc = validate_inputs(state, entropyLength, additionalLength, 0);
387 if (rc != CCDRBG_STATUS_OK) {
388 return rc;
389 }
390
391 int rx = hmac_dbrg_update(drbg, entropyLength, entropy, additionalLength, additional, 0, NULL);
392 state->reseed_counter = 1;
393
394 #if DRBG_NISTHMAC_DEBUG
395 dumpState("Reseed: ", state);
396 #endif
397 return rx;
398 }
399
400 /*
401 * HMAC_DRBG_Generate_algorithm:
402 * Input: bitstring (V, Key), integer (reseed_counter, requested_number_of_bits).
403 * Output: string status, bitstring (pseudorandom_bits, V, Key), integer reseed_counter.
404 *
405 * Process:
406 * 1. If (reseed_counter ≥ 10,000), then Return (“Reseed required”, Null, V, Key, reseed_counter).
407 * 2. temp = Null.
408 * 3. While (len (temp) < requested_no_of_bits) do:
409 * 3.1 V = HMAC (Key, V).
410 * 3.2 temp = temp || V.
411 * 4. pseudorandom_bits = Leftmost (requested_no_of_bits) of temp.
412 * 5. (Key, V) = HMAC_DRBG_Update (Null, Key, V).
413 * 6. reseed_counter = reseed_counter + 1.
414 * 7. Return (“Success”, pseudorandom_bits, V, Key, reseed_counter).
415 */
416
417 static int
418 validate_gen_params(uint64_t reseed_counter, size_t dataOutLength, size_t additionalLength)
419 {
420 int rc = CCDRBG_STATUS_PARAM_ERROR;
421
422 // Zero byte in one request is a valid use-case (21208820)
423 cc_require(dataOutLength <= CCDRBG_MAX_REQUEST_SIZE, end); //Requested too many bytes in one request
424 cc_require(additionalLength <= CCDRBG_MAX_ADDITIONALINPUT_SIZE, end); //Additional input too long
425
426 // 1. If (reseed_counter > 2^^48), then Return (“Reseed required”, Null, V, Key, reseed_counter).
427 rc = CCDRBG_STATUS_NEED_RESEED;
428 cc_require(reseed_counter <= CCDRBG_RESEED_INTERVAL, end); //Reseed required
429
430 rc = CCDRBG_STATUS_OK;
431
432 end:
433 return rc;
434 }
435
436 static int
437 generate(struct ccdrbg_state *drbg, size_t dataOutLength, void *dataOut,
438 size_t additionalLength, const void *additional)
439 {
440 struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg;
441 const struct ccdrbg_nisthmac_custom *custom = state->custom;
442 const struct ccdigest_info *di = custom->di;
443
444 int rc = validate_gen_params(state->reseed_counter, dataOutLength, additional == NULL?0:additionalLength);
445 if (rc != CCDRBG_STATUS_OK) {
446 return rc;
447 }
448
449 // 2. If additional_input ≠ Null, then (Key, V) = HMAC_DRBG_Update (additional_input, Key, V).
450 if (additional && additionalLength) {
451 hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL);
452 }
453
454 // hmac_dbrg_generate_algorithm
455 char *outPtr = (char *) dataOut;
456 while (dataOutLength > 0) {
457 if (!state->bytesLeft) {
458 // 5. V=HMAC(K,V).
459 cchmac(di, state->keysize, state->key, state->vsize, state->nextvptr, state->vptr); // Won't be returned
460 // FIPS 140-2 4.9.2 Conditional Tests
461 // "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."
462 if (0 == cc_cmp_safe(state->vsize, state->vptr, state->nextvptr)) {
463 //The world as we know it has come to an end
464 //the DRBG data structure is zeroized. subsequent calls to
465 //DRBG ends up in NULL dereferencing and/or unpredictable state.
466 //catastrophic error in SP 800-90A
467 done(drbg);
468 rc = CCDRBG_STATUS_ABORT;
469 cc_try_abort(NULL);
470 goto errOut;
471 }
472 CC_SWAP(state->nextvptr, state->vptr);
473 state->bytesLeft = state->vsize;
474 #if DRBG_NISTHMAC_DEBUG
475 cc_print("generate blk: ", state->vsize, state->vptr);
476 #endif
477 }
478 size_t outLength = dataOutLength > state->bytesLeft ? state->bytesLeft : dataOutLength;
479 CC_MEMCPY(outPtr, state->vptr, outLength);
480 state->bytesLeft -= outLength;
481 outPtr += outLength;
482 dataOutLength -= outLength;
483 }
484
485 // 6. (Key, V) = HMAC_DRBG_Update (additional_input, Key, V).
486 hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL);
487
488 // 7. reseed_counter = reseed_counter + 1.
489 state->reseed_counter++;
490
491 #if DRBG_NISTHMAC_DEBUG
492 dumpState("generate end: ", state);
493 cc_print("generate end nxt: ", state->vsize, state->nextvptr);
494 #endif
495 rc = CCDRBG_STATUS_OK;
496 errOut:
497 return rc;
498 }
499
500 static void
501 done(struct ccdrbg_state *drbg)
502 {
503 struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg;
504 cc_clear(sizeof(struct ccdrbg_nisthmac_state), state); //clear v, key as well as internal variables
505 }
506
507 struct ccdrbg_info ccdrbg_nisthmac_info = {
508 .size = sizeof(struct ccdrbg_nisthmac_state) + sizeof(struct ccdrbg_nisthmac_custom),
509 .init = init,
510 .reseed = reseed,
511 .generate = generate,
512 .done = done,
513 .custom = NULL
514 };
515
516 /* This initializes an info object with the right options */
517 void
518 ccdrbg_factory_nisthmac(struct ccdrbg_info *info, const struct ccdrbg_nisthmac_custom *custom)
519 {
520 info->size = sizeof(struct ccdrbg_nisthmac_state) + sizeof(struct ccdrbg_nisthmac_custom);
521 info->init = init;
522 info->generate = generate;
523 info->reseed = reseed;
524 info->done = done;
525 info->custom = custom;
526 };