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