/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  | }  |