]>
Commit | Line | Data |
---|---|---|
fe8ab488 A |
1 | /* |
2 | * ccdrbg_nisthmac.c | |
3 | * corecrypto | |
4 | * | |
3e170ce0 A |
5 | * Created on 05/09/2014 |
6 | * | |
7 | * Copyright (c) 2014,2015 Apple Inc. All rights reserved. | |
fe8ab488 A |
8 | * |
9 | */ | |
10 | ||
11 | #include <corecrypto/ccdrbg.h> | |
12 | #include <corecrypto/cchmac.h> | |
13 | #include <corecrypto/ccsha2.h> | |
3e170ce0 | 14 | #include <corecrypto/cc_priv.h> |
fe8ab488 | 15 | #include <corecrypto/cc_debug.h> |
3e170ce0 | 16 | #include <corecrypto/cc_macros.h> |
fe8ab488 A |
17 | |
18 | // Test vectors at: | |
19 | // http://csrc.nist.gov/groups/STM/cavp/#05 | |
20 | // http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip | |
21 | // | |
22 | ||
23 | /* | |
3e170ce0 A |
24 | This HMAC DBRG is described in: |
25 | ||
26 | SP 800-90 A Rev. 1 (2nd Draft) | |
27 | DRAFT Recommendation for Random Number Generation Using Deterministic Random Bit Generators | |
28 | April 2014 | |
29 | ||
30 | ||
31 | See in particular | |
32 | - 10.1.2 HMAC_DRBG (p 45) | |
33 | - B.2 HMAC_DRBGExample (p 83) | |
34 | ||
35 | We support maximum security strength of 256 bits | |
36 | Note that the example in B.2 is very limited, refer to §10.1.2 for more | |
37 | */ | |
fe8ab488 A |
38 | |
39 | /* | |
3e170ce0 | 40 | The Get_entropy_input function is specified in pseudocode in [SP 800-90C] for various RBG constructions; |
fe8ab488 A |
41 | however, in general, the function has the following meaning: |
42 | Get_entropy_input: A function that is used to obtain entropy input. The function call is: | |
43 | (status, entropy_input) = Get_entropy_input (min_entropy, min_ length, max_ length, prediction_resistance_request), | |
44 | which requests a string of bits (entropy_input) with at least min_entropy bits of entropy. The length for the string | |
3e170ce0 A |
45 | shall be equal to or greater than min_length bits, and less than or equal to max_length bits. The |
46 | prediction_resistance_request parameter indicates whether or not prediction resistance is to be provided during the request | |
fe8ab488 A |
47 | (i.e., whether fresh entropy is required). A status code is also returned from the function. |
48 | */ | |
49 | ||
50 | /* | |
51 | Check the validity of the input parameters. | |
52 | 1. If (requested_instantiation_security_strength > 256), then Return (“Invalid | |
53 | requested_instantiation_security_strength”, −1). | |
54 | 2. If (len (personalization_string) > 160), then Return (“Personalization_string | |
55 | too long”, −1) | |
56 | Comment: Set the security_strength to one of the valid security strengths. | |
57 | 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. | |
58 | Comment: Get the entropy_input and the nonce. | |
59 | 4. min_entropy = 1.5 × security_strength. | |
60 | 5. (status, entropy_input) = Get_entropy_input (min_entropy, 1000). | |
61 | 6. If (status ≠ “Success”), then Return (status, −1). | |
62 | */ | |
63 | ||
64 | /* | |
65 | 1. highest_supported_security_strength = 256. | |
66 | 2. Output block (outlen) = 256 bits. | |
67 | 3. Required minimum entropy for the entropy input at instantiation = 3/2 security_strength (this includes the entropy required for the nonce). | |
68 | 4. Seed length (seedlen) = 440 bits. | |
69 | 5. Maximum number of bits per request (max_number_of_bits_per_request) = 7500 | |
70 | bits. | |
71 | 6. Reseed_interval (reseed_ interval) = 10,000 requests. | |
72 | 7. Maximum length of the personalization string (max_personalization_string_length) = 160 bits. | |
73 | 8. Maximum length of the entropy input (max _length) = 1000 bits. | |
74 | */ | |
75 | ||
76 | // | |
77 | // Defines below based on 10.1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p 39) | |
78 | // | |
79 | ||
fe8ab488 A |
80 | #define NH_MAX_OUTPUT_BLOCK_SIZE (CCSHA512_OUTPUT_SIZE) // 512 bits, i.e. 64 bytes (CCSHA512_OUTPUT_SIZE) |
81 | #define NH_MAX_KEY_SIZE (CCSHA512_OUTPUT_SIZE) // 512 bits, i.e. 64 bytes (CCSHA512_OUTPUT_SIZE) | |
3e170ce0 A |
82 | |
83 | #define MIN_REQ_ENTROPY(di) ((di)->output_size/2) | |
fe8ab488 A |
84 | |
85 | struct ccdrbg_nisthmac_state { | |
3e170ce0 A |
86 | const struct ccdrbg_nisthmac_custom *custom; //ccdrbg_nisthmac_state does not need to store ccdrbg_info. ccdrbg_nisthmac_custom is sufficient |
87 | size_t bytesLeft; | |
88 | uint64_t reseed_counter; // the reseed counter should be able to hole 2^^48. size_t might be smaller than 48 bits | |
fe8ab488 A |
89 | size_t vsize; |
90 | size_t keysize; | |
91 | uint8_t v[NH_MAX_OUTPUT_BLOCK_SIZE]; | |
92 | uint8_t key[NH_MAX_KEY_SIZE]; | |
93 | }; | |
94 | ||
95 | #ifdef DEBUGFOO | |
96 | static void dumpState(const char *label, struct ccdrbg_nisthmac_state *state) { | |
97 | cc_print(label, state->vsize, state->v); | |
98 | cc_print(label, state->keysize, state->key); | |
99 | } | |
100 | #endif | |
101 | ||
102 | /* | |
103 | NIST SP 800-90A, Rev. 1 HMAC_DRBG April 2014, p 46 | |
3e170ce0 | 104 | |
fe8ab488 A |
105 | HMAC_DRBG_Update (provided_data, K, V): |
106 | 1. provided_data: The data to be used. | |
107 | 2. K: The current value of Key. | |
108 | 3. V: The current value of V. | |
109 | Output: | |
110 | 1. K: The new value for Key. | |
111 | 2. V: The new value for V. | |
3e170ce0 | 112 | |
fe8ab488 | 113 | HMAC_DRBG Update Process: |
3e170ce0 | 114 | |
fe8ab488 A |
115 | 1. K = HMAC (K, V || 0x00 || provided_data). |
116 | 2. V=HMAC(K,V). | |
117 | 3. If (provided_data = Null), then return K and V. | |
118 | 4. K = HMAC (K, V || 0x01 || provided_data). | |
119 | 5. V=HMAC(K,V). | |
120 | 6. Return K and V. | |
121 | */ | |
122 | ||
123 | // was: unsigned long providedDataLength, const void *providedData | |
124 | ||
125 | /* | |
126 | To handle the case where we have three strings that are concatenated, | |
127 | we pass in three (ptr, len) pairs | |
128 | */ | |
129 | ||
130 | static int hmac_dbrg_update(struct ccdrbg_state *drbg, | |
131 | unsigned long daLen, const void *da, | |
132 | unsigned long dbLen, const void *db, | |
133 | unsigned long dcLen, const void *dc | |
134 | ) | |
135 | { | |
136 | struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; | |
3e170ce0 A |
137 | const struct ccdigest_info *di = state->custom->di; |
138 | ||
fe8ab488 A |
139 | const unsigned char cZero = 0x00; |
140 | const unsigned char cOne = 0x01; | |
141 | cchmac_ctx_decl(di->state_size, di->block_size, ctx); | |
3e170ce0 | 142 | |
fe8ab488 | 143 | cchmac_init(di, ctx, state->keysize, state->key); |
3e170ce0 | 144 | |
fe8ab488 A |
145 | // 1. K = HMAC (K, V || 0x00 || provided_data). |
146 | cchmac_update(di, ctx, state->vsize, state->v); | |
147 | cchmac_update(di, ctx, 1, &cZero); | |
148 | if (da && daLen) cchmac_update(di, ctx, daLen, da); | |
149 | if (db && dbLen) cchmac_update(di, ctx, dbLen, db); | |
150 | if (dc && dcLen) cchmac_update(di, ctx, dcLen, dc); | |
151 | cchmac_final(di, ctx, state->key); | |
3e170ce0 | 152 | |
fe8ab488 A |
153 | // 2. V=HMAC(K,V). |
154 | cchmac(di, state->keysize, state->key, state->vsize, state->v, state->v); | |
3e170ce0 | 155 | |
fe8ab488 A |
156 | // 3. If (provided_data = Null), then return K and V. |
157 | // One parameter must be non-empty, or return | |
158 | if (!((da && daLen) || (db && dbLen) || (dc && dcLen))) | |
3e170ce0 A |
159 | return CCDRBG_STATUS_OK; |
160 | ||
fe8ab488 A |
161 | // 4. K = HMAC (K, V || 0x01 || provided_data). |
162 | cchmac_init(di, ctx, state->keysize, state->key); | |
163 | cchmac_update(di, ctx, state->vsize, state->v); | |
164 | cchmac_update(di, ctx, 1, &cOne); | |
165 | if (da && daLen) cchmac_update(di, ctx, daLen, da); | |
166 | if (db && dbLen) cchmac_update(di, ctx, dbLen, db); | |
167 | if (dc && dcLen) cchmac_update(di, ctx, dcLen, dc); | |
168 | cchmac_final(di, ctx, state->key); | |
3e170ce0 | 169 | |
fe8ab488 A |
170 | // 5. V=HMAC(K,V). |
171 | cchmac(di, state->keysize, state->key, state->vsize, state->v, state->v); | |
3e170ce0 A |
172 | |
173 | return CCDRBG_STATUS_OK; | |
174 | } | |
fe8ab488 | 175 | |
3e170ce0 A |
176 | //make sure state is initialized, before calling this function |
177 | static int validate_inputs(struct ccdrbg_nisthmac_state *state, | |
178 | unsigned long entropyLength, | |
179 | unsigned long additionalInputLength, | |
180 | unsigned long psLength) | |
181 | { | |
182 | int rc; | |
183 | const struct ccdrbg_nisthmac_custom *custom=state->custom; | |
184 | const struct ccdigest_info *di = custom->di; | |
185 | ||
186 | rc =CCDRBG_STATUS_ERROR; | |
187 | //buffer size checks | |
188 | cc_require (di->output_size<=sizeof(state->v), end); //digest size too long | |
189 | cc_require (di->output_size<=sizeof(state->key), end); //digest size too long | |
190 | ||
191 | //NIST SP800 compliance checks | |
192 | //the following maximum checks are redundant if long is 32 bits. | |
193 | ||
194 | rc=CCDRBG_STATUS_PARAM_ERROR; | |
195 | cc_require (psLength <= CCDRBG_MAX_PSINPUT_SIZE, end); //personalization string too long | |
196 | cc_require (entropyLength <= CCDRBG_MAX_ENTROPY_SIZE, end); //supplied too much entropy | |
197 | cc_require (additionalInputLength <= CCDRBG_MAX_ADDITIONALINPUT_SIZE, end); //additional input too long | |
198 | cc_require (entropyLength >= MIN_REQ_ENTROPY(di), end); //supplied too litle entropy | |
199 | ||
200 | cc_require(di->output_size<=NH_MAX_OUTPUT_BLOCK_SIZE, end); //the requested security strength is not supported | |
201 | ||
202 | rc=CCDRBG_STATUS_OK; | |
203 | end: | |
204 | return rc; | |
fe8ab488 A |
205 | } |
206 | ||
207 | /* | |
3e170ce0 A |
208 | NIST SP 800-90A, Rev. 1 April 2014 B.2.2, p 84 |
209 | ||
210 | HMAC_DRBG_Instantiate_algorithm (...): | |
211 | Input: bitstring (entropy_input, personalization_string). | |
212 | Output: bitstring (V, Key), integer reseed_counter. | |
213 | ||
214 | Process: | |
215 | 1. seed_material = entropy_input || personalization_string. | |
216 | 2. Set Key to outlen bits of zeros. | |
217 | 3. Set V to outlen/8 bytes of 0x01. | |
218 | 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V). | |
219 | 5. reseed_counter = 1. | |
220 | 6. Return (V, Key, reseed_counter). | |
221 | */ | |
fe8ab488 A |
222 | |
223 | // This version does not do memory allocation | |
3e170ce0 | 224 | //SP800-90 A: Required minimum entropy for instantiate and reseed=security_strength |
fe8ab488 A |
225 | |
226 | static int hmac_dbrg_instantiate_algorithm(struct ccdrbg_state *drbg, | |
227 | unsigned long entropyLength, const void *entropy, | |
228 | unsigned long nonceLength, const void *nonce, | |
229 | unsigned long psLength, const void *ps) | |
230 | { | |
231 | // TODO: The NIST code passes nonce (i.e. HMAC key) to generate, but cc interface isn't set up that way | |
3e170ce0 A |
232 | struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; |
233 | ||
fe8ab488 | 234 | // 1. seed_material = entropy_input || nonce || personalization_string. |
3e170ce0 | 235 | |
fe8ab488 A |
236 | // 2. Set Key to outlen bits of zeros. |
237 | cc_zero(state->keysize, state->key); | |
3e170ce0 | 238 | |
fe8ab488 A |
239 | // 3. Set V to outlen/8 bytes of 0x01. |
240 | CC_MEMSET(state->v, 0x01, state->vsize); | |
3e170ce0 | 241 | |
fe8ab488 A |
242 | // 4. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V). |
243 | hmac_dbrg_update(drbg, entropyLength, entropy, nonceLength, nonce, psLength, ps); | |
3e170ce0 | 244 | |
fe8ab488 A |
245 | // 5. reseed_counter = 1. |
246 | state->reseed_counter = 1; | |
247 | ||
3e170ce0 | 248 | return CCDRBG_STATUS_OK; |
fe8ab488 A |
249 | } |
250 | ||
251 | // In NIST terminology, the nonce is the HMAC key and ps is the personalization string | |
3e170ce0 A |
252 | // We assume that the caller has passed in |
253 | // min_entropy = NH_REQUIRED_MIN_ENTROPY(security_strength) | |
254 | // bytes of entropy | |
255 | ||
256 | static void done(struct ccdrbg_state *drbg); | |
fe8ab488 A |
257 | |
258 | static int init(const struct ccdrbg_info *info, struct ccdrbg_state *drbg, | |
259 | unsigned long entropyLength, const void* entropy, | |
260 | unsigned long nonceLength, const void* nonce, | |
261 | unsigned long psLength, const void* ps) | |
262 | { | |
263 | struct ccdrbg_nisthmac_state *state=(struct ccdrbg_nisthmac_state *)drbg; | |
fe8ab488 | 264 | state->bytesLeft = 0; |
3e170ce0 A |
265 | state->custom = info->custom; //we only need to get the custom parameter from the info structure. |
266 | ||
267 | int rc = validate_inputs(state , entropyLength, 0, psLength); | |
268 | if(rc!=CCDRBG_STATUS_OK){ | |
269 | //clear everything if cannot initialize. The idea is that if the caller doesn't check the output of init() and init() fails, | |
270 | //the system crashes by NULL dereferencing after a call to generate, rather than generating bad random numbers. | |
271 | done(drbg); | |
272 | return rc; | |
273 | } | |
fe8ab488 | 274 | |
3e170ce0 A |
275 | const struct ccdigest_info *di = state->custom->di; |
276 | state->vsize = di->output_size; | |
277 | state->keysize = di->output_size; | |
278 | ||
fe8ab488 | 279 | // 7. (V, Key, reseed_counter) = HMAC_DRBG_Instantiate_algorithm (entropy_input, personalization_string). |
fe8ab488 A |
280 | hmac_dbrg_instantiate_algorithm(drbg, entropyLength, entropy, nonceLength, nonce, psLength, ps); |
281 | ||
282 | #ifdef DEBUGFOO | |
283 | dumpState("Init: ", state); | |
284 | #endif | |
3e170ce0 A |
285 | return CCDRBG_STATUS_OK; |
286 | ||
fe8ab488 A |
287 | } |
288 | ||
289 | /* | |
3e170ce0 A |
290 | 10.1.2.4 Reseeding an HMAC_DRBG Instantiation |
291 | Notes for the reseed function specified in Section 9.2: | |
292 | The reseeding of an HMAC_DRBG instantiation requires a call to the Reseed_function specified in Section 9.2. | |
293 | Process step 6 of that function calls the reseed algorithm specified in this section. The values for min_length | |
294 | are provided in Table 2 of Section 10.1. | |
295 | ||
296 | The reseed algorithm: | |
297 | Let HMAC_DRBG_Update be the function specified in Section 10.1.2.2. The following process or its equivalent | |
298 | shall be used as the reseed algorithm for this DRBG mechanism (see step 6 of the reseed process in Section 9.2): | |
299 | ||
300 | HMAC_DRBG_Reseed_algorithm (working_state, entropy_input, additional_input): | |
301 | 1. working_state: The current values for V, Key and reseed_counter (see Section 10.1.2.1). | |
302 | 2. entropy_input: The string of bits obtained from the source of entropy input. | |
303 | 3. additional_input: The additional input string received from the consuming application. | |
304 | Note that the length of the additional_input string may be zero. | |
305 | ||
306 | Output: | |
307 | 1. new_working_state: The new values for V, Key and reseed_counter. HMAC_DRBG Reseed Process: | |
308 | 1. seed_material = entropy_input || additional_input. | |
309 | 2. (Key, V) = HMAC_DRBG_Update (seed_material, Key, V). 3. reseed_counter = 1. | |
310 | 4. Return V, Key and reseed_counter as the new_working_state. | |
311 | */ | |
fe8ab488 | 312 | |
3e170ce0 A |
313 | static int |
314 | reseed(struct ccdrbg_state *drbg, | |
315 | unsigned long entropyLength, const void *entropy, | |
316 | unsigned long additionalLength, const void *additional) | |
317 | { | |
318 | ||
319 | struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; | |
320 | int rc = validate_inputs(state, entropyLength, additionalLength, 0); | |
321 | if(rc!=CCDRBG_STATUS_OK) return rc; | |
322 | ||
323 | int rx = hmac_dbrg_update(drbg, entropyLength, entropy, additionalLength, additional, 0, NULL); | |
fe8ab488 | 324 | state->reseed_counter = 1; |
3e170ce0 | 325 | |
fe8ab488 A |
326 | #ifdef DEBUGFOO |
327 | dumpState("Reseed: ", state); | |
328 | #endif | |
329 | return rx; | |
330 | } | |
331 | ||
332 | /* | |
3e170ce0 A |
333 | HMAC_DRBG_Generate_algorithm: |
334 | Input: bitstring (V, Key), integer (reseed_counter, requested_number_of_bits). | |
335 | Output: string status, bitstring (pseudorandom_bits, V, Key), integer reseed_counter. | |
336 | ||
337 | Process: | |
338 | 1. If (reseed_counter ≥ 10,000), then Return (“Reseed required”, Null, V, Key, reseed_counter). | |
339 | 2. temp = Null. | |
340 | 3. While (len (temp) < requested_no_of_bits) do: | |
341 | 3.1 V = HMAC (Key, V). | |
342 | 3.2 temp = temp || V. | |
343 | 4. pseudorandom_bits = Leftmost (requested_no_of_bits) of temp. | |
344 | 5. (Key, V) = HMAC_DRBG_Update (Null, Key, V). | |
345 | 6. reseed_counter = reseed_counter + 1. | |
346 | 7. Return (“Success”, pseudorandom_bits, V, Key, reseed_counter). | |
347 | */ | |
fe8ab488 | 348 | |
3e170ce0 | 349 | static int validate_gen_params(uint64_t reseed_counter, unsigned long dataOutLength, unsigned long additionalLength) |
fe8ab488 | 350 | |
3e170ce0 A |
351 | { |
352 | int rc=CCDRBG_STATUS_PARAM_ERROR; | |
353 | ||
354 | cc_require (dataOutLength >= 1, end); //Requested zero byte in one request | |
355 | cc_require (dataOutLength <= CCDRBG_MAX_REQUEST_SIZE, end); //Requested too many bytes in one request | |
356 | cc_require (additionalLength<=CCDRBG_MAX_ADDITIONALINPUT_SIZE, end); //Additional input too long | |
357 | ||
fe8ab488 | 358 | // 1. If (reseed_counter > 2^^48), then Return (“Reseed required”, Null, V, Key, reseed_counter). |
3e170ce0 A |
359 | rc = CCDRBG_STATUS_NEED_RESEED; |
360 | cc_require (reseed_counter <= CCDRBG_RESEED_INTERVAL, end); //Reseed required | |
361 | ||
362 | rc=CCDRBG_STATUS_OK; | |
363 | ||
364 | end: | |
365 | return rc; | |
366 | } | |
fe8ab488 | 367 | |
3e170ce0 A |
368 | static int generate(struct ccdrbg_state *drbg, unsigned long dataOutLength, void *dataOut, |
369 | unsigned long additionalLength, const void *additional) | |
370 | { | |
371 | struct ccdrbg_nisthmac_state *state = (struct ccdrbg_nisthmac_state *)drbg; | |
372 | const struct ccdrbg_nisthmac_custom *custom = state->custom; | |
373 | const struct ccdigest_info *di = custom->di; | |
374 | ||
375 | int rc = validate_gen_params(state->reseed_counter, dataOutLength, additional==NULL?0:additionalLength); | |
376 | if(rc!=CCDRBG_STATUS_OK) return rc; | |
377 | ||
fe8ab488 | 378 | // 2. If additional_input ≠ Null, then (Key, V) = HMAC_DRBG_Update (additional_input, Key, V). |
3e170ce0 A |
379 | if (additional && additionalLength) |
380 | hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL); | |
381 | ||
fe8ab488 | 382 | // hmac_dbrg_generate_algorithm |
3e170ce0 A |
383 | char *outPtr = (char *) dataOut; |
384 | while (dataOutLength > 0) { | |
fe8ab488 A |
385 | if (!state->bytesLeft) { |
386 | // 5. V=HMAC(K,V). | |
387 | cchmac(di, state->keysize, state->key, state->vsize, state->v, state->v); | |
388 | state->bytesLeft = di->output_size;//di->output_size; state->vsize | |
389 | } | |
3e170ce0 A |
390 | size_t outLength = dataOutLength > state->bytesLeft ? state->bytesLeft : dataOutLength; |
391 | CC_MEMCPY(outPtr, state->v, outLength); | |
fe8ab488 A |
392 | state->bytesLeft -= outLength; |
393 | outPtr += outLength; | |
3e170ce0 | 394 | dataOutLength -= outLength; |
fe8ab488 | 395 | } |
3e170ce0 | 396 | |
fe8ab488 | 397 | // 6. (Key, V) = HMAC_DRBG_Update (additional_input, Key, V). |
3e170ce0 A |
398 | hmac_dbrg_update(drbg, additionalLength, additional, 0, NULL, 0, NULL); |
399 | ||
fe8ab488 A |
400 | // 7. reseed_counter = reseed_counter + 1. |
401 | state->reseed_counter++; | |
3e170ce0 | 402 | |
fe8ab488 A |
403 | #ifdef DEBUGFOO |
404 | dumpState("generate: ", state); | |
405 | #endif | |
406 | ||
3e170ce0 | 407 | return CCDRBG_STATUS_OK; |
fe8ab488 A |
408 | } |
409 | ||
410 | static void done(struct ccdrbg_state *drbg) | |
411 | { | |
412 | struct ccdrbg_nisthmac_state *state=(struct ccdrbg_nisthmac_state *)drbg; | |
3e170ce0 | 413 | cc_clear(sizeof(struct ccdrbg_nisthmac_state), state); //clear v, key as well as internal variables |
fe8ab488 A |
414 | } |
415 | ||
416 | struct ccdrbg_info ccdrbg_nisthmac_info = { | |
417 | .size = sizeof(struct ccdrbg_nisthmac_state) + sizeof(struct ccdrbg_nisthmac_custom), | |
418 | .init = init, | |
419 | .reseed = reseed, | |
420 | .generate = generate, | |
421 | .done = done, | |
422 | .custom = NULL | |
423 | }; | |
424 | ||
425 | /* This initializes an info object with the right options */ | |
426 | void ccdrbg_factory_nisthmac(struct ccdrbg_info *info, const struct ccdrbg_nisthmac_custom *custom) | |
427 | { | |
428 | info->size = sizeof(struct ccdrbg_nisthmac_state) + sizeof(struct ccdrbg_nisthmac_custom); | |
429 | info->init = init; | |
430 | info->generate = generate; | |
431 | info->reseed = reseed; | |
432 | info->done = done; | |
433 | info->custom = custom; | |
434 | }; | |
435 |