| 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 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); |
| 130 | } |
| 131 | #endif |
| 132 | |
| 133 | |
| 134 | static void done(struct ccdrbg_state *drbg); |
| 135 | |
| 136 | /* |
| 137 | NIST SP 800-90A, Rev. 1 HMAC_DRBG April 2014, p 46 |
| 138 | |
| 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. |
| 143 | Output: |
| 144 | 1. K: The new value for Key. |
| 145 | 2. V: The new value for V. |
| 146 | |
| 147 | HMAC_DRBG Update Process: |
| 148 | |
| 149 | 1. K = HMAC (K, V || 0x00 || provided_data). |
| 150 | 2. V=HMAC(K,V). |
| 151 | 3. If (provided_data = Null), then return K and V. |
| 152 | 4. K = HMAC (K, V || 0x01 || provided_data). |
| 153 | 5. V=HMAC(K,V). |
| 154 | 6. Return K and V. |
| 155 | */ |
| 156 | |
| 157 | // was: size_t providedDataLength, const void *providedData |
| 158 | |
| 159 | /* |
| 160 | To handle the case where we have three strings that are concatenated, |
| 161 | we pass in three (ptr, len) pairs |
| 162 | */ |
| 163 | |
| 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 |
| 168 | ) |
| 169 | { |
| 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; |
| 173 | |
| 174 | const unsigned char cZero = 0x00; |
| 175 | const unsigned char cOne = 0x01; |
| 176 | |
| 177 | cchmac_ctx_decl(di->state_size, di->block_size, ctx); |
| 178 | cchmac_init(di, ctx, state->keysize, state->key); |
| 179 | |
| 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); |
| 187 | |
| 188 | // One parameter must be non-empty, or return |
| 189 | if (((da && daLen) || (db && dbLen) || (dc && dcLen))) { |
| 190 | // 2. V=HMAC(K,V). |
| 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); |
| 200 | } |
| 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; |
| 204 | |
| 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 |
| 216 | done(drbg); |
| 217 | rc=CCDRBG_STATUS_ABORT; |
| 218 | cc_try_abort(NULL); |
| 219 | goto errOut; |
| 220 | } |
| 221 | rc=CCDRBG_STATUS_OK; |
| 222 | errOut: |
| 223 | return rc; |
| 224 | } |
| 225 | |
| 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, |
| 230 | size_t psLength) |
| 231 | { |
| 232 | int rc; |
| 233 | const struct ccdrbg_nisthmac_custom *custom=state->custom; |
| 234 | const struct ccdigest_info *di = custom->di; |
| 235 | |
| 236 | rc =CCDRBG_STATUS_ERROR; |
| 237 | //buffer size checks |
| 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 |
| 240 | |
| 241 | //NIST SP800 compliance checks |
| 242 | //the following maximum checks are redundant if long is 32 bits. |
| 243 | |
| 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 |
| 249 | |
| 250 | cc_require(di->output_size<=NH_MAX_OUTPUT_BLOCK_SIZE, end); //the requested security strength is not supported |
| 251 | |
| 252 | rc=CCDRBG_STATUS_OK; |
| 253 | end: |
| 254 | return rc; |
| 255 | } |
| 256 | |
| 257 | /* |
| 258 | NIST SP 800-90A, Rev. 1 April 2014 B.2.2, p 84 |
| 259 | |
| 260 | HMAC_DRBG_Instantiate_algorithm (...): |
| 261 | Input: bitstring (entropy_input, personalization_string). |
| 262 | Output: bitstring (V, Key), integer reseed_counter. |
| 263 | |
| 264 | Process: |
| 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). |
| 271 | */ |
| 272 | |
| 273 | // This version does not do memory allocation |
| 274 | //SP800-90 A: Required minimum entropy for instantiate and reseed=security_strength |
| 275 | |
| 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) |
| 280 | { |
| 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; |
| 283 | |
| 284 | // 1. seed_material = entropy_input || nonce || personalization_string. |
| 285 | |
| 286 | // 2. Set Key to outlen bits of zeros. |
| 287 | cc_zero(state->keysize, state->key); |
| 288 | |
| 289 | // 3. Set V to outlen/8 bytes of 0x01. |
| 290 | CC_MEMSET(state->vptr, 0x01, state->vsize); |
| 291 | |
| 292 | // 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V). |
| 293 | hmac_dbrg_update(drbg, entropyLength, entropy, nonceLength, nonce, psLength, ps); |
| 294 | |
| 295 | // 5. reseed_counter = 1. |
| 296 | state->reseed_counter = 1; |
| 297 | |
| 298 | return CCDRBG_STATUS_OK; |
| 299 | } |
| 300 | |
| 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) |
| 304 | // bytes of entropy |
| 305 | |
| 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) |
| 310 | { |
| 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. |
| 314 | |
| 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. |
| 319 | done(drbg); |
| 320 | return rc; |
| 321 | } |
| 322 | |
| 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; |
| 328 | |
| 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); |
| 331 | |
| 332 | #if DRBG_NISTHMAC_DEBUG |
| 333 | dumpState("Init: " , state); |
| 334 | #endif |
| 335 | return CCDRBG_STATUS_OK; |
| 336 | |
| 337 | } |
| 338 | |
| 339 | /* |
| 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. |
| 345 | |
| 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): |
| 349 | |
| 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. |
| 355 | |
| 356 | Output: |
| 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. |
| 361 | */ |
| 362 | |
| 363 | static int |
| 364 | reseed(struct ccdrbg_state *drbg, |
| 365 | size_t entropyLength, const void *entropy, |
| 366 | size_t additionalLength, const void *additional) |
| 367 | { |
| 368 | |
| 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; |
| 372 | |
| 373 | int rx = hmac_dbrg_update(drbg, entropyLength, entropy, additionalLength, additional, 0, NULL); |
| 374 | state->reseed_counter = 1; |
| 375 | |
| 376 | #if DRBG_NISTHMAC_DEBUG |
| 377 | dumpState("Reseed: " , state); |
| 378 | #endif |
| 379 | return rx; |
| 380 | } |
| 381 | |
| 382 | /* |
| 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. |
| 386 | |
| 387 | Process: |
| 388 | 1. If (reseed_counter ≥ 10,000), then Return (“Reseed required”, Null, V, Key, reseed_counter). |
| 389 | 2. temp = Null. |
| 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). |
| 397 | */ |
| 398 | |
| 399 | static int validate_gen_params(uint64_t reseed_counter, size_t dataOutLength, size_t additionalLength) |
| 400 | |
| 401 | { |
| 402 | int rc=CCDRBG_STATUS_PARAM_ERROR; |
| 403 | |
| 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 |
| 407 | |
| 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 |
| 411 | |
| 412 | rc=CCDRBG_STATUS_OK; |
| 413 | |
| 414 | end: |
| 415 | return rc; |
| 416 | } |
| 417 | |
| 418 | static int generate(struct ccdrbg_state *drbg, size_t dataOutLength, void *dataOut, |
| 419 | size_t additionalLength, const void *additional) |
| 420 | { |
| 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; |
| 424 | |
| 425 | int rc = validate_gen_params(state->reseed_counter, dataOutLength, additional==NULL?0:additionalLength); |
| 426 | if(rc!=CCDRBG_STATUS_OK) return rc; |
| 427 | |
| 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); |
| 431 | |
| 432 | // hmac_dbrg_generate_algorithm |
| 433 | char *outPtr = (char *) dataOut; |
| 434 | while (dataOutLength > 0) { |
| 435 | if (!state->bytesLeft) { |
| 436 | // 5. V=HMAC(K,V). |
| 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 |
| 445 | done(drbg); |
| 446 | rc=CCDRBG_STATUS_ABORT; |
| 447 | cc_try_abort(NULL); |
| 448 | goto errOut; |
| 449 | } |
| 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); |
| 454 | #endif |
| 455 | } |
| 456 | size_t outLength = dataOutLength > state->bytesLeft ? state->bytesLeft : dataOutLength; |
| 457 | CC_MEMCPY(outPtr, state->vptr, outLength); |
| 458 | state->bytesLeft -= outLength; |
| 459 | outPtr += outLength; |
| 460 | dataOutLength -= outLength; |
| 461 | } |
| 462 | |
| 463 | // 6. (Key, V) = HMAC_DRBG_Update (additional_input, Key, V). |
| 464 | hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL); |
| 465 | |
| 466 | // 7. reseed_counter = reseed_counter + 1. |
| 467 | state->reseed_counter++; |
| 468 | |
| 469 | #if DRBG_NISTHMAC_DEBUG |
| 470 | dumpState("generate end: " , state); |
| 471 | cc_print("generate end nxt: " , state->vsize, state->nextvptr); |
| 472 | #endif |
| 473 | rc=CCDRBG_STATUS_OK; |
| 474 | errOut: |
| 475 | return rc; |
| 476 | } |
| 477 | |
| 478 | static void done(struct ccdrbg_state *drbg) |
| 479 | { |
| 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 |
| 482 | } |
| 483 | |
| 484 | struct ccdrbg_info ccdrbg_nisthmac_info = { |
| 485 | .size = sizeof(struct ccdrbg_nisthmac_state) + sizeof(struct ccdrbg_nisthmac_custom), |
| 486 | .init = init, |
| 487 | .reseed = reseed, |
| 488 | .generate = generate, |
| 489 | .done = done, |
| 490 | .custom = NULL |
| 491 | }; |
| 492 | |
| 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) |
| 495 | { |
| 496 | info->size = sizeof(struct ccdrbg_nisthmac_state) + sizeof(struct ccdrbg_nisthmac_custom); |
| 497 | info->init = init; |
| 498 | info->generate = generate; |
| 499 | info->reseed = reseed; |
| 500 | info->done = done; |
| 501 | info->custom = custom; |
| 502 | }; |
| 503 | |