/src/nss/lib/softoken/kbkdf.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "pkcs11i.h" |
2 | | #include "blapi.h" |
3 | | #include "secerr.h" |
4 | | #include "softoken.h" |
5 | | |
6 | | /* Overview: |
7 | | * |
8 | | * This file contains implementations of the three KDFs from NIST SP800-108 |
9 | | * "Recommendation for Key Derivation Using Pseudorandom Functions": |
10 | | * |
11 | | * 1. KDF in Counter Mode (section 5.1) |
12 | | * 2. KDF in Feedback Mode (section 5.2) |
13 | | * 3. KDF in Double-Pipeline Iteration Mode (section 5.3) |
14 | | * |
15 | | * These KDFs are a form of negotiable building blocks for KDFs: protocol |
16 | | * designers can choose various fields, their endianness, and the underlying |
17 | | * PRF. These constructs are generic enough to handle creation of arbitrary, |
18 | | * (but known ahead of time) length outputs. |
19 | | * |
20 | | * The families of PRFs described here are used, among other places, in |
21 | | * Kerberos and GlobalPlatform's Secure Channel Protocol 03. The PKCS#11 v3.0 |
22 | | * design for this KDF facilitates a wide range of uses. |
23 | | * |
24 | | * Implementation Details: |
25 | | * |
26 | | * We reuse the new sftk_MACCtx for handling the underlying MACing; with a few |
27 | | * safe restrictions, we can reuse whatever it gives us to use as a PRF. |
28 | | * |
29 | | * We implement the core of the KDF in the *Raw(...) version of the function |
30 | | * call. The PKCS#11 key handling happens in the non-Raw version. This means |
31 | | * we need a single large allocation upfront (large enough to store the entire |
32 | | * key stream), but means we can share key parsing logic and enable the |
33 | | * creation of data objects. |
34 | | */ |
35 | | |
36 | | /* [ section: #define's ] */ |
37 | | |
38 | 0 | #define VALID_CK_BOOL(x) ((x) == CK_TRUE || (x) == CK_FALSE) |
39 | 0 | #define IS_COUNTER(_mech) ((_mech) == CKM_SP800_108_COUNTER_KDF || (_mech) == CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA) |
40 | 0 | #define DOES_DERIVE_DATA(_mech) ((_mech) == CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA || (_mech) == CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA || (_mech) == CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA) |
41 | | |
42 | | /* [ section: parameter validation ] */ |
43 | | |
44 | | static CK_RV |
45 | | kbkdf_LoadParameters(CK_MECHANISM_TYPE mech, CK_MECHANISM_PTR pMechanism, CK_SP800_108_KDF_PARAMS_PTR kdf_params, CK_BYTE_PTR *initial_value, CK_ULONG_PTR initial_value_length) |
46 | 0 | { |
47 | | /* This function loads the parameters for the given mechanism into the |
48 | | * specified kdf_params, splitting off the IV if present. In PKCS#11 v3.0, |
49 | | * CK_SP800_108_FEEDBACK_KDF_PARAMS and CK_SP800_108_KDF_PARAMS have |
50 | | * different ordering of internal parameters, which means that it isn't |
51 | | * easy to reuse feedback parameters in the same functions as non-feedback |
52 | | * parameters. Rather than duplicating the logic, split out the only |
53 | | * Feedback-specific data (the IV) into a separate argument and repack it |
54 | | * into the passed kdf_params struct instead. */ |
55 | 0 | PR_ASSERT(pMechanism != NULL && kdf_params != NULL && initial_value != NULL && initial_value_length != NULL); |
56 | |
|
57 | 0 | CK_SP800_108_KDF_PARAMS_PTR in_params; |
58 | 0 | CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR feedback_params; |
59 | |
|
60 | 0 | if (mech == CKM_SP800_108_FEEDBACK_KDF || mech == CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA) { |
61 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)) { |
62 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
63 | 0 | } |
64 | | |
65 | 0 | feedback_params = (CK_SP800_108_FEEDBACK_KDF_PARAMS *)pMechanism->pParameter; |
66 | |
|
67 | 0 | if (feedback_params->pIV == NULL && feedback_params->ulIVLen > 0) { |
68 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
69 | 0 | } |
70 | | |
71 | 0 | kdf_params->prfType = feedback_params->prfType; |
72 | 0 | kdf_params->ulNumberOfDataParams = feedback_params->ulNumberOfDataParams; |
73 | 0 | kdf_params->pDataParams = feedback_params->pDataParams; |
74 | 0 | kdf_params->ulAdditionalDerivedKeys = feedback_params->ulAdditionalDerivedKeys; |
75 | 0 | kdf_params->pAdditionalDerivedKeys = feedback_params->pAdditionalDerivedKeys; |
76 | |
|
77 | 0 | *initial_value = feedback_params->pIV; |
78 | 0 | *initial_value_length = feedback_params->ulIVLen; |
79 | 0 | } else { |
80 | 0 | if (pMechanism->ulParameterLen != sizeof(CK_SP800_108_KDF_PARAMS)) { |
81 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
82 | 0 | } |
83 | | |
84 | 0 | in_params = (CK_SP800_108_KDF_PARAMS *)pMechanism->pParameter; |
85 | |
|
86 | 0 | (*kdf_params) = *in_params; |
87 | 0 | } |
88 | | |
89 | 0 | return CKR_OK; |
90 | 0 | } |
91 | | |
92 | | static CK_RV |
93 | | kbkdf_ValidateParameter(CK_MECHANISM_TYPE mech, const CK_PRF_DATA_PARAM *data) |
94 | 0 | { |
95 | | /* This function validates that the passed data parameter (data) conforms |
96 | | * to PKCS#11 v3.0's expectations for KDF parameters. This depends both on |
97 | | * the type of this parameter (data->type) and on the KDF mechanism (mech) |
98 | | * as certain parameters are context dependent (like Iteration Variable). |
99 | | */ |
100 | | |
101 | | /* If the parameter is missing a value when one is expected, then this |
102 | | * parameter is invalid. */ |
103 | 0 | if ((data->pValue == NULL) != (data->ulValueLen == 0)) { |
104 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
105 | 0 | } |
106 | | |
107 | 0 | switch (data->type) { |
108 | 0 | case CK_SP800_108_ITERATION_VARIABLE: |
109 | 0 | case CK_SP800_108_OPTIONAL_COUNTER: { |
110 | 0 | if (data->type == CK_SP800_108_ITERATION_VARIABLE && !IS_COUNTER(mech)) { |
111 | | /* In Feedback and Double Pipeline KDFs, PKCS#11 v3.0 connotes the |
112 | | * iteration variable as the chaining value from the previous PRF |
113 | | * invocation. In contrast, counter mode treats this variable as a |
114 | | * COUNTER_FORMAT descriptor. Thus we can skip validation of |
115 | | * iteration variable parameters outside of counter mode. However, |
116 | | * PKCS#11 v3.0 technically mandates that pValue is NULL, so we |
117 | | * still have to validate that. */ |
118 | |
|
119 | 0 | if (data->pValue != NULL) { |
120 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
121 | 0 | } |
122 | | |
123 | 0 | return CKR_OK; |
124 | 0 | } |
125 | | |
126 | | /* In counter mode, data->pValue should be a pointer to an instance of |
127 | | * CK_SP800_108_COUNTER_FORMAT; validate its length. */ |
128 | 0 | if (data->ulValueLen != sizeof(CK_SP800_108_COUNTER_FORMAT)) { |
129 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
130 | 0 | } |
131 | | |
132 | 0 | CK_SP800_108_COUNTER_FORMAT_PTR param = (CK_SP800_108_COUNTER_FORMAT_PTR)data->pValue; |
133 | | |
134 | | /* Validate the endian parameter. */ |
135 | 0 | if (!VALID_CK_BOOL(param->bLittleEndian)) { |
136 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
137 | 0 | } |
138 | | |
139 | | /* Due to restrictions by our underlying hashes, we restrict bit |
140 | | * widths to actually be byte widths by ensuring they're a multiple |
141 | | * of eight. */ |
142 | 0 | if ((param->ulWidthInBits % 8) != 0) { |
143 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
144 | 0 | } |
145 | | |
146 | | /* Note that section 5.1 denotes the maximum length of the counter |
147 | | * to be 32. */ |
148 | 0 | if (param->ulWidthInBits > 32) { |
149 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
150 | 0 | } |
151 | 0 | break; |
152 | 0 | } |
153 | 0 | case CK_SP800_108_DKM_LENGTH: { |
154 | | /* data->pValue should be a pointer to an instance of |
155 | | * CK_SP800_108_DKM_LENGTH_FORMAT; validate its length. */ |
156 | 0 | if (data->ulValueLen != sizeof(CK_SP800_108_DKM_LENGTH_FORMAT)) { |
157 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
158 | 0 | } |
159 | | |
160 | 0 | CK_SP800_108_DKM_LENGTH_FORMAT_PTR param = (CK_SP800_108_DKM_LENGTH_FORMAT_PTR)data->pValue; |
161 | | |
162 | | /* Validate the method parameter. */ |
163 | 0 | if (param->dkmLengthMethod != CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS && |
164 | 0 | param->dkmLengthMethod != CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS) { |
165 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
166 | 0 | } |
167 | | |
168 | | /* Validate the endian parameter. */ |
169 | 0 | if (!VALID_CK_BOOL(param->bLittleEndian)) { |
170 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
171 | 0 | } |
172 | | |
173 | | /* Validate the maximum width: we restrict it to being a byte width |
174 | | * instead of a bit width due to restrictions by the underlying |
175 | | * PRFs. */ |
176 | 0 | if ((param->ulWidthInBits % 8) != 0) { |
177 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
178 | 0 | } |
179 | | |
180 | | /* Ensure that the width doesn't overflow a 64-bit int. This |
181 | | * restriction is arbitrary but since the counters can't exceed |
182 | | * 32-bits (and most PRFs output at most 1024 bits), you're unlikely |
183 | | * to need all 64-bits of length indicator. */ |
184 | 0 | if (param->ulWidthInBits > 64) { |
185 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
186 | 0 | } |
187 | 0 | break; |
188 | 0 | } |
189 | 0 | case CK_SP800_108_BYTE_ARRAY: |
190 | | /* There is no additional data to validate for byte arrays; we can |
191 | | * only assume the byte array is of the specified size. */ |
192 | 0 | break; |
193 | 0 | default: |
194 | | /* Unexpected parameter type. */ |
195 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
196 | 0 | } |
197 | | |
198 | 0 | return CKR_OK; |
199 | 0 | } |
200 | | |
201 | | static CK_RV |
202 | | kbkdf_ValidateDerived(CK_DERIVED_KEY_PTR key) |
203 | 0 | { |
204 | 0 | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
205 | 0 | PRUint64 keySize = 0; |
206 | | |
207 | | /* The pointer to the key handle shouldn't be NULL. If it is, we can't |
208 | | * do anything else, so exit early. Every other failure case sets the |
209 | | * key->phKey = CK_INVALID_HANDLE, so we can't use `goto failure` here. */ |
210 | 0 | if (key->phKey == NULL) { |
211 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
212 | 0 | } |
213 | | |
214 | | /* Validate that we have no attributes if and only if pTemplate is NULL. |
215 | | * Otherwise, there's an inconsistency somewhere. */ |
216 | 0 | if ((key->ulAttributeCount == 0) != (key->pTemplate == NULL)) { |
217 | 0 | goto failure; |
218 | 0 | } |
219 | | |
220 | 0 | for (size_t offset = 0; offset < key->ulAttributeCount; offset++) { |
221 | 0 | CK_ATTRIBUTE_PTR template = key->pTemplate + offset; |
222 | | |
223 | | /* We only look for the CKA_VALUE_LEN and CKA_KEY_TYPE attributes. |
224 | | * Everything else we assume we can set on the key if it is passed |
225 | | * here. However, if we can't inquire as to a length (and barring |
226 | | * that, if we have a key type without a standard length), we're |
227 | | * definitely stuck. This mirrors the logic at the top of |
228 | | * NSC_DeriveKey(...). */ |
229 | 0 | if (template->type == CKA_KEY_TYPE) { |
230 | 0 | if (template->ulValueLen != sizeof(CK_KEY_TYPE)) { |
231 | 0 | goto failure; |
232 | 0 | } |
233 | | |
234 | 0 | keyType = *(CK_KEY_TYPE *)template->pValue; |
235 | 0 | } else if (template->type == CKA_VALUE_LEN) { |
236 | 0 | if (template->ulValueLen != sizeof(CK_ULONG)) { |
237 | 0 | goto failure; |
238 | 0 | } |
239 | | |
240 | 0 | keySize = *(CK_ULONG *)template->pValue; |
241 | 0 | } |
242 | 0 | } |
243 | | |
244 | 0 | if (keySize == 0) { |
245 | | /* When we lack a keySize, see if we can infer it from the type of the |
246 | | * passed key. */ |
247 | 0 | keySize = sftk_MapKeySize(keyType); |
248 | 0 | } |
249 | | |
250 | | /* The main piece of information we validate is that we have a length for |
251 | | * this key. */ |
252 | 0 | if (keySize == 0 || keySize >= (1ull << 32ull)) { |
253 | 0 | goto failure; |
254 | 0 | } |
255 | | |
256 | 0 | return CKR_OK; |
257 | | |
258 | 0 | failure: |
259 | | /* PKCS#11 v3.0: If the failure was caused by the content of a specific |
260 | | * key's template (ie the template defined by the content of pTemplate), |
261 | | * the corresponding phKey value will be set to CK_INVALID_HANDLE to |
262 | | * identify the offending template. */ |
263 | 0 | *(key->phKey) = CK_INVALID_HANDLE; |
264 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
265 | 0 | } |
266 | | |
267 | | static PRBool |
268 | | kbkdf_ValidPRF(CK_SP800_108_PRF_TYPE prf) |
269 | 0 | { |
270 | | // See Table 161 of PKCS#11 v3.0 or Table 192 of PKCS#11 v3.1. |
271 | 0 | switch (prf) { |
272 | 0 | case CKM_AES_CMAC: |
273 | | /* case CKM_DES3_CMAC: */ |
274 | 0 | return PR_TRUE; |
275 | 0 | case CKM_SHA_1_HMAC: |
276 | 0 | case CKM_SHA224_HMAC: |
277 | 0 | case CKM_SHA256_HMAC: |
278 | 0 | case CKM_SHA384_HMAC: |
279 | 0 | case CKM_SHA512_HMAC: |
280 | 0 | case CKM_SHA3_224_HMAC: |
281 | 0 | case CKM_SHA3_256_HMAC: |
282 | 0 | case CKM_SHA3_384_HMAC: |
283 | 0 | case CKM_SHA3_512_HMAC: |
284 | | /* Valid HMAC <-> HASH isn't NULL */ |
285 | 0 | return sftk_HMACMechanismToHash(prf) != HASH_AlgNULL; |
286 | 0 | } |
287 | 0 | return PR_FALSE; |
288 | 0 | } |
289 | | |
290 | | static CK_RV |
291 | | kbkdf_ValidateParameters(CK_MECHANISM_TYPE mech, const CK_SP800_108_KDF_PARAMS *params, CK_ULONG keySize) |
292 | 0 | { |
293 | 0 | CK_RV ret = CKR_MECHANISM_PARAM_INVALID; |
294 | 0 | int param_type_count[5] = { 0, 0, 0, 0, 0 }; |
295 | 0 | size_t offset = 0; |
296 | | |
297 | | /* Start with checking the prfType as a mechanism against a list of |
298 | | * PRFs allowed by PKCS#11 v3.0. */ |
299 | 0 | if (!kbkdf_ValidPRF(params->prfType)) { |
300 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
301 | 0 | } |
302 | | |
303 | | /* We can't have a null pDataParams pointer: we always need at least one |
304 | | * parameter to succeed. */ |
305 | 0 | if (params->pDataParams == NULL) { |
306 | 0 | return CKR_HOST_MEMORY; |
307 | 0 | } |
308 | | |
309 | | /* Validate each KDF parameter. */ |
310 | 0 | for (offset = 0; offset < params->ulNumberOfDataParams; offset++) { |
311 | | /* Validate this parameter has acceptable values. */ |
312 | 0 | ret = kbkdf_ValidateParameter(mech, params->pDataParams + offset); |
313 | 0 | if (ret != CKR_OK) { |
314 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
315 | 0 | } |
316 | | |
317 | | /* Count that we have a parameter of this type. The above logic |
318 | | * in ValidateParameter MUST validate that type is within the |
319 | | * appropriate range. */ |
320 | 0 | PR_ASSERT(params->pDataParams[offset].type < sizeof(param_type_count) / sizeof(param_type_count[0])); |
321 | 0 | param_type_count[params->pDataParams[offset].type] += 1; |
322 | 0 | } |
323 | | |
324 | 0 | if (IS_COUNTER(mech)) { |
325 | | /* We have to have at least one iteration variable parameter. */ |
326 | 0 | if (param_type_count[CK_SP800_108_ITERATION_VARIABLE] == 0) { |
327 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
328 | 0 | } |
329 | | |
330 | | /* We can't have any optional counters parameters -- these belong in |
331 | | * iteration variable parameters instead. */ |
332 | 0 | if (param_type_count[CK_SP800_108_OPTIONAL_COUNTER] != 0) { |
333 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
334 | 0 | } |
335 | 0 | } |
336 | | |
337 | | /* Validate basic assumptions about derived keys: |
338 | | * NULL <-> ulAdditionalDerivedKeys > 0 |
339 | | */ |
340 | 0 | if ((params->ulAdditionalDerivedKeys == 0) != (params->pAdditionalDerivedKeys == NULL)) { |
341 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
342 | 0 | } |
343 | | |
344 | | /* Validate each derived key. */ |
345 | 0 | for (offset = 0; offset < params->ulAdditionalDerivedKeys; offset++) { |
346 | 0 | ret = kbkdf_ValidateDerived(params->pAdditionalDerivedKeys + offset); |
347 | 0 | if (ret != CKR_OK) { |
348 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
349 | 0 | } |
350 | 0 | } |
351 | | |
352 | | /* Validate the length of our primary key. */ |
353 | 0 | if (keySize == 0 || ((PRUint64)keySize) >= (1ull << 32ull)) { |
354 | 0 | return CKR_KEY_SIZE_RANGE; |
355 | 0 | } |
356 | | |
357 | 0 | return CKR_OK; |
358 | 0 | } |
359 | | |
360 | | /* [ section: parameter helpers ] */ |
361 | | |
362 | | static CK_VOID_PTR |
363 | | kbkdf_FindParameter(const CK_SP800_108_KDF_PARAMS *params, CK_PRF_DATA_TYPE type) |
364 | 0 | { |
365 | 0 | for (size_t offset = 0; offset < params->ulNumberOfDataParams; offset++) { |
366 | 0 | if (params->pDataParams[offset].type == type) { |
367 | 0 | return params->pDataParams[offset].pValue; |
368 | 0 | } |
369 | 0 | } |
370 | | |
371 | 0 | return NULL; |
372 | 0 | } |
373 | | |
374 | | size_t |
375 | | kbkdf_IncrementBuffer(size_t cur_offset, size_t consumed, size_t prf_length) |
376 | 0 | { |
377 | 0 | return cur_offset + PR_ROUNDUP(consumed, prf_length); |
378 | 0 | } |
379 | | |
380 | | CK_ULONG |
381 | | kbkdf_GetDerivedKeySize(CK_DERIVED_KEY_PTR derived_key) |
382 | 0 | { |
383 | | /* Precondition: kbkdf_ValidateDerived(...) returns CKR_OK for this key, |
384 | | * which implies that keySize is defined. */ |
385 | |
|
386 | 0 | CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
387 | 0 | CK_ULONG keySize = 0; |
388 | |
|
389 | 0 | for (size_t offset = 0; offset < derived_key->ulAttributeCount; offset++) { |
390 | 0 | CK_ATTRIBUTE_PTR template = derived_key->pTemplate + offset; |
391 | | |
392 | | /* Find the two attributes we care about. */ |
393 | 0 | if (template->type == CKA_KEY_TYPE) { |
394 | 0 | keyType = *(CK_KEY_TYPE *)template->pValue; |
395 | 0 | } else if (template->type == CKA_VALUE_LEN) { |
396 | 0 | keySize = *(CK_ULONG *)template->pValue; |
397 | 0 | } |
398 | 0 | } |
399 | | |
400 | | /* Prefer keySize, if we have it. */ |
401 | 0 | if (keySize > 0) { |
402 | 0 | return keySize; |
403 | 0 | } |
404 | | |
405 | | /* Else, fall back to this mapping. We know kbkdf_ValidateDerived(...) |
406 | | * passed, so this should return non-zero. */ |
407 | 0 | return sftk_MapKeySize(keyType); |
408 | 0 | } |
409 | | |
410 | | static CK_RV |
411 | | kbkdf_CalculateLength(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, CK_ULONG ret_key_size, PRUint64 *output_bitlen, size_t *buffer_length) |
412 | 0 | { |
413 | | /* Two cases: either we have additional derived keys or we don't. In the |
414 | | * case that we don't, the length of the derivation is the size of the |
415 | | * single derived key, and that is the length of the PRF buffer. Otherwise, |
416 | | * we need to use the proper CK_SP800_108_DKM_LENGTH_METHOD to calculate |
417 | | * the length of the output (in bits), with a separate value for the size |
418 | | * of the PRF data buffer. This means that, under PKCS#11 with additional |
419 | | * derived keys, we lie to the KDF about the _actual_ length of the PRF |
420 | | * output. |
421 | | * |
422 | | * Note that *output_bitlen is the L parameter in NIST SP800-108 and is in |
423 | | * bits. However, *buffer_length is in bytes. |
424 | | */ |
425 | |
|
426 | 0 | if (params->ulAdditionalDerivedKeys == 0) { |
427 | | /* When we have no additional derived keys, we get the keySize from |
428 | | * the value passed to one of our KBKDF_* methods. */ |
429 | 0 | *output_bitlen = ret_key_size; |
430 | 0 | *buffer_length = ret_key_size; |
431 | 0 | } else { |
432 | | /* Offset in the additional derived keys array. */ |
433 | 0 | size_t offset = 0; |
434 | | |
435 | | /* Size of the derived key. */ |
436 | 0 | CK_ULONG derived_size = 0; |
437 | | |
438 | | /* In the below, we place the sum of the keys into *output_bitlen |
439 | | * and the size of the buffer (with padding mandated by PKCS#11 v3.0) |
440 | | * into *buffer_length. If the method is the segment sum, then we |
441 | | * replace *output_bitlen with *buffer_length at the end. This ensures |
442 | | * we always get a output buffer large enough to handle all derived |
443 | | * keys, and *output_bitlen reflects the correct L value. */ |
444 | | |
445 | | /* Count the initial derived key. */ |
446 | 0 | *output_bitlen = ret_key_size; |
447 | 0 | *buffer_length = kbkdf_IncrementBuffer(0, ret_key_size, ctx->mac_size); |
448 | | |
449 | | /* Handle n - 1 keys. The last key is special. */ |
450 | 0 | for (; offset < params->ulAdditionalDerivedKeys - 1; offset++) { |
451 | 0 | derived_size = kbkdf_GetDerivedKeySize(params->pAdditionalDerivedKeys + offset); |
452 | |
|
453 | 0 | *output_bitlen += derived_size; |
454 | 0 | *buffer_length = kbkdf_IncrementBuffer(*buffer_length, derived_size, ctx->mac_size); |
455 | 0 | } |
456 | | |
457 | | /* Handle the last key. */ |
458 | 0 | derived_size = kbkdf_GetDerivedKeySize(params->pAdditionalDerivedKeys + offset); |
459 | |
|
460 | 0 | *output_bitlen += derived_size; |
461 | 0 | *buffer_length = kbkdf_IncrementBuffer(*buffer_length, derived_size, ctx->mac_size); |
462 | | |
463 | | /* Pointer to the DKM method parameter. Note that this implicit cast |
464 | | * is safe since we've assumed we've been validated by |
465 | | * kbkdf_ValidateParameters(...). When kdm_param is NULL, we don't |
466 | | * use the output_bitlen parameter. */ |
467 | 0 | CK_SP800_108_DKM_LENGTH_FORMAT_PTR dkm_param = kbkdf_FindParameter(params, CK_SP800_108_DKM_LENGTH); |
468 | 0 | if (dkm_param != NULL) { |
469 | 0 | if (dkm_param->dkmLengthMethod == CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS) { |
470 | 0 | *output_bitlen = *buffer_length; |
471 | 0 | } |
472 | 0 | } |
473 | 0 | } |
474 | | |
475 | | /* Note that keySize is the size in bytes and ctx->mac_size is also |
476 | | * the size in bytes. However, output_bitlen needs to be in bits, so |
477 | | * multiply by 8 here. */ |
478 | 0 | *output_bitlen *= 8; |
479 | |
|
480 | 0 | return CKR_OK; |
481 | 0 | } |
482 | | |
483 | | static CK_RV |
484 | | kbkdf_CalculateIterations(CK_MECHANISM_TYPE mech, const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, size_t buffer_length, PRUint32 *num_iterations) |
485 | 0 | { |
486 | 0 | CK_SP800_108_COUNTER_FORMAT_PTR param_ptr = NULL; |
487 | 0 | PRUint64 iteration_count; |
488 | 0 | PRUint64 r = 32; |
489 | | |
490 | | /* We need to know how many full iterations are required. This is done |
491 | | * by rounding up the division of the PRF length into buffer_length. |
492 | | * However, we're not guaranteed that the last output is a full PRF |
493 | | * invocation, so handle that here. */ |
494 | 0 | iteration_count = buffer_length + (ctx->mac_size - 1); |
495 | 0 | iteration_count = iteration_count / ctx->mac_size; |
496 | | |
497 | | /* NIST SP800-108, section 5.1, process step #2: |
498 | | * |
499 | | * if n > 2^r - 1, then indicate an error and stop. |
500 | | * |
501 | | * In non-counter mode KDFs, r is set at 32, leaving behavior |
502 | | * under-defined when the optional counter is included but fewer than |
503 | | * 32 bits. This implementation assumes r is 32, but if the counter |
504 | | * parameter is included, validates it against that. In counter-mode |
505 | | * KDFs, this is in the ITERATION_VARIABLE parameter; in feedback- or |
506 | | * pipeline-mode KDFs, this is in the COUNTER parameter. |
507 | | * |
508 | | * This is consistent with the supplied sample CAVP tests; none reuses the |
509 | | * same counter value. In some configurations, this could result in |
510 | | * duplicated KDF output. We seek to avoid that from happening. |
511 | | */ |
512 | 0 | if (IS_COUNTER(mech)) { |
513 | 0 | param_ptr = kbkdf_FindParameter(params, CK_SP800_108_ITERATION_VARIABLE); |
514 | | |
515 | | /* Validated by kbkdf_ValidateParameters(...) above. */ |
516 | 0 | PR_ASSERT(param_ptr != NULL); |
517 | |
|
518 | 0 | r = ((CK_SP800_108_COUNTER_FORMAT_PTR)param_ptr)->ulWidthInBits; |
519 | 0 | } else { |
520 | 0 | param_ptr = kbkdf_FindParameter(params, CK_SP800_108_COUNTER); |
521 | | |
522 | | /* Not guaranteed to exist, hence the default value of r=32. */ |
523 | 0 | if (param_ptr != NULL) { |
524 | 0 | r = ((CK_SP800_108_COUNTER_FORMAT_PTR)param_ptr)->ulWidthInBits; |
525 | 0 | } |
526 | 0 | } |
527 | |
|
528 | 0 | if (iteration_count >= (1ull << r) || r > 32) { |
529 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
530 | 0 | } |
531 | | |
532 | 0 | *num_iterations = (PRUint32)iteration_count; |
533 | |
|
534 | 0 | return CKR_OK; |
535 | 0 | } |
536 | | |
537 | | static CK_RV |
538 | | kbkdf_AddParameters(CK_MECHANISM_TYPE mech, sftk_MACCtx *ctx, const CK_SP800_108_KDF_PARAMS *params, PRUint32 counter, PRUint64 length, const unsigned char *chaining_prf, size_t chaining_prf_len, CK_PRF_DATA_TYPE exclude) |
539 | 0 | { |
540 | 0 | size_t offset = 0; |
541 | 0 | CK_RV ret = CKR_OK; |
542 | |
|
543 | 0 | for (offset = 0; offset < params->ulNumberOfDataParams; offset++) { |
544 | 0 | CK_PRF_DATA_PARAM_PTR param = params->pDataParams + offset; |
545 | |
|
546 | 0 | if (param->type == exclude) { |
547 | | /* Necessary for Double Pipeline mode: when constructing the IV, |
548 | | * we skip the optional counter. */ |
549 | 0 | continue; |
550 | 0 | } |
551 | | |
552 | 0 | switch (param->type) { |
553 | 0 | case CK_SP800_108_ITERATION_VARIABLE: { |
554 | | /* When present in COUNTER mode, this signifies adding the counter |
555 | | * variable to the PRF. Otherwise, it signifies the chaining |
556 | | * value for other KDF modes. */ |
557 | 0 | if (IS_COUNTER(mech)) { |
558 | 0 | CK_SP800_108_COUNTER_FORMAT_PTR counter_format = (CK_SP800_108_COUNTER_FORMAT_PTR)param->pValue; |
559 | 0 | CK_BYTE buffer[sizeof(PRUint64)]; |
560 | 0 | CK_ULONG num_bytes; |
561 | 0 | sftk_EncodeInteger(counter, counter_format->ulWidthInBits, counter_format->bLittleEndian, buffer, &num_bytes); |
562 | 0 | ret = sftk_MAC_Update(ctx, buffer, num_bytes); |
563 | 0 | } else { |
564 | 0 | ret = sftk_MAC_Update(ctx, chaining_prf, chaining_prf_len); |
565 | 0 | } |
566 | 0 | break; |
567 | 0 | } |
568 | 0 | case CK_SP800_108_COUNTER: { |
569 | | /* Only present in the case when not using COUNTER mode. */ |
570 | 0 | PR_ASSERT(!IS_COUNTER(mech)); |
571 | | |
572 | | /* We should've already validated that this parameter is of |
573 | | * type COUNTER_FORMAT. */ |
574 | 0 | CK_SP800_108_COUNTER_FORMAT_PTR counter_format = (CK_SP800_108_COUNTER_FORMAT_PTR)param->pValue; |
575 | 0 | CK_BYTE buffer[sizeof(PRUint64)]; |
576 | 0 | CK_ULONG num_bytes; |
577 | 0 | sftk_EncodeInteger(counter, counter_format->ulWidthInBits, counter_format->bLittleEndian, buffer, &num_bytes); |
578 | 0 | ret = sftk_MAC_Update(ctx, buffer, num_bytes); |
579 | 0 | break; |
580 | 0 | } |
581 | 0 | case CK_SP800_108_BYTE_ARRAY: |
582 | 0 | ret = sftk_MAC_Update(ctx, (CK_BYTE_PTR)param->pValue, param->ulValueLen); |
583 | 0 | break; |
584 | 0 | case CK_SP800_108_DKM_LENGTH: { |
585 | | /* We've already done the hard work of calculating the length in |
586 | | * the kbkdf_CalculateIterations function; we merely need to add |
587 | | * the length to the desired point in the input stream. */ |
588 | 0 | CK_SP800_108_DKM_LENGTH_FORMAT_PTR length_format = (CK_SP800_108_DKM_LENGTH_FORMAT_PTR)param->pValue; |
589 | 0 | CK_BYTE buffer[sizeof(PRUint64)]; |
590 | 0 | CK_ULONG num_bytes; |
591 | 0 | sftk_EncodeInteger(length, length_format->ulWidthInBits, length_format->bLittleEndian, buffer, &num_bytes); |
592 | 0 | ret = sftk_MAC_Update(ctx, buffer, num_bytes); |
593 | 0 | break; |
594 | 0 | } |
595 | 0 | default: |
596 | | /* This should've been caught by kbkdf_ValidateParameters(...). */ |
597 | 0 | PR_ASSERT(PR_FALSE); |
598 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
599 | 0 | } |
600 | | |
601 | 0 | if (ret != CKR_OK) { |
602 | 0 | return ret; |
603 | 0 | } |
604 | 0 | } |
605 | | |
606 | 0 | return CKR_OK; |
607 | 0 | } |
608 | | |
609 | | CK_RV |
610 | | kbkdf_SaveKey(SFTKObject *key, unsigned char *key_buffer, unsigned int key_len) |
611 | 0 | { |
612 | 0 | return sftk_forceAttribute(key, CKA_VALUE, key_buffer, key_len); |
613 | 0 | } |
614 | | |
615 | | CK_RV |
616 | | kbkdf_CreateKey(CK_MECHANISM_TYPE kdf_mech, CK_SESSION_HANDLE hSession, CK_DERIVED_KEY_PTR derived_key, SFTKObject **ret_key) |
617 | 0 | { |
618 | | /* Largely duplicated from NSC_DeriveKey(...) */ |
619 | 0 | CK_RV ret = CKR_HOST_MEMORY; |
620 | 0 | SFTKObject *key = NULL; |
621 | 0 | SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); |
622 | 0 | size_t offset = 0; |
623 | | |
624 | | /* Slot should be non-NULL because NSC_DeriveKey(...) has already |
625 | | * performed a sftk_SlotFromSessionHandle(...) call on this session |
626 | | * handle. However, Coverity incorrectly flagged this (see 1607955). */ |
627 | 0 | PR_ASSERT(slot != NULL); |
628 | 0 | PR_ASSERT(ret_key != NULL); |
629 | 0 | PR_ASSERT(derived_key != NULL); |
630 | 0 | PR_ASSERT(derived_key->phKey != NULL); |
631 | |
|
632 | 0 | if (slot == NULL) { |
633 | 0 | return CKR_SESSION_HANDLE_INVALID; |
634 | 0 | } |
635 | | |
636 | | /* Create the new key object for this additional derived key. */ |
637 | 0 | key = sftk_NewObject(slot); |
638 | 0 | if (key == NULL) { |
639 | 0 | return CKR_HOST_MEMORY; |
640 | 0 | } |
641 | | |
642 | | /* Setup the key from the provided template. */ |
643 | 0 | for (offset = 0; offset < derived_key->ulAttributeCount; offset++) { |
644 | 0 | ret = sftk_AddAttributeType(key, sftk_attr_expand(derived_key->pTemplate + offset)); |
645 | 0 | if (ret != CKR_OK) { |
646 | 0 | sftk_FreeObject(key); |
647 | 0 | return ret; |
648 | 0 | } |
649 | 0 | } |
650 | | |
651 | | /* When using the CKM_SP800_* series of mechanisms, the result must be a |
652 | | * secret key, so its contents can be adequately protected in FIPS mode. |
653 | | * However, when using the special CKM_NSS_SP800_*_DERIVE_DATA series, the |
654 | | * contents need not be protected, so we set CKO_DATA on these "keys". */ |
655 | 0 | CK_OBJECT_CLASS classType = CKO_SECRET_KEY; |
656 | 0 | if (DOES_DERIVE_DATA(kdf_mech)) { |
657 | 0 | classType = CKO_DATA; |
658 | 0 | } |
659 | |
|
660 | 0 | ret = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType)); |
661 | 0 | if (ret != CKR_OK) { |
662 | 0 | sftk_FreeObject(key); |
663 | 0 | return ret; |
664 | 0 | } |
665 | | |
666 | 0 | *ret_key = key; |
667 | 0 | return CKR_OK; |
668 | 0 | } |
669 | | |
670 | | CK_RV |
671 | | kbkdf_FinalizeKey(CK_SESSION_HANDLE hSession, CK_DERIVED_KEY_PTR derived_key, SFTKObject *key) |
672 | 0 | { |
673 | | /* Largely duplicated from NSC_DeriveKey(...) */ |
674 | 0 | CK_RV ret = CKR_HOST_MEMORY; |
675 | 0 | SFTKSession *session = NULL; |
676 | |
|
677 | 0 | PR_ASSERT(derived_key != NULL && key != NULL); |
678 | |
|
679 | 0 | SFTKSessionObject *sessionForKey = sftk_narrowToSessionObject(key); |
680 | 0 | PR_ASSERT(sessionForKey != NULL); |
681 | 0 | sessionForKey->wasDerived = PR_TRUE; |
682 | |
|
683 | 0 | session = sftk_SessionFromHandle(hSession); |
684 | | |
685 | | /* Session should be non-NULL because NSC_DeriveKey(...) has already |
686 | | * performed a sftk_SessionFromHandle(...) call on this session handle. */ |
687 | 0 | PR_ASSERT(session != NULL); |
688 | |
|
689 | 0 | ret = sftk_handleObject(key, session); |
690 | 0 | if (ret != CKR_OK) { |
691 | 0 | goto done; |
692 | 0 | } |
693 | | |
694 | 0 | *(derived_key->phKey) = key->handle; |
695 | |
|
696 | 0 | done: |
697 | | /* Guaranteed that key != NULL */ |
698 | 0 | sftk_FreeObject(key); |
699 | | |
700 | | /* Doesn't do anything. */ |
701 | 0 | if (session) { |
702 | 0 | sftk_FreeSession(session); |
703 | 0 | } |
704 | |
|
705 | 0 | return ret; |
706 | 0 | } |
707 | | |
708 | | CK_RV |
709 | | kbkdf_SaveKeys(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_SP800_108_KDF_PARAMS_PTR params, unsigned char *output_buffer, size_t buffer_len, size_t prf_length, SFTKObject *ret_key, CK_ULONG ret_key_size) |
710 | 0 | { |
711 | 0 | CK_RV ret; |
712 | 0 | size_t key_offset = 0; |
713 | 0 | size_t buffer_offset = 0; |
714 | |
|
715 | 0 | PR_ASSERT(output_buffer != NULL && buffer_len > 0 && ret_key != NULL); |
716 | | |
717 | | /* First place key material into the main key. */ |
718 | 0 | ret = kbkdf_SaveKey(ret_key, output_buffer + buffer_offset, ret_key_size); |
719 | 0 | if (ret != CKR_OK) { |
720 | 0 | return ret; |
721 | 0 | } |
722 | | |
723 | | /* Then increment the offset based on PKCS#11 additional key guidelines: |
724 | | * no two keys may share the key stream from the same PRF invocation. */ |
725 | 0 | buffer_offset = kbkdf_IncrementBuffer(buffer_offset, ret_key_size, prf_length); |
726 | |
|
727 | 0 | if (params->ulAdditionalDerivedKeys > 0) { |
728 | | /* Note that the following code is technically incorrect: PKCS#11 v3.0 |
729 | | * says that _no_ key should be set in the event of failure to derive |
730 | | * _any_ key. */ |
731 | 0 | for (key_offset = 0; key_offset < params->ulAdditionalDerivedKeys; key_offset++) { |
732 | 0 | CK_DERIVED_KEY_PTR derived_key = params->pAdditionalDerivedKeys + key_offset; |
733 | 0 | SFTKObject *key_obj = NULL; |
734 | 0 | size_t key_size = kbkdf_GetDerivedKeySize(derived_key); |
735 | | |
736 | | /* Create a new internal key object for this derived key. */ |
737 | 0 | ret = kbkdf_CreateKey(mech, hSession, derived_key, &key_obj); |
738 | 0 | if (ret != CKR_OK) { |
739 | 0 | *(derived_key->phKey) = CK_INVALID_HANDLE; |
740 | 0 | return ret; |
741 | 0 | } |
742 | | |
743 | | /* Save the underlying key bytes to the key object. */ |
744 | 0 | ret = kbkdf_SaveKey(key_obj, output_buffer + buffer_offset, key_size); |
745 | 0 | if (ret != CKR_OK) { |
746 | | /* When kbkdf_CreateKey(...) exits with an error, it will free |
747 | | * the constructed key object. kbkdf_FinalizeKey(...) also |
748 | | * always frees the key object. In the unlikely event that |
749 | | * kbkdf_SaveKey(...) _does_ fail, we thus need to free it |
750 | | * manually. */ |
751 | 0 | sftk_FreeObject(key_obj); |
752 | 0 | *(derived_key->phKey) = CK_INVALID_HANDLE; |
753 | 0 | return ret; |
754 | 0 | } |
755 | | |
756 | | /* Handle the increment. */ |
757 | 0 | buffer_offset = kbkdf_IncrementBuffer(buffer_offset, key_size, prf_length); |
758 | | |
759 | | /* Finalize this key. */ |
760 | 0 | ret = kbkdf_FinalizeKey(hSession, derived_key, key_obj); |
761 | 0 | if (ret != CKR_OK) { |
762 | 0 | *(derived_key->phKey) = CK_INVALID_HANDLE; |
763 | 0 | return ret; |
764 | 0 | } |
765 | 0 | } |
766 | 0 | } |
767 | | |
768 | 0 | return CKR_OK; |
769 | 0 | } |
770 | | |
771 | | /* [ section: KDFs ] */ |
772 | | |
773 | | static CK_RV |
774 | | kbkdf_CounterRaw(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen) |
775 | 0 | { |
776 | 0 | CK_RV ret = CKR_OK; |
777 | | |
778 | | /* Counter variable for this KDF instance. */ |
779 | 0 | PRUint32 counter; |
780 | | |
781 | | /* Number of iterations required of this PRF necessary to reach the |
782 | | * desired output length. */ |
783 | 0 | PRUint32 num_iterations; |
784 | | |
785 | | /* Offset in ret_buffer that we're at. */ |
786 | 0 | size_t buffer_offset = 0; |
787 | | |
788 | | /* Size of this block, in bytes. Defaults to ctx->mac_size except on |
789 | | * the last iteration where it could be a partial block. */ |
790 | 0 | size_t block_size = ctx->mac_size; |
791 | | |
792 | | /* Calculate the number of iterations required based on the size of the |
793 | | * output buffer. */ |
794 | 0 | ret = kbkdf_CalculateIterations(CKM_SP800_108_COUNTER_KDF, params, ctx, buffer_length, &num_iterations); |
795 | 0 | if (ret != CKR_OK) { |
796 | 0 | return ret; |
797 | 0 | } |
798 | | |
799 | | /* |
800 | | * 5.1 - [ KDF in Counter Mode ] |
801 | | * |
802 | | * Fixed values: |
803 | | * 1. h - the length of the PRF in bits (ctx->mac_size) |
804 | | * 2. r - the length of the binary representation of the counter i |
805 | | * (params[k: params[k].type == CK_SP800_108_ITERATION_VARIABLE:].data->ulWidthInBits) |
806 | | * Input: |
807 | | * 1. K_I - the key for the PRF (base_key) |
808 | | * 2. label - a binary data field, usually before the separator. Optional. |
809 | | * 3. context - a binary data field, usually after the separator. Optional. |
810 | | * 4. L - length of the output in bits (output_bitlen) |
811 | | * |
812 | | * Process: |
813 | | * 1. n := ceil(L / h) (num_iterations) |
814 | | * 2. if n > 2^r - 1, then indicate an error and stop |
815 | | * 3. result(0) = NULL |
816 | | * 4. for i = 1 to n, do |
817 | | * a. K(i) = PRF(K_I, [i]_2 || Label || 0x00 || Context || [L]_2) |
818 | | * b. result(i) := result(i - 1) || K(i). |
819 | | * 5. return K_O := the leftmost L bits of result(n). |
820 | | */ |
821 | 0 | for (counter = 1; counter <= num_iterations; counter++) { |
822 | 0 | if (counter == num_iterations) { |
823 | 0 | block_size = buffer_length - buffer_offset; |
824 | | |
825 | | /* Assumption: if we've validated our arguments correctly, this |
826 | | * should always be true. */ |
827 | 0 | PR_ASSERT(block_size <= ctx->mac_size); |
828 | 0 | } |
829 | | |
830 | | /* Add all parameters required by this instance of the KDF to the |
831 | | * input stream of the underlying PRF. */ |
832 | 0 | ret = kbkdf_AddParameters(CKM_SP800_108_COUNTER_KDF, ctx, params, counter, output_bitlen, NULL, 0 /* chaining_prf output */, 0 /* exclude */); |
833 | 0 | if (ret != CKR_OK) { |
834 | 0 | return ret; |
835 | 0 | } |
836 | | |
837 | | /* Finalize this iteration of the PRF. */ |
838 | 0 | ret = sftk_MAC_End(ctx, ret_buffer + buffer_offset, NULL, block_size); |
839 | 0 | if (ret != CKR_OK) { |
840 | 0 | return ret; |
841 | 0 | } |
842 | | |
843 | | /* Increment our position in the key material. */ |
844 | 0 | buffer_offset += block_size; |
845 | |
|
846 | 0 | if (counter < num_iterations) { |
847 | | /* Reset the underlying PRF for the next iteration. Only do this |
848 | | * when we have a next iteration since it isn't necessary to do |
849 | | * either before the first iteration (MAC is already initialized) |
850 | | * or after the last iteration (we won't be called again). */ |
851 | 0 | ret = sftk_MAC_Reset(ctx); |
852 | 0 | if (ret != CKR_OK) { |
853 | 0 | return ret; |
854 | 0 | } |
855 | 0 | } |
856 | 0 | } |
857 | | |
858 | 0 | return CKR_OK; |
859 | 0 | } |
860 | | |
861 | | static CK_RV |
862 | | kbkdf_FeedbackRaw(const CK_SP800_108_KDF_PARAMS *params, const unsigned char *initial_value, CK_ULONG initial_value_length, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen) |
863 | 0 | { |
864 | 0 | CK_RV ret = CKR_OK; |
865 | | |
866 | | /* Counter variable for this KDF instance. */ |
867 | 0 | PRUint32 counter; |
868 | | |
869 | | /* Number of iterations required of this PRF necessary to reach the |
870 | | * desired output length. */ |
871 | 0 | PRUint32 num_iterations; |
872 | | |
873 | | /* Offset in ret_buffer that we're at. */ |
874 | 0 | size_t buffer_offset = 0; |
875 | | |
876 | | /* Size of this block, in bytes. Defaults to ctx->mac_size except on |
877 | | * the last iteration where it could be a partial block. */ |
878 | 0 | size_t block_size = ctx->mac_size; |
879 | | |
880 | | /* The last PRF invocation and/or the initial value; used for feedback |
881 | | * chaining in this KDF. Note that we have to make it large enough to |
882 | | * fit the output of the PRF, but we can delay its actual creation until |
883 | | * the first PRF invocation. Until then, point to the IV value. */ |
884 | 0 | unsigned char *chaining_value = (unsigned char *)initial_value; |
885 | | |
886 | | /* Size of the chaining value discussed above. Defaults to the size of |
887 | | * the IV value. */ |
888 | 0 | size_t chaining_length = initial_value_length; |
889 | | |
890 | | /* Calculate the number of iterations required based on the size of the |
891 | | * output buffer. */ |
892 | 0 | ret = kbkdf_CalculateIterations(CKM_SP800_108_FEEDBACK_KDF, params, ctx, buffer_length, &num_iterations); |
893 | 0 | if (ret != CKR_OK) { |
894 | 0 | goto finish; |
895 | 0 | } |
896 | | |
897 | | /* |
898 | | * 5.2 - [ KDF in Feedback Mode ] |
899 | | * |
900 | | * Fixed values: |
901 | | * 1. h - the length of the PRF in bits (ctx->mac_size) |
902 | | * 2. r - the length of the binary representation of the counter i |
903 | | * (params[k: params[k].type == CK_SP800_108_OPTIONAL_COUNTER:].data->ulWidthInBits) |
904 | | * Note that it is only specified when the optional counter is requested. |
905 | | * Input: |
906 | | * 1. K_I - the key for the PRF (base_key) |
907 | | * 2. label - a binary data field, usually before the separator. Optional. |
908 | | * 3. context - a binary data field, usually after the separator. Optional. |
909 | | * 4. IV - a binary data field, initial PRF value. (params->pIV) |
910 | | * 5. L - length of the output in bits (output_bitlen) |
911 | | * |
912 | | * Process: |
913 | | * 1. n := ceil(L / h) (num_iterations) |
914 | | * 2. if n > 2^32 - 1, then indicate an error and stop |
915 | | * 3. result(0) = NULL, K(0) := IV (chaining_value) |
916 | | * 4. for i = 1 to n, do |
917 | | * a. K(i) = PRF(K_I, K(i-1) {|| [i]_2} || Label || 0x00 || Context || [L]_2) |
918 | | * b. result(i) := result(i - 1) || K(i). |
919 | | * 5. return K_O := the leftmost L bits of result(n). |
920 | | */ |
921 | 0 | for (counter = 1; counter <= num_iterations; counter++) { |
922 | 0 | if (counter == num_iterations) { |
923 | 0 | block_size = buffer_length - buffer_offset; |
924 | | |
925 | | /* Assumption: if we've validated our arguments correctly, this |
926 | | * should always be true. */ |
927 | 0 | PR_ASSERT(block_size <= ctx->mac_size); |
928 | 0 | } |
929 | | |
930 | | /* Add all parameters required by this instance of the KDF to the |
931 | | * input stream of the underlying PRF. */ |
932 | 0 | ret = kbkdf_AddParameters(CKM_SP800_108_FEEDBACK_KDF, ctx, params, counter, output_bitlen, chaining_value, chaining_length, 0 /* exclude */); |
933 | 0 | if (ret != CKR_OK) { |
934 | 0 | goto finish; |
935 | 0 | } |
936 | | |
937 | 0 | if (counter == 1) { |
938 | | /* On the first iteration, chaining_value points to the IV from |
939 | | * the caller and chaining_length is the length of that IV. We |
940 | | * now need to allocate a buffer of suitable length to store the |
941 | | * MAC output. */ |
942 | 0 | chaining_value = PORT_ZNewArray(unsigned char, ctx->mac_size); |
943 | 0 | chaining_length = ctx->mac_size; |
944 | |
|
945 | 0 | if (chaining_value == NULL) { |
946 | 0 | ret = CKR_HOST_MEMORY; |
947 | 0 | goto finish; |
948 | 0 | } |
949 | 0 | } |
950 | | |
951 | | /* Finalize this iteration of the PRF. Unlike other KDF forms, we |
952 | | * first save this to the chaining value so that we can reuse it |
953 | | * in the next iteration before copying the necessary length to |
954 | | * the output buffer. */ |
955 | 0 | ret = sftk_MAC_End(ctx, chaining_value, NULL, chaining_length); |
956 | 0 | if (ret != CKR_OK) { |
957 | 0 | goto finish; |
958 | 0 | } |
959 | | |
960 | | /* Save as much of the chaining value as we need for output. */ |
961 | 0 | PORT_Memcpy(ret_buffer + buffer_offset, chaining_value, block_size); |
962 | | |
963 | | /* Increment our position in the key material. */ |
964 | 0 | buffer_offset += block_size; |
965 | |
|
966 | 0 | if (counter < num_iterations) { |
967 | | /* Reset the underlying PRF for the next iteration. Only do this |
968 | | * when we have a next iteration since it isn't necessary to do |
969 | | * either before the first iteration (MAC is already initialized) |
970 | | * or after the last iteration (we won't be called again). */ |
971 | 0 | ret = sftk_MAC_Reset(ctx); |
972 | 0 | if (ret != CKR_OK) { |
973 | 0 | goto finish; |
974 | 0 | } |
975 | 0 | } |
976 | 0 | } |
977 | | |
978 | 0 | finish: |
979 | 0 | if (chaining_value != initial_value && chaining_value != NULL) { |
980 | 0 | PORT_ZFree(chaining_value, chaining_length); |
981 | 0 | } |
982 | |
|
983 | 0 | return ret; |
984 | 0 | } |
985 | | |
986 | | static CK_RV |
987 | | kbkdf_PipelineRaw(const CK_SP800_108_KDF_PARAMS *params, sftk_MACCtx *ctx, unsigned char *ret_buffer, size_t buffer_length, PRUint64 output_bitlen) |
988 | 0 | { |
989 | 0 | CK_RV ret = CKR_OK; |
990 | | |
991 | | /* Counter variable for this KDF instance. */ |
992 | 0 | PRUint32 counter; |
993 | | |
994 | | /* Number of iterations required of this PRF necessary to reach the |
995 | | * desired output length. */ |
996 | 0 | PRUint32 num_iterations; |
997 | | |
998 | | /* Offset in ret_buffer that we're at. */ |
999 | 0 | size_t buffer_offset = 0; |
1000 | | |
1001 | | /* Size of this block, in bytes. Defaults to ctx->mac_size except on |
1002 | | * the last iteration where it could be a partial block. */ |
1003 | 0 | size_t block_size = ctx->mac_size; |
1004 | | |
1005 | | /* The last PRF invocation. This is used for the first of the double |
1006 | | * PRF invocations this KDF is named after. This defaults to NULL, |
1007 | | * signifying that we have to calculate the initial value from params; |
1008 | | * when non-NULL, we directly add only this value to the PRF. */ |
1009 | 0 | unsigned char *chaining_value = NULL; |
1010 | | |
1011 | | /* Size of the chaining value discussed above. Defaults to 0. */ |
1012 | 0 | size_t chaining_length = 0; |
1013 | | |
1014 | | /* Calculate the number of iterations required based on the size of the |
1015 | | * output buffer. */ |
1016 | 0 | ret = kbkdf_CalculateIterations(CKM_SP800_108_DOUBLE_PIPELINE_KDF, params, ctx, buffer_length, &num_iterations); |
1017 | 0 | if (ret != CKR_OK) { |
1018 | 0 | goto finish; |
1019 | 0 | } |
1020 | | |
1021 | | /* |
1022 | | * 5.3 - [ KDF in Double-Pipeline Iteration Mode ] |
1023 | | * |
1024 | | * Fixed values: |
1025 | | * 1. h - the length of the PRF in bits (ctx->mac_size) |
1026 | | * 2. r - the length of the binary representation of the counter i |
1027 | | * (params[k: params[k].type == CK_SP800_108_OPTIONAL_COUNTER:].data->ulWidthInBits) |
1028 | | * Note that it is only specified when the optional counter is requested. |
1029 | | * Input: |
1030 | | * 1. K_I - the key for the PRF (base_key) |
1031 | | * 2. label - a binary data field, usually before the separator. Optional. |
1032 | | * 3. context - a binary data field, usually after the separator. Optional. |
1033 | | * 4. L - length of the output in bits (output_bitlen) |
1034 | | * |
1035 | | * Process: |
1036 | | * 1. n := ceil(L / h) (num_iterations) |
1037 | | * 2. if n > 2^32 - 1, then indicate an error and stop |
1038 | | * 3. result(0) = NULL |
1039 | | * 4. A(0) := IV := Label || 0x00 || Context || [L]_2 |
1040 | | * 5. for i = 1 to n, do |
1041 | | * a. A(i) := PRF(K_I, A(i-1)) |
1042 | | * b. K(i) := PRF(K_I, A(i) {|| [i]_2} || Label || 0x00 || Context || [L]_2 |
1043 | | * c. result(i) := result(i-1) || K(i) |
1044 | | * 6. return K_O := the leftmost L bits of result(n). |
1045 | | */ |
1046 | 0 | for (counter = 1; counter <= num_iterations; counter++) { |
1047 | 0 | if (counter == num_iterations) { |
1048 | 0 | block_size = buffer_length - buffer_offset; |
1049 | | |
1050 | | /* Assumption: if we've validated our arguments correctly, this |
1051 | | * should always be true. */ |
1052 | 0 | PR_ASSERT(block_size <= ctx->mac_size); |
1053 | 0 | } |
1054 | | |
1055 | | /* ===== First pipeline: construct A(i) ===== */ |
1056 | 0 | if (counter == 1) { |
1057 | | /* On the first iteration, we have no chaining value so specify |
1058 | | * NULL for the pointer and 0 for the length, and exclude the |
1059 | | * optional counter if it exists. This is what NIST specifies as |
1060 | | * the IV for the KDF. */ |
1061 | 0 | ret = kbkdf_AddParameters(CKM_SP800_108_DOUBLE_PIPELINE_KDF, ctx, params, counter, output_bitlen, NULL, 0, CK_SP800_108_OPTIONAL_COUNTER); |
1062 | 0 | if (ret != CKR_OK) { |
1063 | 0 | goto finish; |
1064 | 0 | } |
1065 | | |
1066 | | /* Allocate the chaining value so we can save the PRF output. */ |
1067 | 0 | chaining_value = PORT_ZNewArray(unsigned char, ctx->mac_size); |
1068 | 0 | chaining_length = ctx->mac_size; |
1069 | 0 | if (chaining_value == NULL) { |
1070 | 0 | ret = CKR_HOST_MEMORY; |
1071 | 0 | goto finish; |
1072 | 0 | } |
1073 | 0 | } else { |
1074 | | /* On all other iterations, the next stage of the first pipeline |
1075 | | * comes directly from this stage. */ |
1076 | 0 | ret = sftk_MAC_Update(ctx, chaining_value, chaining_length); |
1077 | 0 | if (ret != CKR_OK) { |
1078 | 0 | goto finish; |
1079 | 0 | } |
1080 | 0 | } |
1081 | | |
1082 | | /* Save the PRF output to chaining_value for use in the second |
1083 | | * pipeline. */ |
1084 | 0 | ret = sftk_MAC_End(ctx, chaining_value, NULL, chaining_length); |
1085 | 0 | if (ret != CKR_OK) { |
1086 | 0 | goto finish; |
1087 | 0 | } |
1088 | | |
1089 | | /* Reset the PRF so we can reuse it for the second pipeline. */ |
1090 | 0 | ret = sftk_MAC_Reset(ctx); |
1091 | 0 | if (ret != CKR_OK) { |
1092 | 0 | goto finish; |
1093 | 0 | } |
1094 | | |
1095 | | /* ===== Second pipeline: construct K(i) ===== */ |
1096 | | |
1097 | | /* Add all parameters required by this instance of the KDF to the |
1098 | | * input stream of the underlying PRF. Note that this includes the |
1099 | | * chaining value we calculated from the previous pipeline stage. */ |
1100 | 0 | ret = kbkdf_AddParameters(CKM_SP800_108_FEEDBACK_KDF, ctx, params, counter, output_bitlen, chaining_value, chaining_length, 0 /* exclude */); |
1101 | 0 | if (ret != CKR_OK) { |
1102 | 0 | goto finish; |
1103 | 0 | } |
1104 | | |
1105 | | /* Finalize this iteration of the PRF directly to the output buffer. |
1106 | | * Unlike Feedback mode, this pipeline doesn't influence the previous |
1107 | | * stage. */ |
1108 | 0 | ret = sftk_MAC_End(ctx, ret_buffer + buffer_offset, NULL, block_size); |
1109 | 0 | if (ret != CKR_OK) { |
1110 | 0 | goto finish; |
1111 | 0 | } |
1112 | | |
1113 | | /* Increment our position in the key material. */ |
1114 | 0 | buffer_offset += block_size; |
1115 | |
|
1116 | 0 | if (counter < num_iterations) { |
1117 | | /* Reset the underlying PRF for the next iteration. Only do this |
1118 | | * when we have a next iteration since it isn't necessary to do |
1119 | | * either before the first iteration (MAC is already initialized) |
1120 | | * or after the last iteration (we won't be called again). */ |
1121 | 0 | ret = sftk_MAC_Reset(ctx); |
1122 | 0 | if (ret != CKR_OK) { |
1123 | 0 | goto finish; |
1124 | 0 | } |
1125 | 0 | } |
1126 | 0 | } |
1127 | | |
1128 | 0 | finish: |
1129 | 0 | PORT_ZFree(chaining_value, chaining_length); |
1130 | |
|
1131 | 0 | return ret; |
1132 | 0 | } |
1133 | | |
1134 | | static CK_RV |
1135 | | kbkdf_RawDispatch(CK_MECHANISM_TYPE mech, |
1136 | | const CK_SP800_108_KDF_PARAMS *kdf_params, |
1137 | | const CK_BYTE *initial_value, |
1138 | | CK_ULONG initial_value_length, |
1139 | | SFTKObject *prf_key, const unsigned char *prf_key_bytes, |
1140 | | unsigned int prf_key_length, unsigned char **out_key_bytes, |
1141 | | size_t *out_key_length, unsigned int *mac_size, |
1142 | | CK_ULONG ret_key_size) |
1143 | 0 | { |
1144 | 0 | CK_RV ret; |
1145 | | /* Context for our underlying PRF function. |
1146 | | * |
1147 | | * Zeroing context required unconditional call of sftk_MAC_DestroyContext. |
1148 | | */ |
1149 | 0 | sftk_MACCtx ctx = { 0 }; |
1150 | | |
1151 | | /* We need one buffers large enough to fit the entire KDF key stream for |
1152 | | * all iterations of the PRF. This needs only include to the end of the |
1153 | | * last key, so it isn't an even multiple of the PRF output size. */ |
1154 | 0 | unsigned char *output_buffer = NULL; |
1155 | | |
1156 | | /* Size of the above buffer, in bytes. Note that this is technically |
1157 | | * separate from the below output_bitlen variable due to the presence |
1158 | | * of additional derived keys. See commentary in kbkdf_CalculateLength. |
1159 | | */ |
1160 | 0 | size_t buffer_length = 0; |
1161 | | |
1162 | | /* While NIST specifies a maximum length (in bits) for the counter, they |
1163 | | * don't for the maximum length. It is unlikely, but theoretically |
1164 | | * possible for output of the PRF to exceed 32 bits while keeping the |
1165 | | * counter under 2^32. Thus, use a 64-bit variable for the maximum |
1166 | | * output length. |
1167 | | * |
1168 | | * It is unlikely any caller will request this much data in practice. |
1169 | | * 2^32 invocations of the PRF (for a 512-bit PRF) would be 256GB of |
1170 | | * data in the KDF key stream alone. The bigger limit is the number of |
1171 | | * and size of keys (again, 2^32); this could easily exceed 256GB when |
1172 | | * counting the backing softoken key, the key data, template data, and |
1173 | | * the input parameters to this KDF. |
1174 | | * |
1175 | | * This is the L parameter in NIST SP800-108. |
1176 | | */ |
1177 | 0 | PRUint64 output_bitlen = 0; |
1178 | | |
1179 | | /* First validate our passed input parameters against PKCS#11 v3.0 |
1180 | | * and NIST SP800-108 requirements. */ |
1181 | 0 | ret = kbkdf_ValidateParameters(mech, kdf_params, ret_key_size); |
1182 | 0 | if (ret != CKR_OK) { |
1183 | 0 | goto finish; |
1184 | 0 | } |
1185 | | |
1186 | | /* Initialize the underlying PRF state. */ |
1187 | 0 | if (prf_key) { |
1188 | 0 | ret = sftk_MAC_Init(&ctx, kdf_params->prfType, prf_key); |
1189 | 0 | } else { |
1190 | 0 | ret = sftk_MAC_InitRaw(&ctx, kdf_params->prfType, prf_key_bytes, |
1191 | 0 | prf_key_length, PR_TRUE); |
1192 | 0 | } |
1193 | 0 | if (ret != CKR_OK) { |
1194 | 0 | goto finish; |
1195 | 0 | } |
1196 | | |
1197 | | /* Compute the size of our output buffer based on passed parameters and |
1198 | | * the output size of the underlying PRF. */ |
1199 | 0 | ret = kbkdf_CalculateLength(kdf_params, &ctx, ret_key_size, &output_bitlen, &buffer_length); |
1200 | 0 | if (ret != CKR_OK) { |
1201 | 0 | goto finish; |
1202 | 0 | } |
1203 | | |
1204 | | /* Allocate memory for the PRF output */ |
1205 | 0 | output_buffer = PORT_ZNewArray(unsigned char, buffer_length); |
1206 | 0 | if (output_buffer == NULL) { |
1207 | 0 | ret = CKR_HOST_MEMORY; |
1208 | 0 | goto finish; |
1209 | 0 | } |
1210 | | |
1211 | | /* Call into the underlying KDF */ |
1212 | 0 | switch (mech) { |
1213 | 0 | case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA: /* fall through */ |
1214 | 0 | case CKM_SP800_108_COUNTER_KDF: |
1215 | 0 | ret = kbkdf_CounterRaw(kdf_params, &ctx, output_buffer, buffer_length, output_bitlen); |
1216 | 0 | break; |
1217 | 0 | case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */ |
1218 | 0 | case CKM_SP800_108_FEEDBACK_KDF: |
1219 | 0 | ret = kbkdf_FeedbackRaw(kdf_params, initial_value, initial_value_length, &ctx, output_buffer, buffer_length, output_bitlen); |
1220 | 0 | break; |
1221 | 0 | case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */ |
1222 | 0 | case CKM_SP800_108_DOUBLE_PIPELINE_KDF: |
1223 | 0 | ret = kbkdf_PipelineRaw(kdf_params, &ctx, output_buffer, buffer_length, output_bitlen); |
1224 | 0 | break; |
1225 | 0 | default: |
1226 | | /* Shouldn't happen unless NIST introduces a new KBKDF type. */ |
1227 | 0 | PR_ASSERT(PR_FALSE); |
1228 | 0 | ret = CKR_FUNCTION_FAILED; |
1229 | 0 | } |
1230 | | |
1231 | | /* Validate the above KDF succeeded. */ |
1232 | 0 | if (ret != CKR_OK) { |
1233 | 0 | goto finish; |
1234 | 0 | } |
1235 | | |
1236 | 0 | *out_key_bytes = output_buffer; |
1237 | 0 | *out_key_length = buffer_length; |
1238 | 0 | *mac_size = ctx.mac_size; |
1239 | |
|
1240 | 0 | output_buffer = NULL; /* returning the buffer, don't zero and free it */ |
1241 | |
|
1242 | 0 | finish: |
1243 | 0 | PORT_ZFree(output_buffer, buffer_length); |
1244 | | |
1245 | | /* Free the PRF. This should handle clearing all sensitive information. */ |
1246 | 0 | sftk_MAC_DestroyContext(&ctx, PR_FALSE); |
1247 | 0 | return ret; |
1248 | 0 | } |
1249 | | |
1250 | | /* [ section: PKCS#11 entry ] */ |
1251 | | |
1252 | | CK_RV |
1253 | | kbkdf_Dispatch(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, SFTKObject *prf_key, SFTKObject *ret_key, CK_ULONG ret_key_size) |
1254 | 0 | { |
1255 | | /* This handles boilerplate common to all KBKDF types. Instead of placing |
1256 | | * this in pkcs11c.c, place it here to reduce clutter. */ |
1257 | |
|
1258 | 0 | CK_RV ret; |
1259 | | |
1260 | | /* Assumptions about our calling environment. */ |
1261 | 0 | PR_ASSERT(pMechanism != NULL && prf_key != NULL && ret_key != NULL); |
1262 | | |
1263 | | /* Validate that the caller passed parameters. */ |
1264 | 0 | if (pMechanism->pParameter == NULL) { |
1265 | 0 | return CKR_MECHANISM_PARAM_INVALID; |
1266 | 0 | } |
1267 | | |
1268 | | /* Create a common set of parameters to use for all KDF types. This |
1269 | | * separates out the KDF parameters from the Feedback-specific IV, |
1270 | | * allowing us to use a common type for all calls. */ |
1271 | 0 | CK_SP800_108_KDF_PARAMS kdf_params = { 0 }; |
1272 | 0 | CK_BYTE_PTR initial_value = NULL; |
1273 | 0 | CK_ULONG initial_value_length = 0; |
1274 | 0 | unsigned char *output_buffer = NULL; |
1275 | 0 | size_t buffer_length = 0; |
1276 | 0 | unsigned int mac_size = 0; |
1277 | | |
1278 | | /* Split Feedback-specific IV from remaining KDF parameters. */ |
1279 | 0 | ret = kbkdf_LoadParameters(mech, pMechanism, &kdf_params, &initial_value, &initial_value_length); |
1280 | 0 | if (ret != CKR_OK) { |
1281 | 0 | goto finish; |
1282 | 0 | } |
1283 | | /* let rawDispatch handle the rest. We split this out so we could |
1284 | | * handle the POST test without accessing pkcs #11 objects. */ |
1285 | 0 | ret = kbkdf_RawDispatch(mech, &kdf_params, initial_value, |
1286 | 0 | initial_value_length, prf_key, NULL, 0, |
1287 | 0 | &output_buffer, &buffer_length, &mac_size, |
1288 | 0 | ret_key_size); |
1289 | 0 | if (ret != CKR_OK) { |
1290 | 0 | goto finish; |
1291 | 0 | } |
1292 | | |
1293 | | /* Write the output of the PRF into the appropriate keys. */ |
1294 | 0 | ret = kbkdf_SaveKeys(mech, hSession, &kdf_params, output_buffer, buffer_length, mac_size, ret_key, ret_key_size); |
1295 | 0 | if (ret != CKR_OK) { |
1296 | 0 | goto finish; |
1297 | 0 | } |
1298 | | |
1299 | 0 | finish: |
1300 | 0 | PORT_ZFree(output_buffer, buffer_length); |
1301 | |
|
1302 | 0 | return ret; |
1303 | 0 | } |
1304 | | |
1305 | | struct sftk_SP800_Test_struct { |
1306 | | CK_MECHANISM_TYPE mech; |
1307 | | CK_SP800_108_KDF_PARAMS kdf_params; |
1308 | | unsigned int expected_mac_size; |
1309 | | unsigned int ret_key_length; |
1310 | | const unsigned char expected_key_bytes[64]; |
1311 | | }; |
1312 | | |
1313 | | static const CK_SP800_108_COUNTER_FORMAT counter_32 = { 0, 32 }; |
1314 | | static const CK_PRF_DATA_PARAM counter_32_data = { CK_SP800_108_ITERATION_VARIABLE, (CK_VOID_PTR)&counter_32, sizeof(counter_32) }; |
1315 | | |
1316 | | #ifdef NSS_FULL_POST |
1317 | | static const CK_SP800_108_COUNTER_FORMAT counter_16 = { 0, 16 }; |
1318 | | static const CK_PRF_DATA_PARAM counter_16_data = { CK_SP800_108_ITERATION_VARIABLE, (CK_VOID_PTR)&counter_16, sizeof(counter_16) }; |
1319 | | static const CK_PRF_DATA_PARAM counter_null_data = { CK_SP800_108_ITERATION_VARIABLE, NULL, 0 }; |
1320 | | #endif |
1321 | | |
1322 | | static const struct sftk_SP800_Test_struct sftk_SP800_Tests[] = { |
1323 | | #ifdef NSS_FULL_POST |
1324 | | { |
1325 | | CKM_SP800_108_COUNTER_KDF, |
1326 | | { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_16_data, 0, NULL }, |
1327 | | 16, |
1328 | | 64, |
1329 | | { 0x7b, 0x1c, 0xe7, 0xf3, 0x14, 0x67, 0x15, 0xdd, |
1330 | | 0xde, 0x0c, 0x09, 0x46, 0x3f, 0x47, 0x7b, 0xa6, |
1331 | | 0xb8, 0xba, 0x40, 0x07, 0x7c, 0xe3, 0x19, 0x53, |
1332 | | 0x26, 0xac, 0x4c, 0x2e, 0x2b, 0x37, 0x41, 0xe4, |
1333 | | 0x1b, 0x01, 0x3f, 0x2f, 0x2d, 0x16, 0x95, 0xee, |
1334 | | 0xeb, 0x7e, 0x72, 0x7d, 0xa4, 0xab, 0x2e, 0x67, |
1335 | | 0x1d, 0xef, 0x6f, 0xa2, 0xc6, 0xee, 0x3c, 0xcf, |
1336 | | 0xef, 0x88, 0xfd, 0x5c, 0x1d, 0x7b, 0xa0, 0x5a }, |
1337 | | }, |
1338 | | { |
1339 | | CKM_SP800_108_COUNTER_KDF, |
1340 | | { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL }, |
1341 | | 48, |
1342 | | 64, |
1343 | | { 0xe6, 0x62, 0xa4, 0x32, 0x5c, 0xe4, 0xc2, 0x28, |
1344 | | 0x73, 0x8a, 0x5d, 0x94, 0xe7, 0x05, 0xe0, 0x5a, |
1345 | | 0x71, 0x61, 0xb2, 0x3c, 0x51, 0x28, 0x03, 0x1d, |
1346 | | 0xa7, 0xf5, 0x10, 0x83, 0x34, 0xdb, 0x11, 0x73, |
1347 | | 0x92, 0xa6, 0x79, 0x74, 0x81, 0x5d, 0x22, 0x7e, |
1348 | | 0x8d, 0xf2, 0x59, 0x14, 0x56, 0x60, 0xcf, 0xb2, |
1349 | | 0xb3, 0xfd, 0x46, 0xfd, 0x9b, 0x74, 0xfe, 0x4a, |
1350 | | 0x09, 0x30, 0x4a, 0xdf, 0x07, 0x43, 0xfe, 0x85 }, |
1351 | | }, |
1352 | | { |
1353 | | CKM_SP800_108_COUNTER_KDF, |
1354 | | { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL }, |
1355 | | 64, |
1356 | | 64, |
1357 | | { 0xb0, 0x78, 0x36, 0xe1, 0x15, 0xd6, 0xf0, 0xac, |
1358 | | 0x68, 0x7b, 0x42, 0xd3, 0xb6, 0x82, 0x51, 0xad, |
1359 | | 0x95, 0x0a, 0x69, 0x88, 0x84, 0xc2, 0x2e, 0x07, |
1360 | | 0x34, 0x62, 0x8d, 0x42, 0x72, 0x0f, 0x22, 0xe6, |
1361 | | 0xd5, 0x7f, 0x80, 0x15, 0xe6, 0x84, 0x00, 0x65, |
1362 | | 0xef, 0x64, 0x77, 0x29, 0xd6, 0x3b, 0xc7, 0x9a, |
1363 | | 0x15, 0x6d, 0x36, 0xf3, 0x96, 0xc9, 0x14, 0x3f, |
1364 | | 0x2d, 0x4a, 0x7c, 0xdb, 0xc3, 0x6c, 0x3d, 0x6a }, |
1365 | | }, |
1366 | | { |
1367 | | CKM_SP800_108_FEEDBACK_KDF, |
1368 | | { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1369 | | 16, |
1370 | | 64, |
1371 | | { 0xc0, 0xa0, 0x23, 0x96, 0x16, 0x4d, 0xd6, 0xbd, |
1372 | | 0x2a, 0x75, 0x8e, 0x72, 0xf5, 0xc3, 0xa0, 0xb8, |
1373 | | 0x78, 0x83, 0x15, 0x21, 0x34, 0xd3, 0xd8, 0x71, |
1374 | | 0xc9, 0xe7, 0x4b, 0x20, 0xb7, 0x65, 0x5b, 0x13, |
1375 | | 0xbc, 0x85, 0x54, 0xe3, 0xb6, 0xee, 0x73, 0xd5, |
1376 | | 0xf2, 0xa0, 0x94, 0x1a, 0x79, 0x66, 0x3b, 0x1e, |
1377 | | 0x67, 0x3e, 0x69, 0xa4, 0x12, 0x40, 0xa9, 0xda, |
1378 | | 0x8d, 0x14, 0xb1, 0xce, 0xf1, 0x4b, 0x79, 0x4e }, |
1379 | | }, |
1380 | | { |
1381 | | CKM_SP800_108_FEEDBACK_KDF, |
1382 | | { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1383 | | 32, |
1384 | | 64, |
1385 | | { 0x99, 0x9b, 0x08, 0x79, 0x14, 0x2e, 0x58, 0x34, |
1386 | | 0xd7, 0x92, 0xa7, 0x7e, 0x7f, 0xc2, 0xf0, 0x34, |
1387 | | 0xa3, 0x4e, 0x33, 0xf0, 0x63, 0x95, 0x2d, 0xad, |
1388 | | 0xbf, 0x3b, 0xcb, 0x6d, 0x4e, 0x07, 0xd9, 0xe9, |
1389 | | 0xbd, 0xbd, 0x77, 0x54, 0xe1, 0xa3, 0x36, 0x26, |
1390 | | 0xcd, 0xb1, 0xf9, 0x2d, 0x80, 0x68, 0xa2, 0x01, |
1391 | | 0x4e, 0xbf, 0x35, 0xec, 0x65, 0xae, 0xfd, 0x71, |
1392 | | 0xa6, 0xd7, 0x62, 0x26, 0x2c, 0x3f, 0x73, 0x63 }, |
1393 | | }, |
1394 | | { |
1395 | | CKM_SP800_108_FEEDBACK_KDF, |
1396 | | { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1397 | | 48, |
1398 | | 64, |
1399 | | { 0xc8, 0x7a, 0xf8, 0xd9, 0x6b, 0x90, 0x82, 0x35, |
1400 | | 0xea, 0xf5, 0x2c, 0x8f, 0xce, 0xaa, 0x3b, 0xa5, |
1401 | | 0x68, 0xd3, 0x7f, 0xae, 0x31, 0x93, 0xe6, 0x69, |
1402 | | 0x0c, 0xd1, 0x74, 0x7f, 0x8f, 0xc2, 0xe2, 0x33, |
1403 | | 0x93, 0x45, 0x23, 0xba, 0xb3, 0x73, 0xc9, 0x2c, |
1404 | | 0xd6, 0xd2, 0x10, 0x16, 0xe9, 0x9f, 0x9e, 0xe8, |
1405 | | 0xc1, 0x0e, 0x29, 0x95, 0x3d, 0x16, 0x68, 0x24, |
1406 | | 0x40, 0x4d, 0x40, 0x21, 0x41, 0xa6, 0xc8, 0xdb }, |
1407 | | }, |
1408 | | { |
1409 | | CKM_SP800_108_FEEDBACK_KDF, |
1410 | | { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1411 | | 64, |
1412 | | 64, |
1413 | | { 0x81, 0x39, 0x12, 0xc2, 0xf9, 0x31, 0x24, 0x7c, |
1414 | | 0x71, 0x12, 0x97, 0x08, 0x82, 0x76, 0x83, 0x55, |
1415 | | 0x8c, 0x82, 0xf3, 0x09, 0xd6, 0x1b, 0x7a, 0xa2, |
1416 | | 0x6e, 0x71, 0x6b, 0xad, 0x46, 0x57, 0x60, 0x89, |
1417 | | 0x38, 0xcf, 0x63, 0xfa, 0xf4, 0x38, 0x27, 0xef, |
1418 | | 0xf0, 0xaf, 0x75, 0x4e, 0xc2, 0xe0, 0x31, 0xdb, |
1419 | | 0x59, 0x7d, 0x19, 0xc9, 0x6d, 0xbb, 0xed, 0x95, |
1420 | | 0xaf, 0x3e, 0xd8, 0x33, 0x76, 0xab, 0xec, 0xfa }, |
1421 | | }, |
1422 | | { |
1423 | | CKM_SP800_108_DOUBLE_PIPELINE_KDF, |
1424 | | { CKM_AES_CMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1425 | | 16, |
1426 | | 64, |
1427 | | { 0x3e, 0xa8, 0xbf, 0x77, 0x84, 0x90, 0xb0, 0x3a, |
1428 | | 0x89, 0x16, 0x32, 0x01, 0x92, 0xd3, 0x1f, 0x1b, |
1429 | | 0xc1, 0x06, 0xc5, 0x32, 0x62, 0x03, 0x50, 0x16, |
1430 | | 0x3b, 0xb9, 0xa7, 0xdc, 0xb5, 0x68, 0x6a, 0xbb, |
1431 | | 0xbb, 0x7d, 0x63, 0x69, 0x24, 0x6e, 0x09, 0xd6, |
1432 | | 0x6f, 0x80, 0x57, 0x65, 0xc5, 0x62, 0x33, 0x96, |
1433 | | 0x69, 0xe6, 0xab, 0x65, 0x36, 0xd0, 0xe2, 0x5c, |
1434 | | 0xd7, 0xbd, 0xe4, 0x68, 0x13, 0xd6, 0xb1, 0x46 }, |
1435 | | }, |
1436 | | { |
1437 | | CKM_SP800_108_DOUBLE_PIPELINE_KDF, |
1438 | | { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1439 | | 32, |
1440 | | 64, |
1441 | | { 0xeb, 0x28, 0xd9, 0x2c, 0x19, 0x33, 0xb9, 0x2a, |
1442 | | 0xf9, 0xac, 0x85, 0xbd, 0xf4, 0xdb, 0xfa, 0x88, |
1443 | | 0x73, 0xf4, 0x36, 0x08, 0xdb, 0xfe, 0x13, 0xd1, |
1444 | | 0x5a, 0xec, 0x7b, 0x68, 0x13, 0x53, 0xb3, 0xd1, |
1445 | | 0x31, 0xf2, 0x83, 0xae, 0x9f, 0x75, 0x47, 0xb6, |
1446 | | 0x6d, 0x3c, 0x20, 0x16, 0x47, 0x9c, 0x27, 0x66, |
1447 | | 0xec, 0xa9, 0xdf, 0x0c, 0xda, 0x2a, 0xf9, 0xf4, |
1448 | | 0x55, 0x74, 0xde, 0x9d, 0x3f, 0xe3, 0x5e, 0x14 }, |
1449 | | }, |
1450 | | { |
1451 | | CKM_SP800_108_DOUBLE_PIPELINE_KDF, |
1452 | | { CKM_SHA384_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1453 | | 48, |
1454 | | 64, |
1455 | | { 0xa5, 0xca, 0x32, 0x40, 0x00, 0x93, 0xb2, 0xcc, |
1456 | | 0x78, 0x3c, 0xa6, 0xc4, 0xaf, 0xa8, 0xb3, 0xd0, |
1457 | | 0xa4, 0x6b, 0xb5, 0x31, 0x35, 0x87, 0x33, 0xa2, |
1458 | | 0x6a, 0x6b, 0xe1, 0xff, 0xea, 0x1d, 0x6e, 0x9e, |
1459 | | 0x0b, 0xde, 0x8b, 0x92, 0x15, 0xd6, 0x56, 0x2f, |
1460 | | 0xb6, 0x1a, 0xd7, 0xd2, 0x01, 0x3e, 0x28, 0x2e, |
1461 | | 0xfa, 0x84, 0x3c, 0xc0, 0xe8, 0xbe, 0x94, 0xc0, |
1462 | | 0x06, 0xbd, 0xbf, 0x87, 0x1f, 0xb8, 0x64, 0xc2 }, |
1463 | | }, |
1464 | | { |
1465 | | CKM_SP800_108_DOUBLE_PIPELINE_KDF, |
1466 | | { CKM_SHA512_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_null_data, 0, NULL }, |
1467 | | 64, |
1468 | | 64, |
1469 | | { 0x3f, 0xd9, 0x4e, 0x80, 0x58, 0x21, 0xc8, 0xea, |
1470 | | 0x22, 0x17, 0xcf, 0x7d, 0xce, 0xfd, 0xec, 0x03, |
1471 | | 0xb9, 0xe4, 0xa2, 0xf7, 0xc0, 0xf1, 0x68, 0x81, |
1472 | | 0x53, 0x71, 0xb7, 0x42, 0x14, 0x4e, 0x5b, 0x09, |
1473 | | 0x05, 0x31, 0xb9, 0x27, 0x18, 0x2d, 0x23, 0xf8, |
1474 | | 0x9c, 0x3d, 0x4e, 0xd0, 0xdd, 0xf3, 0x1e, 0x4b, |
1475 | | 0xf2, 0xf9, 0x1a, 0x5d, 0x00, 0x66, 0x22, 0x83, |
1476 | | 0xae, 0x3c, 0x53, 0xd2, 0x54, 0x4b, 0x06, 0x4c }, |
1477 | | }, |
1478 | | #endif |
1479 | | { |
1480 | | CKM_SP800_108_COUNTER_KDF, |
1481 | | { CKM_SHA256_HMAC, 1, (CK_PRF_DATA_PARAM_PTR)&counter_32_data, 0, NULL }, |
1482 | | 32, |
1483 | | 64, |
1484 | | { 0xfb, 0x2b, 0xb5, 0xde, 0xce, 0x5a, 0x2b, 0xdc, |
1485 | | 0x25, 0x8f, 0x54, 0x17, 0x4b, 0x5a, 0xa7, 0x90, |
1486 | | 0x64, 0x36, 0xeb, 0x43, 0x1f, 0x1d, 0xf9, 0x23, |
1487 | | 0xb2, 0x22, 0x29, 0xa0, 0xfa, 0x2e, 0x21, 0xb6, |
1488 | | 0xb7, 0xfb, 0x27, 0x0a, 0x1c, 0xa6, 0x58, 0x43, |
1489 | | 0xa1, 0x16, 0x44, 0x29, 0x4b, 0x1c, 0xb3, 0x72, |
1490 | | 0xd5, 0x98, 0x9d, 0x27, 0xd5, 0x75, 0x25, 0xbf, |
1491 | | 0x23, 0x61, 0x40, 0x48, 0xbb, 0x0b, 0x49, 0x8e }, |
1492 | | } |
1493 | | }; |
1494 | | |
1495 | | SECStatus |
1496 | | sftk_fips_SP800_108_PowerUpSelfTests(void) |
1497 | 0 | { |
1498 | 0 | int i; |
1499 | 0 | CK_RV crv; |
1500 | |
|
1501 | 0 | const unsigned char prf_key[] = { |
1502 | 0 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
1503 | 0 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
1504 | 0 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
1505 | 0 | 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
1506 | 0 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
1507 | 0 | 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
1508 | 0 | 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
1509 | 0 | 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 |
1510 | 0 | }; |
1511 | 0 | for (i = 0; i < PR_ARRAY_SIZE(sftk_SP800_Tests); i++) { |
1512 | 0 | const struct sftk_SP800_Test_struct *test = &sftk_SP800_Tests[i]; |
1513 | 0 | unsigned char *output_buffer; |
1514 | 0 | size_t buffer_length; |
1515 | 0 | unsigned int mac_size; |
1516 | |
|
1517 | 0 | crv = kbkdf_RawDispatch(test->mech, &test->kdf_params, |
1518 | 0 | prf_key, test->expected_mac_size, |
1519 | 0 | NULL, prf_key, test->expected_mac_size, |
1520 | 0 | &output_buffer, &buffer_length, &mac_size, |
1521 | 0 | test->ret_key_length); |
1522 | 0 | if (crv != CKR_OK) { |
1523 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1524 | 0 | return SECFailure; |
1525 | 0 | } |
1526 | 0 | if ((mac_size != test->expected_mac_size) || |
1527 | 0 | (buffer_length != test->ret_key_length) || |
1528 | 0 | (output_buffer == NULL) || |
1529 | 0 | (PORT_Memcmp(output_buffer, test->expected_key_bytes, buffer_length) != 0)) { |
1530 | 0 | PORT_ZFree(output_buffer, buffer_length); |
1531 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
1532 | 0 | return SECFailure; |
1533 | 0 | } |
1534 | 0 | PORT_ZFree(output_buffer, buffer_length); |
1535 | 0 | } |
1536 | 0 | return SECSuccess; |
1537 | 0 | } |