/src/nss/lib/softoken/sftkike.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* This Source Code Form is subject to the terms of the Mozilla Public  | 
2  |  |  * License, v. 2.0. If a copy of the MPL was not distributed with this  | 
3  |  |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */  | 
4  |  | /*  | 
5  |  |  * This file implements PKCS 11 on top of our existing security modules  | 
6  |  |  *  | 
7  |  |  * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.  | 
8  |  |  *   This implementation has two slots:  | 
9  |  |  *      slot 1 is our generic crypto support. It does not require login.  | 
10  |  |  *   It supports Public Key ops, and all they bulk ciphers and hashes.  | 
11  |  |  *   It can also support Private Key ops for imported Private keys. It does  | 
12  |  |  *   not have any token storage.  | 
13  |  |  *      slot 2 is our private key support. It requires a login before use. It  | 
14  |  |  *   can store Private Keys and Certs as token objects. Currently only private  | 
15  |  |  *   keys and their associated Certificates are saved on the token.  | 
16  |  |  *  | 
17  |  |  *   In this implementation, session objects are only visible to the session  | 
18  |  |  *   that created or generated them.  | 
19  |  |  */  | 
20  |  | #include "seccomon.h"  | 
21  |  | #include "secitem.h"  | 
22  |  | #include "secport.h"  | 
23  |  | #include "blapi.h"  | 
24  |  | #include "pkcs11.h"  | 
25  |  | #include "pkcs11i.h"  | 
26  |  | #include "pkcs1sig.h"  | 
27  |  | #include "lowkeyi.h"  | 
28  |  | #include "secder.h"  | 
29  |  | #include "secdig.h"  | 
30  |  | #include "lowpbe.h" /* We do PBE below */  | 
31  |  | #include "pkcs11t.h"  | 
32  |  | #include "secoid.h"  | 
33  |  | #include "alghmac.h"  | 
34  |  | #include "softoken.h"  | 
35  |  | #include "secasn1.h"  | 
36  |  | #include "secerr.h"  | 
37  |  |  | 
38  |  | #include "prprf.h"  | 
39  |  | #include "prenv.h"  | 
40  |  |  | 
41  |  | /*  | 
42  |  |  * A common prfContext to handle both hmac and aes xcbc  | 
43  |  |  * hash contexts have non-null hashObj and hmac, aes  | 
44  |  |  * contexts have non-null aes */  | 
45  |  | typedef struct prfContextStr { | 
46  |  |     HASH_HashType hashType;  | 
47  |  |     const SECHashObject *hashObj;  | 
48  |  |     HMACContext *hmac;  | 
49  |  |     AESContext *aes;  | 
50  |  |     unsigned int nextChar;  | 
51  |  |     unsigned char padBuf[AES_BLOCK_SIZE];  | 
52  |  |     unsigned char macBuf[AES_BLOCK_SIZE];  | 
53  |  |     unsigned char k1[AES_BLOCK_SIZE];  | 
54  |  |     unsigned char k2[AES_BLOCK_SIZE];  | 
55  |  |     unsigned char k3[AES_BLOCK_SIZE];  | 
56  |  | } prfContext;  | 
57  |  |  | 
58  |  | /* iv full of zeros used in several places in aes xcbc */  | 
59  |  | static const unsigned char iv_zero[] = { | 
60  |  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  | 
61  |  |     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  | 
62  |  | };  | 
63  |  |  | 
64  |  | /*  | 
65  |  |  * Generate AES XCBC keys from the AES MAC key.  | 
66  |  |  * k1 is used in the actual mac.  | 
67  |  |  * k2 and k3 are used in the final pad step.  | 
68  |  |  */  | 
69  |  | static CK_RV  | 
70  |  | sftk_aes_xcbc_get_keys(const unsigned char *keyValue, unsigned int keyLen,  | 
71  |  |                        unsigned char *k1, unsigned char *k2, unsigned char *k3)  | 
72  | 0  | { | 
73  | 0  |     SECStatus rv;  | 
74  | 0  |     CK_RV crv;  | 
75  | 0  |     unsigned int tmpLen;  | 
76  | 0  |     AESContext *aes_context = NULL;  | 
77  | 0  |     unsigned char newKey[AES_BLOCK_SIZE];  | 
78  |  |  | 
79  |  |     /* AES XCBC keys. k1, k2, and k3 are derived by encrypting  | 
80  |  |      * k1data, k2data, and k3data with the mac key.  | 
81  |  |      */  | 
82  | 0  |     static const unsigned char k1data[] = { | 
83  | 0  |         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,  | 
84  | 0  |         0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01  | 
85  | 0  |     };  | 
86  | 0  |     static const unsigned char k2data[] = { | 
87  | 0  |         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  | 
88  | 0  |         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02  | 
89  | 0  |     };  | 
90  | 0  |     static const unsigned char k3data[] = { | 
91  | 0  |         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,  | 
92  | 0  |         0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03  | 
93  | 0  |     };  | 
94  |  |  | 
95  |  |     /* k1_0 = aes_ecb(0, k1data) */  | 
96  | 0  |     static const unsigned char k1_0[] = { | 
97  | 0  |         0xe1, 0x4d, 0x5d, 0x0e, 0xe2, 0x77, 0x15, 0xdf,  | 
98  | 0  |         0x08, 0xb4, 0x15, 0x2b, 0xa2, 0x3d, 0xa8, 0xe0  | 
99  |  | 
  | 
100  | 0  |     };  | 
101  |  |     /* k2_0 = aes_ecb(0, k2data) */  | 
102  | 0  |     static const unsigned char k2_0[] = { | 
103  | 0  |         0x5e, 0xba, 0x73, 0xf8, 0x91, 0x42, 0xc5, 0x48,  | 
104  | 0  |         0x80, 0xf6, 0x85, 0x94, 0x37, 0x3c, 0x5c, 0x37  | 
105  | 0  |     };  | 
106  |  |     /* k3_0 = aes_ecb(0, k3data) */  | 
107  | 0  |     static const unsigned char k3_0[] = { | 
108  | 0  |         0x8d, 0x34, 0xef, 0xcb, 0x3b, 0xd5, 0x45, 0xca,  | 
109  | 0  |         0x06, 0x2a, 0xec, 0xdf, 0xef, 0x7c, 0x0b, 0xfa  | 
110  | 0  |     };  | 
111  |  |  | 
112  |  |     /* first make sure out input key is the correct length  | 
113  |  |      * rfc 4434. If key is shorter, pad with zeros to the  | 
114  |  |      * the right. If key is longer newKey = aes_xcbc(0, key, keyLen).  | 
115  |  |      */  | 
116  | 0  |     if (keyLen < AES_BLOCK_SIZE) { | 
117  | 0  |         PORT_Memcpy(newKey, keyValue, keyLen);  | 
118  | 0  |         PORT_Memset(&newKey[keyLen], 0, AES_BLOCK_SIZE - keyLen);  | 
119  | 0  |         keyValue = newKey;  | 
120  | 0  |     } else if (keyLen > AES_BLOCK_SIZE) { | 
121  |  |         /* calculate our new key = aes_xcbc(0, key, keyLen). Because the  | 
122  |  |          * key above is fixed (0), we can precalculate k1, k2, and k3.  | 
123  |  |          * if this code ever needs to be more generic (support any xcbc  | 
124  |  |          * function rather than just aes, we would probably want to just  | 
125  |  |          * recurse here using our prf functions. This would be safe because  | 
126  |  |          * the recurse case would have keyLen == blocksize and thus skip  | 
127  |  |          * this conditional.  | 
128  |  |          */  | 
129  | 0  |         aes_context = AES_CreateContext(k1_0, iv_zero, NSS_AES_CBC,  | 
130  | 0  |                                         PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE);  | 
131  |  |         /* we know the following loop will execute at least once */  | 
132  | 0  |         while (keyLen > AES_BLOCK_SIZE) { | 
133  | 0  |             rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,  | 
134  | 0  |                              keyValue, AES_BLOCK_SIZE);  | 
135  | 0  |             if (rv != SECSuccess) { | 
136  | 0  |                 goto fail;  | 
137  | 0  |             }  | 
138  | 0  |             keyValue += AES_BLOCK_SIZE;  | 
139  | 0  |             keyLen -= AES_BLOCK_SIZE;  | 
140  | 0  |         }  | 
141  | 0  |         PORT_Memcpy(newKey, keyValue, keyLen);  | 
142  | 0  |         sftk_xcbc_mac_pad(newKey, keyLen, AES_BLOCK_SIZE, k2_0, k3_0);  | 
143  | 0  |         rv = AES_Encrypt(aes_context, newKey, &tmpLen, AES_BLOCK_SIZE,  | 
144  | 0  |                          newKey, AES_BLOCK_SIZE);  | 
145  | 0  |         if (rv != SECSuccess) { | 
146  | 0  |             goto fail;  | 
147  | 0  |         }  | 
148  | 0  |         keyValue = newKey;  | 
149  | 0  |         AES_DestroyContext(aes_context, PR_TRUE);  | 
150  | 0  |     }  | 
151  |  |     /* the length of the key in keyValue is known to be AES_BLOCK_SIZE,  | 
152  |  |      * either because it was on input, or it was shorter and extended, or  | 
153  |  |      * because it was mac'd down using aes_xcbc_prf.  | 
154  |  |      */  | 
155  | 0  |     aes_context = AES_CreateContext(keyValue, iv_zero,  | 
156  | 0  |                                     NSS_AES, PR_TRUE, AES_BLOCK_SIZE, AES_BLOCK_SIZE);  | 
157  | 0  |     if (aes_context == NULL) { | 
158  | 0  |         goto fail;  | 
159  | 0  |     }  | 
160  | 0  |     rv = AES_Encrypt(aes_context, k1, &tmpLen, AES_BLOCK_SIZE,  | 
161  | 0  |                      k1data, sizeof(k1data));  | 
162  | 0  |     if (rv != SECSuccess) { | 
163  | 0  |         goto fail;  | 
164  | 0  |     }  | 
165  | 0  |     rv = AES_Encrypt(aes_context, k2, &tmpLen, AES_BLOCK_SIZE,  | 
166  | 0  |                      k2data, sizeof(k2data));  | 
167  | 0  |     if (rv != SECSuccess) { | 
168  | 0  |         goto fail;  | 
169  | 0  |     }  | 
170  | 0  |     rv = AES_Encrypt(aes_context, k3, &tmpLen, AES_BLOCK_SIZE,  | 
171  | 0  |                      k3data, sizeof(k3data));  | 
172  | 0  |     if (rv != SECSuccess) { | 
173  | 0  |         goto fail;  | 
174  | 0  |     }  | 
175  | 0  |     AES_DestroyContext(aes_context, PR_TRUE);  | 
176  | 0  |     PORT_Memset(newKey, 0, AES_BLOCK_SIZE);  | 
177  | 0  |     return CKR_OK;  | 
178  | 0  | fail:  | 
179  | 0  |     crv = sftk_MapCryptError(PORT_GetError());  | 
180  | 0  |     if (aes_context) { | 
181  | 0  |         AES_DestroyContext(aes_context, PR_TRUE);  | 
182  | 0  |     }  | 
183  | 0  |     PORT_Memset(k1, 0, AES_BLOCK_SIZE);  | 
184  | 0  |     PORT_Memset(k2, 0, AES_BLOCK_SIZE);  | 
185  | 0  |     PORT_Memset(k3, 0, AES_BLOCK_SIZE);  | 
186  | 0  |     PORT_Memset(newKey, 0, AES_BLOCK_SIZE);  | 
187  | 0  |     return crv;  | 
188  | 0  | }  | 
189  |  |  | 
190  |  | /* encode the final pad block of aes xcbc, padBuf is modified */  | 
191  |  | CK_RV  | 
192  |  | sftk_xcbc_mac_pad(unsigned char *padBuf, unsigned int bufLen,  | 
193  |  |                   unsigned int blockSize, const unsigned char *k2,  | 
194  |  |                   const unsigned char *k3)  | 
195  | 0  | { | 
196  | 0  |     unsigned int i;  | 
197  | 0  |     if (bufLen == blockSize) { | 
198  | 0  |         for (i = 0; i < blockSize; i++) { | 
199  | 0  |             padBuf[i] ^= k2[i];  | 
200  | 0  |         }  | 
201  | 0  |     } else { | 
202  | 0  |         padBuf[bufLen++] = 0x80;  | 
203  | 0  |         for (i = bufLen; i < blockSize; i++) { | 
204  | 0  |             padBuf[i] = 0x00;  | 
205  | 0  |         }  | 
206  | 0  |         for (i = 0; i < blockSize; i++) { | 
207  | 0  |             padBuf[i] ^= k3[i];  | 
208  | 0  |         }  | 
209  | 0  |     }  | 
210  | 0  |     return CKR_OK;  | 
211  | 0  | }  | 
212  |  |  | 
213  |  | /* Map the mechanism to the underlying hash. If the type is not a hash  | 
214  |  |  * or HMAC, return HASH_AlgNULL. This can happen legitimately if  | 
215  |  |  * we are doing AES XCBC */  | 
216  |  | static HASH_HashType  | 
217  |  | sftk_map_hmac_to_hash(CK_MECHANISM_TYPE type)  | 
218  | 0  | { | 
219  | 0  |     switch (type) { | 
220  | 0  |         case CKM_SHA_1_HMAC:  | 
221  | 0  |         case CKM_SHA_1:  | 
222  | 0  |             return HASH_AlgSHA1;  | 
223  | 0  |         case CKM_MD5_HMAC:  | 
224  | 0  |         case CKM_MD5:  | 
225  | 0  |             return HASH_AlgMD5;  | 
226  | 0  |         case CKM_MD2_HMAC:  | 
227  | 0  |         case CKM_MD2:  | 
228  | 0  |             return HASH_AlgMD2;  | 
229  | 0  |         case CKM_SHA224_HMAC:  | 
230  | 0  |         case CKM_SHA224:  | 
231  | 0  |             return HASH_AlgSHA224;  | 
232  | 0  |         case CKM_SHA256_HMAC:  | 
233  | 0  |         case CKM_SHA256:  | 
234  | 0  |             return HASH_AlgSHA256;  | 
235  | 0  |         case CKM_SHA384_HMAC:  | 
236  | 0  |         case CKM_SHA384:  | 
237  | 0  |             return HASH_AlgSHA384;  | 
238  | 0  |         case CKM_SHA512_HMAC:  | 
239  | 0  |         case CKM_SHA512:  | 
240  | 0  |             return HASH_AlgSHA512;  | 
241  | 0  |     }  | 
242  | 0  |     return HASH_AlgNULL;  | 
243  | 0  | }  | 
244  |  |  | 
245  |  | /*  | 
246  |  |  * Generally setup the context based on the mechanism.  | 
247  |  |  * If the mech is HMAC, context->hashObj should be set  | 
248  |  |  * Otherwise it is assumed to be AES XCBC. prf_setup  | 
249  |  |  * checks these assumptions and will return an error  | 
250  |  |  * if they are not met. NOTE: this function does not allocate  | 
251  |  |  * anything, so there is no requirement to free context after  | 
252  |  |  * prf_setup like there is if you call prf_init.  | 
253  |  |  */  | 
254  |  | static CK_RV  | 
255  |  | prf_setup(prfContext *context, CK_MECHANISM_TYPE mech)  | 
256  | 0  | { | 
257  | 0  |     context->hashType = sftk_map_hmac_to_hash(mech);  | 
258  | 0  |     context->hashObj = NULL;  | 
259  | 0  |     context->hmac = NULL;  | 
260  | 0  |     context->aes = NULL;  | 
261  | 0  |     if (context->hashType != HASH_AlgNULL) { | 
262  | 0  |         context->hashObj = HASH_GetRawHashObject(context->hashType);  | 
263  | 0  |         if (context->hashObj == NULL) { | 
264  | 0  |             return CKR_GENERAL_ERROR;  | 
265  | 0  |         }  | 
266  | 0  |         return CKR_OK;  | 
267  | 0  |     } else if (mech == CKM_AES_XCBC_MAC) { | 
268  | 0  |         return CKR_OK;  | 
269  | 0  |     }  | 
270  | 0  |     return CKR_MECHANISM_PARAM_INVALID;  | 
271  | 0  | }  | 
272  |  |  | 
273  |  | /* return the underlying prf length for this context. This will  | 
274  |  |  * function once the context is setup */  | 
275  |  | static CK_RV  | 
276  |  | prf_length(prfContext *context)  | 
277  | 0  | { | 
278  | 0  |     if (context->hashObj) { | 
279  | 0  |         return context->hashObj->length;  | 
280  | 0  |     }  | 
281  | 0  |     return AES_BLOCK_SIZE; /* AES */  | 
282  | 0  | }  | 
283  |  |  | 
284  |  | /* set up the key for the prf. prf_update or prf_final should not be called if  | 
285  |  |  * prf_init has not been called first. Once prf_init returns hmac and  | 
286  |  |  * aes contexts should set and valid.  | 
287  |  |  */  | 
288  |  | static CK_RV  | 
289  |  | prf_init(prfContext *context, const unsigned char *keyValue,  | 
290  |  |          unsigned int keyLen)  | 
291  | 0  | { | 
292  | 0  |     CK_RV crv;  | 
293  |  | 
  | 
294  | 0  |     context->hmac = NULL;  | 
295  | 0  |     if (context->hashObj) { | 
296  | 0  |         context->hmac = HMAC_Create(context->hashObj,  | 
297  | 0  |                                     keyValue, keyLen, PR_FALSE);  | 
298  | 0  |         if (context->hmac == NULL) { | 
299  | 0  |             return sftk_MapCryptError(PORT_GetError());  | 
300  | 0  |         }  | 
301  | 0  |         HMAC_Begin(context->hmac);  | 
302  | 0  |     } else { | 
303  | 0  |         crv = sftk_aes_xcbc_get_keys(keyValue, keyLen, context->k1,  | 
304  | 0  |                                      context->k2, context->k3);  | 
305  | 0  |         if (crv != CKR_OK)  | 
306  | 0  |             return crv;  | 
307  | 0  |         context->nextChar = 0;  | 
308  | 0  |         context->aes = AES_CreateContext(context->k1, iv_zero, NSS_AES_CBC,  | 
309  | 0  |                                          PR_TRUE, sizeof(context->k1), AES_BLOCK_SIZE);  | 
310  | 0  |         if (context->aes == NULL) { | 
311  | 0  |             crv = sftk_MapCryptError(PORT_GetError());  | 
312  | 0  |             PORT_Memset(context->k1, 0, sizeof(context->k1));  | 
313  | 0  |             PORT_Memset(context->k2, 0, sizeof(context->k2));  | 
314  | 0  |             PORT_Memset(context->k3, 0, sizeof(context->k2));  | 
315  | 0  |             return crv;  | 
316  | 0  |         }  | 
317  | 0  |     }  | 
318  | 0  |     return CKR_OK;  | 
319  | 0  | }  | 
320  |  |  | 
321  |  | /*  | 
322  |  |  * process input to the prf  | 
323  |  |  */  | 
324  |  | static CK_RV  | 
325  |  | prf_update(prfContext *context, const unsigned char *buf, unsigned int len)  | 
326  | 0  | { | 
327  | 0  |     unsigned int tmpLen;  | 
328  | 0  |     SECStatus rv;  | 
329  |  | 
  | 
330  | 0  |     if (context->hmac) { | 
331  | 0  |         HMAC_Update(context->hmac, buf, len);  | 
332  | 0  |     } else { | 
333  |  |         /* AES MAC XCBC*/  | 
334  |  |         /* We must keep the last block back so that it can be processed in  | 
335  |  |          * final. This is why we only check that nextChar + len > blocksize,  | 
336  |  |          * rather than checking that nextChar + len >= blocksize */  | 
337  | 0  |         while (context->nextChar + len > AES_BLOCK_SIZE) { | 
338  | 0  |             if (context->nextChar != 0) { | 
339  |  |                 /* first handle fill in any partial blocks in the buffer */  | 
340  | 0  |                 unsigned int left = AES_BLOCK_SIZE - context->nextChar;  | 
341  |  |                 /* note: left can be zero */  | 
342  | 0  |                 PORT_Memcpy(context->padBuf + context->nextChar, buf, left);  | 
343  |  |                 /* NOTE: AES MAC XCBC xors the data with the previous block  | 
344  |  |                  * We don't do that step here because our AES_Encrypt mode  | 
345  |  |                  * is CBC, which does the xor automatically */  | 
346  | 0  |                 rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,  | 
347  | 0  |                                  sizeof(context->macBuf), context->padBuf,  | 
348  | 0  |                                  sizeof(context->padBuf));  | 
349  | 0  |                 if (rv != SECSuccess) { | 
350  | 0  |                     return sftk_MapCryptError(PORT_GetError());  | 
351  | 0  |                 }  | 
352  | 0  |                 context->nextChar = 0;  | 
353  | 0  |                 len -= left;  | 
354  | 0  |                 buf += left;  | 
355  | 0  |             } else { | 
356  |  |                 /* optimization. if we have complete blocks to write out  | 
357  |  |                  * (and will still have leftover blocks for padbuf in the end).  | 
358  |  |                  * we can mac directly out of our buffer without first copying  | 
359  |  |                  * them to padBuf */  | 
360  | 0  |                 rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,  | 
361  | 0  |                                  sizeof(context->macBuf), buf, AES_BLOCK_SIZE);  | 
362  | 0  |                 if (rv != SECSuccess) { | 
363  | 0  |                     return sftk_MapCryptError(PORT_GetError());  | 
364  | 0  |                 }  | 
365  | 0  |                 len -= AES_BLOCK_SIZE;  | 
366  | 0  |                 buf += AES_BLOCK_SIZE;  | 
367  | 0  |             }  | 
368  | 0  |         }  | 
369  | 0  |         PORT_Memcpy(context->padBuf + context->nextChar, buf, len);  | 
370  | 0  |         context->nextChar += len;  | 
371  | 0  |     }  | 
372  | 0  |     return CKR_OK;  | 
373  | 0  | }  | 
374  |  |  | 
375  |  | /*  | 
376  |  |  * free the data associated with the prf. Clear any possible CSPs  | 
377  |  |  * This can safely be called on any context after prf_setup. It can  | 
378  |  |  * also be called an an already freed context.  | 
379  |  |  * A free context can be reused by calling prf_init again without  | 
380  |  |  * the need to call prf_setup.  | 
381  |  |  */  | 
382  |  | static void  | 
383  |  | prf_free(prfContext *context)  | 
384  | 0  | { | 
385  | 0  |     if (context->hmac) { | 
386  | 0  |         HMAC_Destroy(context->hmac, PR_TRUE);  | 
387  | 0  |         context->hmac = NULL;  | 
388  | 0  |     }  | 
389  | 0  |     if (context->aes) { | 
390  | 0  |         PORT_Memset(context->k1, 0, sizeof(context->k1));  | 
391  | 0  |         PORT_Memset(context->k2, 0, sizeof(context->k2));  | 
392  | 0  |         PORT_Memset(context->k3, 0, sizeof(context->k2));  | 
393  | 0  |         PORT_Memset(context->padBuf, 0, sizeof(context->padBuf));  | 
394  | 0  |         PORT_Memset(context->macBuf, 0, sizeof(context->macBuf));  | 
395  | 0  |         AES_DestroyContext(context->aes, PR_TRUE);  | 
396  | 0  |         context->aes = NULL;  | 
397  | 0  |     }  | 
398  | 0  | }  | 
399  |  |  | 
400  |  | /*  | 
401  |  |  * extract the final prf value. On success, this has the side effect of  | 
402  |  |  * also freeing the context data and clearing the keys  | 
403  |  |  */  | 
404  |  | static CK_RV  | 
405  |  | prf_final(prfContext *context, unsigned char *buf, unsigned int len)  | 
406  | 0  | { | 
407  | 0  |     unsigned int tmpLen;  | 
408  | 0  |     SECStatus rv;  | 
409  |  | 
  | 
410  | 0  |     if (context->hmac) { | 
411  | 0  |         unsigned int outLen;  | 
412  | 0  |         HMAC_Finish(context->hmac, buf, &outLen, len);  | 
413  | 0  |         if (outLen != len) { | 
414  | 0  |             return CKR_GENERAL_ERROR;  | 
415  | 0  |         }  | 
416  | 0  |     } else { | 
417  |  |         /* prf_update had guarrenteed that the last full block is still in  | 
418  |  |          * the padBuf if the input data is a multiple of the blocksize. This  | 
419  |  |          * allows sftk_xcbc_mac_pad to process that pad buf accordingly */  | 
420  | 0  |         CK_RV crv = sftk_xcbc_mac_pad(context->padBuf, context->nextChar,  | 
421  | 0  |                                       AES_BLOCK_SIZE, context->k2, context->k3);  | 
422  | 0  |         if (crv != CKR_OK) { | 
423  | 0  |             return crv;  | 
424  | 0  |         }  | 
425  | 0  |         rv = AES_Encrypt(context->aes, context->macBuf, &tmpLen,  | 
426  | 0  |                          sizeof(context->macBuf), context->padBuf, AES_BLOCK_SIZE);  | 
427  | 0  |         if (rv != SECSuccess) { | 
428  | 0  |             return sftk_MapCryptError(PORT_GetError());  | 
429  | 0  |         }  | 
430  | 0  |         PORT_Memcpy(buf, context->macBuf, len);  | 
431  | 0  |     }  | 
432  | 0  |     prf_free(context);  | 
433  | 0  |     return CKR_OK;  | 
434  | 0  | }  | 
435  |  |  | 
436  |  | /*  | 
437  |  |  * There are four flavors of ike prf functions here.  | 
438  |  |  * ike_prf is used in both ikeV1 and ikeV2 to generate  | 
439  |  |  * an initial key that all the other keys are generated with.  | 
440  |  |  *  | 
441  |  |  * These functions are called from NSC_DeriveKey with the inKey value  | 
442  |  |  * already looked up, and it expects the CKA_VALUE for outKey to be set.  | 
443  |  |  *  | 
444  |  |  * Depending on usage it returns either:  | 
445  |  |  *    1. prf(Ni|Nr, inKey); (bDataAsKey=TRUE, bRekey=FALSE)  | 
446  |  |  *    2. prf(inKey, Ni|Nr); (bDataAsKkey=FALSE, bRekey=FALSE)  | 
447  |  |  *    3. prf(inKey, newKey | Ni | Nr); (bDataAsKey=FALSE, bRekey=TRUE)  | 
448  |  |  * The resulting output key is always the length of the underlying prf  | 
449  |  |  * (as returned by prf_length()).  | 
450  |  |  * The combination of bDataAsKey=TRUE and bRekey=TRUE is not allowed  | 
451  |  |  *  | 
452  |  |  * Case 1 is used in  | 
453  |  |  *    a. ikev2 (rfc5996) inKey is called g^ir, the output is called SKEYSEED  | 
454  |  |  *    b. ikev1 (rfc2409) inKey is called g^ir, the output is called SKEYID  | 
455  |  |  * Case 2 is used in ikev1 (rfc2409) inkey is called pre-shared-key, output  | 
456  |  |  *    is called SKEYID  | 
457  |  |  * Case 3 is used in ikev2 (rfc5996) rekey case, inKey is SK_d, newKey is  | 
458  |  |  *    g^ir (new), the output is called SKEYSEED  | 
459  |  |  */  | 
460  |  | CK_RV  | 
461  |  | sftk_ike_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,  | 
462  |  |              const CK_IKE_PRF_DERIVE_PARAMS *params, SFTKObject *outKey)  | 
463  | 0  | { | 
464  | 0  |     SFTKAttribute *newKeyValue = NULL;  | 
465  | 0  |     SFTKObject *newKeyObj = NULL;  | 
466  | 0  |     unsigned char outKeyData[HASH_LENGTH_MAX];  | 
467  | 0  |     unsigned char *newInKey = NULL;  | 
468  | 0  |     unsigned int newInKeySize = 0;  | 
469  | 0  |     unsigned int macSize;  | 
470  | 0  |     CK_RV crv = CKR_OK;  | 
471  | 0  |     prfContext context;  | 
472  |  | 
  | 
473  | 0  |     crv = prf_setup(&context, params->prfMechanism);  | 
474  | 0  |     if (crv != CKR_OK) { | 
475  | 0  |         return crv;  | 
476  | 0  |     }  | 
477  | 0  |     macSize = prf_length(&context);  | 
478  | 0  |     if ((params->bDataAsKey) && (params->bRekey)) { | 
479  | 0  |         return CKR_ARGUMENTS_BAD;  | 
480  | 0  |     }  | 
481  | 0  |     if (params->bRekey) { | 
482  |  |         /* lookup the value of new key from the session and key handle */  | 
483  | 0  |         SFTKSession *session = sftk_SessionFromHandle(hSession);  | 
484  | 0  |         if (session == NULL) { | 
485  | 0  |             return CKR_SESSION_HANDLE_INVALID;  | 
486  | 0  |         }  | 
487  | 0  |         newKeyObj = sftk_ObjectFromHandle(params->hNewKey, session);  | 
488  | 0  |         sftk_FreeSession(session);  | 
489  | 0  |         if (newKeyObj == NULL) { | 
490  | 0  |             return CKR_KEY_HANDLE_INVALID;  | 
491  | 0  |         }  | 
492  | 0  |         newKeyValue = sftk_FindAttribute(newKeyObj, CKA_VALUE);  | 
493  | 0  |         if (newKeyValue == NULL) { | 
494  | 0  |             crv = CKR_KEY_HANDLE_INVALID;  | 
495  | 0  |             goto fail;  | 
496  | 0  |         }  | 
497  | 0  |     }  | 
498  | 0  |     if (params->bDataAsKey) { | 
499  |  |         /* The key is Ni || Np, so we need to concatenate them together first */  | 
500  | 0  |         newInKeySize = params->ulNiLen + params->ulNrLen;  | 
501  | 0  |         newInKey = PORT_Alloc(newInKeySize);  | 
502  | 0  |         if (newInKey == NULL) { | 
503  | 0  |             crv = CKR_HOST_MEMORY;  | 
504  | 0  |             goto fail;  | 
505  | 0  |         }  | 
506  | 0  |         PORT_Memcpy(newInKey, params->pNi, params->ulNiLen);  | 
507  | 0  |         PORT_Memcpy(newInKey + params->ulNiLen, params->pNr, params->ulNrLen);  | 
508  | 0  |         crv = prf_init(&context, newInKey, newInKeySize);  | 
509  | 0  |         if (crv != CKR_OK) { | 
510  | 0  |             goto fail;  | 
511  | 0  |         }  | 
512  |  |         /* key as the data */  | 
513  | 0  |         crv = prf_update(&context, inKey->attrib.pValue,  | 
514  | 0  |                          inKey->attrib.ulValueLen);  | 
515  | 0  |         if (crv != CKR_OK) { | 
516  | 0  |             goto fail;  | 
517  | 0  |         }  | 
518  | 0  |     } else { | 
519  | 0  |         crv = prf_init(&context, inKey->attrib.pValue,  | 
520  | 0  |                        inKey->attrib.ulValueLen);  | 
521  | 0  |         if (crv != CKR_OK) { | 
522  | 0  |             goto fail;  | 
523  | 0  |         }  | 
524  | 0  |         if (newKeyValue) { | 
525  | 0  |             crv = prf_update(&context, newKeyValue->attrib.pValue,  | 
526  | 0  |                              newKeyValue->attrib.ulValueLen);  | 
527  | 0  |             if (crv != CKR_OK) { | 
528  | 0  |                 goto fail;  | 
529  | 0  |             }  | 
530  | 0  |         }  | 
531  | 0  |         crv = prf_update(&context, params->pNi, params->ulNiLen);  | 
532  | 0  |         if (crv != CKR_OK) { | 
533  | 0  |             goto fail;  | 
534  | 0  |         }  | 
535  | 0  |         crv = prf_update(&context, params->pNr, params->ulNrLen);  | 
536  | 0  |         if (crv != CKR_OK) { | 
537  | 0  |             goto fail;  | 
538  | 0  |         }  | 
539  | 0  |     }  | 
540  | 0  |     crv = prf_final(&context, outKeyData, macSize);  | 
541  | 0  |     if (crv != CKR_OK) { | 
542  | 0  |         goto fail;  | 
543  | 0  |     }  | 
544  |  |  | 
545  | 0  |     crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, macSize);  | 
546  | 0  | fail:  | 
547  | 0  |     if (newInKey) { | 
548  | 0  |         PORT_ZFree(newInKey, newInKeySize);  | 
549  | 0  |     }  | 
550  | 0  |     if (newKeyValue) { | 
551  | 0  |         sftk_FreeAttribute(newKeyValue);  | 
552  | 0  |     }  | 
553  | 0  |     if (newKeyObj) { | 
554  | 0  |         sftk_FreeObject(newKeyObj);  | 
555  | 0  |     }  | 
556  | 0  |     PORT_Memset(outKeyData, 0, macSize);  | 
557  | 0  |     prf_free(&context);  | 
558  | 0  |     return crv;  | 
559  | 0  | }  | 
560  |  |  | 
561  |  | /*  | 
562  |  |  * The second flavor of  ike prf is ike1_prf.  | 
563  |  |  *  | 
564  |  |  * It is used by ikeV1 to generate the various session keys used in the  | 
565  |  |  * connection. It uses the initial key, an optional previous key, and a one byte  | 
566  |  |  * key number to generate a unique key for each of the various session  | 
567  |  |  * functions (encryption, decryption, mac). These keys expect a key size  | 
568  |  |  * (as they may vary in length based on usage). If no length is provided,  | 
569  |  |  * it will default to the length of the prf.  | 
570  |  |  *  | 
571  |  |  * This function returns either:  | 
572  |  |  *     prf(inKey, gxyKey || CKYi || CKYr || key_number)  | 
573  |  |  * or  | 
574  |  |  *     prf(inKey, prevkey || gxyKey || CKYi || CKYr || key_number)  | 
575  |  |  * depending on the stats of bHasPrevKey  | 
576  |  |  *  | 
577  |  |  * This is defined in rfc2409. For each of the following keys.  | 
578  |  |  *     inKey is  SKEYID,    gxyKey is g^xy  | 
579  |  |  *     for outKey = SKEYID_d, bHasPrevKey = false, key_number = 0  | 
580  |  |  *     for outKey = SKEYID_a, prevKey= SKEYID_d,   key_number = 1  | 
581  |  |  *     for outKey = SKEYID_e, prevKey= SKEYID_a,   key_number = 2  | 
582  |  |  */  | 
583  |  | CK_RV  | 
584  |  | sftk_ike1_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,  | 
585  |  |               const CK_IKE1_PRF_DERIVE_PARAMS *params, SFTKObject *outKey,  | 
586  |  |               unsigned int keySize)  | 
587  | 0  | { | 
588  | 0  |     SFTKAttribute *gxyKeyValue = NULL;  | 
589  | 0  |     SFTKObject *gxyKeyObj = NULL;  | 
590  | 0  |     SFTKAttribute *prevKeyValue = NULL;  | 
591  | 0  |     SFTKObject *prevKeyObj = NULL;  | 
592  | 0  |     SFTKSession *session;  | 
593  | 0  |     unsigned char outKeyData[HASH_LENGTH_MAX];  | 
594  | 0  |     unsigned int macSize;  | 
595  | 0  |     CK_RV crv;  | 
596  | 0  |     prfContext context;  | 
597  |  | 
  | 
598  | 0  |     crv = prf_setup(&context, params->prfMechanism);  | 
599  | 0  |     if (crv != CKR_OK) { | 
600  | 0  |         return crv;  | 
601  | 0  |     }  | 
602  | 0  |     macSize = prf_length(&context);  | 
603  | 0  |     if (keySize > macSize) { | 
604  | 0  |         return CKR_KEY_SIZE_RANGE;  | 
605  | 0  |     }  | 
606  | 0  |     if (keySize == 0) { | 
607  | 0  |         keySize = macSize;  | 
608  | 0  |     }  | 
609  |  |  | 
610  |  |     /* lookup the two keys from their passed in handles */  | 
611  | 0  |     session = sftk_SessionFromHandle(hSession);  | 
612  | 0  |     if (session == NULL) { | 
613  | 0  |         return CKR_SESSION_HANDLE_INVALID;  | 
614  | 0  |     }  | 
615  | 0  |     gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);  | 
616  | 0  |     if (params->bHasPrevKey) { | 
617  | 0  |         prevKeyObj = sftk_ObjectFromHandle(params->hPrevKey, session);  | 
618  | 0  |     }  | 
619  | 0  |     sftk_FreeSession(session);  | 
620  | 0  |     if ((gxyKeyObj == NULL) || ((params->bHasPrevKey) &&  | 
621  | 0  |                                 (prevKeyObj == NULL))) { | 
622  | 0  |         crv = CKR_KEY_HANDLE_INVALID;  | 
623  | 0  |         goto fail;  | 
624  | 0  |     }  | 
625  | 0  |     gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);  | 
626  | 0  |     if (gxyKeyValue == NULL) { | 
627  | 0  |         crv = CKR_KEY_HANDLE_INVALID;  | 
628  | 0  |         goto fail;  | 
629  | 0  |     }  | 
630  | 0  |     if (prevKeyObj) { | 
631  | 0  |         prevKeyValue = sftk_FindAttribute(prevKeyObj, CKA_VALUE);  | 
632  | 0  |         if (prevKeyValue == NULL) { | 
633  | 0  |             crv = CKR_KEY_HANDLE_INVALID;  | 
634  | 0  |             goto fail;  | 
635  | 0  |         }  | 
636  | 0  |     }  | 
637  |  |  | 
638  |  |     /* outKey = prf(inKey, [prevKey|] gxyKey | CKYi | CKYr | keyNumber) */  | 
639  | 0  |     crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);  | 
640  | 0  |     if (crv != CKR_OK) { | 
641  | 0  |         goto fail;  | 
642  | 0  |     }  | 
643  | 0  |     if (prevKeyValue) { | 
644  | 0  |         crv = prf_update(&context, prevKeyValue->attrib.pValue,  | 
645  | 0  |                          prevKeyValue->attrib.ulValueLen);  | 
646  | 0  |         if (crv != CKR_OK) { | 
647  | 0  |             goto fail;  | 
648  | 0  |         }  | 
649  | 0  |     }  | 
650  | 0  |     crv = prf_update(&context, gxyKeyValue->attrib.pValue,  | 
651  | 0  |                      gxyKeyValue->attrib.ulValueLen);  | 
652  | 0  |     if (crv != CKR_OK) { | 
653  | 0  |         goto fail;  | 
654  | 0  |     }  | 
655  | 0  |     crv = prf_update(&context, params->pCKYi, params->ulCKYiLen);  | 
656  | 0  |     if (crv != CKR_OK) { | 
657  | 0  |         goto fail;  | 
658  | 0  |     }  | 
659  | 0  |     crv = prf_update(&context, params->pCKYr, params->ulCKYrLen);  | 
660  | 0  |     if (crv != CKR_OK) { | 
661  | 0  |         goto fail;  | 
662  | 0  |     }  | 
663  | 0  |     crv = prf_update(&context, ¶ms->keyNumber, 1);  | 
664  | 0  |     if (crv != CKR_OK) { | 
665  | 0  |         goto fail;  | 
666  | 0  |     }  | 
667  | 0  |     crv = prf_final(&context, outKeyData, macSize);  | 
668  | 0  |     if (crv != CKR_OK) { | 
669  | 0  |         goto fail;  | 
670  | 0  |     }  | 
671  |  |  | 
672  | 0  |     crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);  | 
673  | 0  | fail:  | 
674  | 0  |     if (gxyKeyValue) { | 
675  | 0  |         sftk_FreeAttribute(gxyKeyValue);  | 
676  | 0  |     }  | 
677  | 0  |     if (prevKeyValue) { | 
678  | 0  |         sftk_FreeAttribute(prevKeyValue);  | 
679  | 0  |     }  | 
680  | 0  |     if (gxyKeyObj) { | 
681  | 0  |         sftk_FreeObject(gxyKeyObj);  | 
682  | 0  |     }  | 
683  | 0  |     if (prevKeyObj) { | 
684  | 0  |         sftk_FreeObject(prevKeyObj);  | 
685  | 0  |     }  | 
686  | 0  |     PORT_Memset(outKeyData, 0, macSize);  | 
687  | 0  |     prf_free(&context);  | 
688  | 0  |     return crv;  | 
689  | 0  | }  | 
690  |  |  | 
691  |  | /*  | 
692  |  |  * The third flavor of ike prf is ike1_appendix_b.  | 
693  |  |  *  | 
694  |  |  * It is used by ikeV1 to generate longer key material from skeyid_e.  | 
695  |  |  * Unlike ike1_prf, if no length is provided, this function  | 
696  |  |  * will generate a KEY_RANGE_ERROR.  | 
697  |  |  *  | 
698  |  |  * This function returns (from rfc2409 appendix b):  | 
699  |  |  * Ka = K1 | K2 | K3 | K4 |... Kn  | 
700  |  |  * where:  | 
701  |  |  *       K1 = prf(K, [gxyKey]|[extraData]) or prf(K, 0) if gxyKey and extraData  | 
702  |  |  *                                                      ar not present.  | 
703  |  |  *       K2 = prf(K, K1|[gxyKey]|[extraData])  | 
704  |  |  *       K3 = prf(K, K2|[gxyKey]|[extraData])  | 
705  |  |  *       K4 = prf(K, K3|[gxyKey]|[extraData])  | 
706  |  |  *            .  | 
707  |  |  *       Kn = prf(K, K(n-1)|[gxyKey]|[extraData])  | 
708  |  |  * K = inKey  | 
709  |  |  */  | 
710  |  | CK_RV  | 
711  |  | sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,  | 
712  |  |                          const CK_IKE1_EXTENDED_DERIVE_PARAMS *params,  | 
713  |  |                          SFTKObject *outKey, unsigned int keySize)  | 
714  | 0  | { | 
715  | 0  |     SFTKAttribute *gxyKeyValue = NULL;  | 
716  | 0  |     SFTKObject *gxyKeyObj = NULL;  | 
717  | 0  |     unsigned char *outKeyData = NULL;  | 
718  | 0  |     unsigned char *thisKey = NULL;  | 
719  | 0  |     unsigned char *lastKey = NULL;  | 
720  | 0  |     unsigned int macSize;  | 
721  | 0  |     unsigned int outKeySize;  | 
722  | 0  |     unsigned int genKeySize;  | 
723  | 0  |     PRBool quickMode = PR_FALSE;  | 
724  | 0  |     CK_RV crv;  | 
725  | 0  |     prfContext context;  | 
726  |  | 
  | 
727  | 0  |     if ((params->ulExtraDataLen != 0) && (params->pExtraData == NULL)) { | 
728  | 0  |         return CKR_ARGUMENTS_BAD;  | 
729  | 0  |     }  | 
730  | 0  |     crv = prf_setup(&context, params->prfMechanism);  | 
731  | 0  |     if (crv != CKR_OK) { | 
732  | 0  |         return crv;  | 
733  | 0  |     }  | 
734  |  |  | 
735  | 0  |     if (params->bHasKeygxy) { | 
736  | 0  |         SFTKSession *session;  | 
737  | 0  |         session = sftk_SessionFromHandle(hSession);  | 
738  | 0  |         if (session == NULL) { | 
739  | 0  |             return CKR_SESSION_HANDLE_INVALID;  | 
740  | 0  |         }  | 
741  | 0  |         gxyKeyObj = sftk_ObjectFromHandle(params->hKeygxy, session);  | 
742  | 0  |         sftk_FreeSession(session);  | 
743  | 0  |         if (gxyKeyObj == NULL) { | 
744  | 0  |             crv = CKR_KEY_HANDLE_INVALID;  | 
745  | 0  |             goto fail;  | 
746  | 0  |         }  | 
747  | 0  |         gxyKeyValue = sftk_FindAttribute(gxyKeyObj, CKA_VALUE);  | 
748  | 0  |         if (gxyKeyValue == NULL) { | 
749  | 0  |             crv = CKR_KEY_HANDLE_INVALID;  | 
750  | 0  |             goto fail;  | 
751  | 0  |         }  | 
752  | 0  |         quickMode = PR_TRUE;  | 
753  | 0  |     }  | 
754  |  |  | 
755  | 0  |     if (params->ulExtraDataLen != 0) { | 
756  | 0  |         quickMode = PR_TRUE;  | 
757  | 0  |     }  | 
758  |  | 
  | 
759  | 0  |     macSize = prf_length(&context);  | 
760  |  | 
  | 
761  | 0  |     if (keySize == 0) { | 
762  | 0  |         keySize = macSize;  | 
763  | 0  |     }  | 
764  |  |  | 
765  |  |     /* In appendix B, we are just expanding or contracting a single key.  | 
766  |  |      * If the input key is less than or equal to the the key size we want,  | 
767  |  |      * just subset the original key. In quick mode we are actually getting  | 
768  |  |      * new keys (salted with our seed data and our gxy key), so we want to  | 
769  |  |      * run through our algorithm */  | 
770  | 0  |     if ((!quickMode) && (keySize <= inKey->attrib.ulValueLen)) { | 
771  | 0  |         return sftk_forceAttribute(outKey, CKA_VALUE,  | 
772  | 0  |                                    inKey->attrib.pValue, keySize);  | 
773  | 0  |     }  | 
774  |  |  | 
775  | 0  |     outKeySize = PR_ROUNDUP(keySize, macSize);  | 
776  | 0  |     outKeyData = PORT_Alloc(outKeySize);  | 
777  | 0  |     if (outKeyData == NULL) { | 
778  | 0  |         crv = CKR_HOST_MEMORY;  | 
779  | 0  |         goto fail;  | 
780  | 0  |     }  | 
781  |  |  | 
782  |  |     /*  | 
783  |  |      * this loop generates on block of the prf, basically  | 
784  |  |      *   kn = prf(key, Kn-1 | [Keygxy] | [ExtraData])  | 
785  |  |      *   Kn is thisKey, Kn-1 is lastKey  | 
786  |  |      *   key is inKey  | 
787  |  |      */  | 
788  | 0  |     thisKey = outKeyData;  | 
789  | 0  |     for (genKeySize = 0; genKeySize < keySize; genKeySize += macSize) { | 
790  | 0  |         PRBool hashedData = PR_FALSE;  | 
791  | 0  |         crv = prf_init(&context, inKey->attrib.pValue, inKey->attrib.ulValueLen);  | 
792  | 0  |         if (crv != CKR_OK) { | 
793  | 0  |             goto fail;  | 
794  | 0  |         }  | 
795  | 0  |         if (lastKey != NULL) { | 
796  | 0  |             crv = prf_update(&context, lastKey, macSize);  | 
797  | 0  |             if (crv != CKR_OK) { | 
798  | 0  |                 goto fail;  | 
799  | 0  |             }  | 
800  | 0  |             hashedData = PR_TRUE;  | 
801  | 0  |         }  | 
802  | 0  |         if (gxyKeyValue != NULL) { | 
803  | 0  |             crv = prf_update(&context, gxyKeyValue->attrib.pValue,  | 
804  | 0  |                              gxyKeyValue->attrib.ulValueLen);  | 
805  | 0  |             if (crv != CKR_OK) { | 
806  | 0  |                 goto fail;  | 
807  | 0  |             }  | 
808  | 0  |             hashedData = PR_TRUE;  | 
809  | 0  |         }  | 
810  | 0  |         if (params->ulExtraDataLen != 0) { | 
811  | 0  |             crv = prf_update(&context, params->pExtraData, params->ulExtraDataLen);  | 
812  | 0  |             if (crv != CKR_OK) { | 
813  | 0  |                 goto fail;  | 
814  | 0  |             }  | 
815  | 0  |             hashedData = PR_TRUE;  | 
816  | 0  |         }  | 
817  |  |         /* if we haven't hashed anything yet, hash a zero */  | 
818  | 0  |         if (hashedData == PR_FALSE) { | 
819  | 0  |             const unsigned char zero = 0;  | 
820  | 0  |             crv = prf_update(&context, &zero, 1);  | 
821  | 0  |             if (crv != CKR_OK) { | 
822  | 0  |                 goto fail;  | 
823  | 0  |             }  | 
824  | 0  |         }  | 
825  | 0  |         crv = prf_final(&context, thisKey, macSize);  | 
826  | 0  |         if (crv != CKR_OK) { | 
827  | 0  |             goto fail;  | 
828  | 0  |         }  | 
829  | 0  |         lastKey = thisKey;  | 
830  | 0  |         thisKey += macSize;  | 
831  | 0  |     }  | 
832  | 0  |     crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);  | 
833  | 0  | fail:  | 
834  | 0  |     if (gxyKeyValue) { | 
835  | 0  |         sftk_FreeAttribute(gxyKeyValue);  | 
836  | 0  |     }  | 
837  | 0  |     if (gxyKeyObj) { | 
838  | 0  |         sftk_FreeObject(gxyKeyObj);  | 
839  | 0  |     }  | 
840  | 0  |     if (outKeyData) { | 
841  | 0  |         PORT_ZFree(outKeyData, outKeySize);  | 
842  | 0  |     }  | 
843  | 0  |     prf_free(&context);  | 
844  | 0  |     return crv;  | 
845  | 0  | }  | 
846  |  |  | 
847  |  | /*  | 
848  |  |  * The final flavor of ike prf is ike_prf_plus  | 
849  |  |  *  | 
850  |  |  * It is used by ikeV2 to generate the various session keys used in the  | 
851  |  |  * connection. It uses the initial key and a feedback version of the prf  | 
852  |  |  * to generate sufficient bytes to cover all the session keys. The application  | 
853  |  |  * will then use CK_EXTRACT_KEY_FROM_KEY to pull out the various subkeys.  | 
854  |  |  * This function expects a key size to be set by the application to cover  | 
855  |  |  * all the keys.  Unlike ike1_prf, if no length is provided, this function  | 
856  |  |  * will generate a KEY_RANGE_ERROR  | 
857  |  |  *  | 
858  |  |  * This function returns (from rfc5996):  | 
859  |  |  * prfplus = T1 | T2 | T3 | T4 |... Tn  | 
860  |  |  * where:  | 
861  |  |  *       T1 = prf(K, S  | 0x01)  | 
862  |  |  *       T2 = prf(K, T1 | S | 0x02)  | 
863  |  |  *       T3 = prf(K, T3 | S | 0x03)  | 
864  |  |  *       T4 = prf(K, T4 | S | 0x04)  | 
865  |  |  *            .  | 
866  |  |  *       Tn = prf(K, T(n-1) | n)  | 
867  |  |  * K = inKey, S = seedKey | seedData  | 
868  |  |  */  | 
869  |  |  | 
870  |  | static CK_RV  | 
871  |  | sftk_ike_prf_plus_raw(CK_SESSION_HANDLE hSession,  | 
872  |  |                       const unsigned char *inKeyData, CK_ULONG inKeyLen,  | 
873  |  |                       const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params,  | 
874  |  |                       unsigned char **outKeyDataPtr, unsigned int *outKeySizePtr,  | 
875  |  |                       unsigned int keySize)  | 
876  | 0  | { | 
877  | 0  |     SFTKAttribute *seedValue = NULL;  | 
878  | 0  |     SFTKObject *seedKeyObj = NULL;  | 
879  | 0  |     unsigned char *outKeyData = NULL;  | 
880  | 0  |     unsigned int outKeySize;  | 
881  | 0  |     unsigned char *thisKey;  | 
882  | 0  |     unsigned char *lastKey = NULL;  | 
883  | 0  |     unsigned char currentByte = 0;  | 
884  | 0  |     unsigned int getKeySize;  | 
885  | 0  |     unsigned int macSize;  | 
886  | 0  |     CK_RV crv;  | 
887  | 0  |     prfContext context;  | 
888  |  | 
  | 
889  | 0  |     if (keySize == 0) { | 
890  | 0  |         return CKR_KEY_SIZE_RANGE;  | 
891  | 0  |     }  | 
892  |  |  | 
893  | 0  |     crv = prf_setup(&context, params->prfMechanism);  | 
894  | 0  |     if (crv != CKR_OK) { | 
895  | 0  |         return crv;  | 
896  | 0  |     }  | 
897  |  |     /* pull in optional seedKey */  | 
898  | 0  |     if (params->bHasSeedKey) { | 
899  | 0  |         SFTKSession *session = sftk_SessionFromHandle(hSession);  | 
900  | 0  |         if (session == NULL) { | 
901  | 0  |             return CKR_SESSION_HANDLE_INVALID;  | 
902  | 0  |         }  | 
903  | 0  |         seedKeyObj = sftk_ObjectFromHandle(params->hSeedKey, session);  | 
904  | 0  |         sftk_FreeSession(session);  | 
905  | 0  |         if (seedKeyObj == NULL) { | 
906  | 0  |             return CKR_KEY_HANDLE_INVALID;  | 
907  | 0  |         }  | 
908  | 0  |         seedValue = sftk_FindAttribute(seedKeyObj, CKA_VALUE);  | 
909  | 0  |         if (seedValue == NULL) { | 
910  | 0  |             crv = CKR_KEY_HANDLE_INVALID;  | 
911  | 0  |             goto fail;  | 
912  | 0  |         }  | 
913  | 0  |     } else if (params->ulSeedDataLen == 0) { | 
914  | 0  |         crv = CKR_ARGUMENTS_BAD;  | 
915  | 0  |         goto fail;  | 
916  | 0  |     }  | 
917  | 0  |     macSize = prf_length(&context);  | 
918  | 0  |     outKeySize = PR_ROUNDUP(keySize, macSize);  | 
919  | 0  |     outKeyData = PORT_Alloc(outKeySize);  | 
920  | 0  |     if (outKeyData == NULL) { | 
921  | 0  |         crv = CKR_HOST_MEMORY;  | 
922  | 0  |         goto fail;  | 
923  | 0  |     }  | 
924  |  |  | 
925  |  |     /*  | 
926  |  |      * this loop generates on block of the prf, basically  | 
927  |  |      *   Tn = prf(key, Tn-1 | S | n)  | 
928  |  |      *   Tn is thisKey, Tn-2 is lastKey, S is seedKey || seedData,  | 
929  |  |      *   key is inKey. currentByte = n-1 on entry.  | 
930  |  |      */  | 
931  | 0  |     thisKey = outKeyData;  | 
932  | 0  |     for (getKeySize = 0; getKeySize < keySize; getKeySize += macSize) { | 
933  |  |         /* if currentByte is 255, we'll overflow when we increment it below.  | 
934  |  |          * This can only happen if keysize > 255*macSize. In that case  | 
935  |  |          * the application has asked for too much key material, so return  | 
936  |  |          * an error */  | 
937  | 0  |         if (currentByte == 255) { | 
938  | 0  |             crv = CKR_KEY_SIZE_RANGE;  | 
939  | 0  |             goto fail;  | 
940  | 0  |         }  | 
941  | 0  |         crv = prf_init(&context, inKeyData, inKeyLen);  | 
942  | 0  |         if (crv != CKR_OK) { | 
943  | 0  |             goto fail;  | 
944  | 0  |         }  | 
945  |  |  | 
946  | 0  |         if (lastKey) { | 
947  | 0  |             crv = prf_update(&context, lastKey, macSize);  | 
948  | 0  |             if (crv != CKR_OK) { | 
949  | 0  |                 goto fail;  | 
950  | 0  |             }  | 
951  | 0  |         }  | 
952  |  |         /* prf the key first */  | 
953  | 0  |         if (seedValue) { | 
954  | 0  |             crv = prf_update(&context, seedValue->attrib.pValue,  | 
955  | 0  |                              seedValue->attrib.ulValueLen);  | 
956  | 0  |             if (crv != CKR_OK) { | 
957  | 0  |                 goto fail;  | 
958  | 0  |             }  | 
959  | 0  |         }  | 
960  |  |         /* then prf the data */  | 
961  | 0  |         if (params->ulSeedDataLen != 0) { | 
962  | 0  |             crv = prf_update(&context, params->pSeedData,  | 
963  | 0  |                              params->ulSeedDataLen);  | 
964  | 0  |             if (crv != CKR_OK) { | 
965  | 0  |                 goto fail;  | 
966  | 0  |             }  | 
967  | 0  |         }  | 
968  | 0  |         currentByte++;  | 
969  | 0  |         crv = prf_update(&context, ¤tByte, 1);  | 
970  | 0  |         if (crv != CKR_OK) { | 
971  | 0  |             goto fail;  | 
972  | 0  |         }  | 
973  | 0  |         crv = prf_final(&context, thisKey, macSize);  | 
974  | 0  |         if (crv != CKR_OK) { | 
975  | 0  |             goto fail;  | 
976  | 0  |         }  | 
977  | 0  |         lastKey = thisKey;  | 
978  | 0  |         thisKey += macSize;  | 
979  | 0  |     }  | 
980  | 0  |     *outKeyDataPtr = outKeyData;  | 
981  | 0  |     *outKeySizePtr = outKeySize;  | 
982  | 0  |     outKeyData = NULL; /* don't free it here, our caller will free it */  | 
983  | 0  | fail:  | 
984  | 0  |     if (outKeyData) { | 
985  | 0  |         PORT_ZFree(outKeyData, outKeySize);  | 
986  | 0  |     }  | 
987  | 0  |     if (seedValue) { | 
988  | 0  |         sftk_FreeAttribute(seedValue);  | 
989  | 0  |     }  | 
990  | 0  |     if (seedKeyObj) { | 
991  | 0  |         sftk_FreeObject(seedKeyObj);  | 
992  | 0  |     }  | 
993  | 0  |     prf_free(&context);  | 
994  | 0  |     return crv;  | 
995  | 0  | }  | 
996  |  |  | 
997  |  | /*  | 
998  |  |  * ike prf + with code to deliever results tosoftoken objects.  | 
999  |  |  */  | 
1000  |  | CK_RV  | 
1001  |  | sftk_ike_prf_plus(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,  | 
1002  |  |                   const CK_IKE2_PRF_PLUS_DERIVE_PARAMS *params, SFTKObject *outKey,  | 
1003  |  |                   unsigned int keySize)  | 
1004  | 0  | { | 
1005  | 0  |     unsigned char *outKeyData = NULL;  | 
1006  | 0  |     unsigned int outKeySize;  | 
1007  | 0  |     CK_RV crv;  | 
1008  |  | 
  | 
1009  | 0  |     crv = sftk_ike_prf_plus_raw(hSession, inKey->attrib.pValue,  | 
1010  | 0  |                                 inKey->attrib.ulValueLen, params,  | 
1011  | 0  |                                 &outKeyData, &outKeySize, keySize);  | 
1012  | 0  |     if (crv != CKR_OK) { | 
1013  | 0  |         return crv;  | 
1014  | 0  |     }  | 
1015  |  |  | 
1016  | 0  |     crv = sftk_forceAttribute(outKey, CKA_VALUE, outKeyData, keySize);  | 
1017  | 0  |     PORT_ZFree(outKeyData, outKeySize);  | 
1018  | 0  |     return crv;  | 
1019  | 0  | }  | 
1020  |  |  | 
1021  |  | /* sftk_aes_xcbc_new_keys:  | 
1022  |  |  *  | 
1023  |  |  * aes xcbc creates 3 new keys from the input key. The first key will be the  | 
1024  |  |  * base key of the underlying cbc. The sign code hooks directly into encrypt  | 
1025  |  |  * so we'll have to create a full PKCS #11 key with handle for that key. The  | 
1026  |  |  * caller needs to delete the key when it's through setting up the context.  | 
1027  |  |  *  | 
1028  |  |  * The other two keys will be stored in the sign context until we need them  | 
1029  |  |  * at the end.  | 
1030  |  |  */  | 
1031  |  | CK_RV  | 
1032  |  | sftk_aes_xcbc_new_keys(CK_SESSION_HANDLE hSession,  | 
1033  |  |                        CK_OBJECT_HANDLE hKey, CK_OBJECT_HANDLE_PTR phKey,  | 
1034  |  |                        unsigned char *k2, unsigned char *k3)  | 
1035  | 0  | { | 
1036  | 0  |     SFTKObject *key = NULL;  | 
1037  | 0  |     SFTKSession *session = NULL;  | 
1038  | 0  |     SFTKObject *inKeyObj = NULL;  | 
1039  | 0  |     SFTKAttribute *inKeyValue = NULL;  | 
1040  | 0  |     CK_KEY_TYPE key_type = CKK_AES;  | 
1041  | 0  |     CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;  | 
1042  | 0  |     CK_BBOOL ck_true = CK_TRUE;  | 
1043  | 0  |     CK_RV crv = CKR_OK;  | 
1044  | 0  |     SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);  | 
1045  | 0  |     unsigned char buf[AES_BLOCK_SIZE];  | 
1046  |  | 
  | 
1047  | 0  |     if (!slot) { | 
1048  | 0  |         return CKR_SESSION_HANDLE_INVALID;  | 
1049  | 0  |     }  | 
1050  |  |  | 
1051  |  |     /* get the session */  | 
1052  | 0  |     session = sftk_SessionFromHandle(hSession);  | 
1053  | 0  |     if (session == NULL) { | 
1054  | 0  |         crv = CKR_SESSION_HANDLE_INVALID;  | 
1055  | 0  |         goto fail;  | 
1056  | 0  |     }  | 
1057  |  |  | 
1058  | 0  |     inKeyObj = sftk_ObjectFromHandle(hKey, session);  | 
1059  | 0  |     if (inKeyObj == NULL) { | 
1060  | 0  |         crv = CKR_KEY_HANDLE_INVALID;  | 
1061  | 0  |         goto fail;  | 
1062  | 0  |     }  | 
1063  |  |  | 
1064  | 0  |     inKeyValue = sftk_FindAttribute(inKeyObj, CKA_VALUE);  | 
1065  | 0  |     if (inKeyValue == NULL) { | 
1066  | 0  |         crv = CKR_KEY_HANDLE_INVALID;  | 
1067  | 0  |         goto fail;  | 
1068  | 0  |     }  | 
1069  |  |  | 
1070  | 0  |     crv = sftk_aes_xcbc_get_keys(inKeyValue->attrib.pValue,  | 
1071  | 0  |                                  inKeyValue->attrib.ulValueLen, buf, k2, k3);  | 
1072  |  | 
  | 
1073  | 0  |     if (crv != CKR_OK) { | 
1074  | 0  |         goto fail;  | 
1075  | 0  |     }  | 
1076  |  |  | 
1077  |  |     /*  | 
1078  |  |      * now lets create an object to hang the attributes off of  | 
1079  |  |      */  | 
1080  | 0  |     key = sftk_NewObject(slot); /* fill in the handle later */  | 
1081  | 0  |     if (key == NULL) { | 
1082  | 0  |         crv = CKR_HOST_MEMORY;  | 
1083  | 0  |         goto fail;  | 
1084  | 0  |     }  | 
1085  |  |  | 
1086  |  |     /* make sure we don't have any class, key_type, or value fields */  | 
1087  | 0  |     sftk_DeleteAttributeType(key, CKA_CLASS);  | 
1088  | 0  |     sftk_DeleteAttributeType(key, CKA_KEY_TYPE);  | 
1089  | 0  |     sftk_DeleteAttributeType(key, CKA_VALUE);  | 
1090  | 0  |     sftk_DeleteAttributeType(key, CKA_SIGN);  | 
1091  |  |  | 
1092  |  |     /* Add the class, key_type, and value */  | 
1093  | 0  |     crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));  | 
1094  | 0  |     if (crv != CKR_OK) { | 
1095  | 0  |         goto fail;  | 
1096  | 0  |     }  | 
1097  | 0  |     crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));  | 
1098  | 0  |     if (crv != CKR_OK) { | 
1099  | 0  |         goto fail;  | 
1100  | 0  |     }  | 
1101  | 0  |     crv = sftk_AddAttributeType(key, CKA_SIGN, &ck_true, sizeof(CK_BBOOL));  | 
1102  | 0  |     if (crv != CKR_OK) { | 
1103  | 0  |         goto fail;  | 
1104  | 0  |     }  | 
1105  | 0  |     crv = sftk_AddAttributeType(key, CKA_VALUE, buf, AES_BLOCK_SIZE);  | 
1106  | 0  |     if (crv != CKR_OK) { | 
1107  | 0  |         goto fail;  | 
1108  | 0  |     }  | 
1109  |  |  | 
1110  |  |     /*  | 
1111  |  |      * finish filling in the key and link it with our global system.  | 
1112  |  |      */  | 
1113  | 0  |     crv = sftk_handleObject(key, session);  | 
1114  | 0  |     if (crv != CKR_OK) { | 
1115  | 0  |         goto fail;  | 
1116  | 0  |     }  | 
1117  | 0  |     *phKey = key->handle;  | 
1118  | 0  | fail:  | 
1119  | 0  |     if (session) { | 
1120  | 0  |         sftk_FreeSession(session);  | 
1121  | 0  |     }  | 
1122  |  | 
  | 
1123  | 0  |     if (inKeyValue) { | 
1124  | 0  |         sftk_FreeAttribute(inKeyValue);  | 
1125  | 0  |     }  | 
1126  | 0  |     if (inKeyObj) { | 
1127  | 0  |         sftk_FreeObject(inKeyObj);  | 
1128  | 0  |     }  | 
1129  | 0  |     if (key) { | 
1130  | 0  |         sftk_FreeObject(key);  | 
1131  | 0  |     }  | 
1132  |  |     /* clear our CSPs */  | 
1133  | 0  |     PORT_Memset(buf, 0, sizeof(buf));  | 
1134  | 0  |     if (crv != CKR_OK) { | 
1135  | 0  |         PORT_Memset(k2, 0, AES_BLOCK_SIZE);  | 
1136  | 0  |         PORT_Memset(k3, 0, AES_BLOCK_SIZE);  | 
1137  | 0  |     }  | 
1138  | 0  |     return crv;  | 
1139  | 0  | }  | 
1140  |  |  | 
1141  |  | /*  | 
1142  |  |  * Helper function that tests a single prf test vector  | 
1143  |  |  */  | 
1144  |  | static SECStatus  | 
1145  |  | prf_test(CK_MECHANISM_TYPE mech,  | 
1146  |  |          const unsigned char *inKey, unsigned int inKeyLen,  | 
1147  |  |          const unsigned char *plainText, unsigned int plainTextLen,  | 
1148  |  |          const unsigned char *expectedResult, unsigned int expectedResultLen)  | 
1149  | 0  | { | 
1150  | 0  |     PRUint8 ike_computed_mac[HASH_LENGTH_MAX];  | 
1151  | 0  |     prfContext context;  | 
1152  | 0  |     unsigned int macSize;  | 
1153  | 0  |     CK_RV crv;  | 
1154  |  | 
  | 
1155  | 0  |     crv = prf_setup(&context, mech);  | 
1156  | 0  |     if (crv != CKR_OK) { | 
1157  | 0  |         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);  | 
1158  | 0  |         return SECFailure;  | 
1159  | 0  |     }  | 
1160  | 0  |     macSize = prf_length(&context);  | 
1161  | 0  |     crv = prf_init(&context, inKey, inKeyLen);  | 
1162  | 0  |     if (crv != CKR_OK) { | 
1163  | 0  |         goto fail;  | 
1164  | 0  |     }  | 
1165  | 0  |     crv = prf_update(&context, plainText, plainTextLen);  | 
1166  | 0  |     if (crv != CKR_OK) { | 
1167  | 0  |         goto fail;  | 
1168  | 0  |     }  | 
1169  | 0  |     crv = prf_final(&context, ike_computed_mac, macSize);  | 
1170  | 0  |     if (crv != CKR_OK) { | 
1171  | 0  |         goto fail;  | 
1172  | 0  |     }  | 
1173  |  |  | 
1174  | 0  |     if (macSize != expectedResultLen) { | 
1175  | 0  |         goto fail;  | 
1176  | 0  |     }  | 
1177  | 0  |     if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) { | 
1178  | 0  |         goto fail;  | 
1179  | 0  |     }  | 
1180  |  |  | 
1181  |  |     /* only do the alignment if the plaintext is long enough */  | 
1182  | 0  |     if (plainTextLen <= macSize) { | 
1183  | 0  |         return SECSuccess;  | 
1184  | 0  |     }  | 
1185  | 0  |     prf_free(&context);  | 
1186  |  |     /* do it again, but this time tweak with the alignment */  | 
1187  | 0  |     crv = prf_init(&context, inKey, inKeyLen);  | 
1188  | 0  |     if (crv != CKR_OK) { | 
1189  | 0  |         goto fail;  | 
1190  | 0  |     }  | 
1191  | 0  |     crv = prf_update(&context, plainText, 1);  | 
1192  | 0  |     if (crv != CKR_OK) { | 
1193  | 0  |         goto fail;  | 
1194  | 0  |     }  | 
1195  | 0  |     crv = prf_update(&context, &plainText[1], macSize);  | 
1196  | 0  |     if (crv != CKR_OK) { | 
1197  | 0  |         goto fail;  | 
1198  | 0  |     }  | 
1199  | 0  |     crv = prf_update(&context, &plainText[1 + macSize], plainTextLen - (macSize + 1));  | 
1200  | 0  |     if (crv != CKR_OK) { | 
1201  | 0  |         goto fail;  | 
1202  | 0  |     }  | 
1203  | 0  |     crv = prf_final(&context, ike_computed_mac, macSize);  | 
1204  | 0  |     if (crv != CKR_OK) { | 
1205  | 0  |         goto fail;  | 
1206  | 0  |     }  | 
1207  | 0  |     if (PORT_Memcmp(expectedResult, ike_computed_mac, macSize) != 0) { | 
1208  | 0  |         goto fail;  | 
1209  | 0  |     }  | 
1210  | 0  |     prf_free(&context);  | 
1211  | 0  |     return SECSuccess;  | 
1212  | 0  | fail:  | 
1213  | 0  |     prf_free(&context);  | 
1214  | 0  |     PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);  | 
1215  | 0  |     return SECFailure;  | 
1216  | 0  | }  | 
1217  |  |  | 
1218  |  | /*  | 
1219  |  |  * FIPS Power up Self Tests for IKE. This is in this function so it  | 
1220  |  |  * can access the private prf_ functions here. It's called out of fipstest.c  | 
1221  |  |  */  | 
1222  |  | SECStatus  | 
1223  |  | sftk_fips_IKE_PowerUpSelfTests(void)  | 
1224  | 0  | { | 
1225  |  |     /* PRF known test vectors */  | 
1226  | 0  |     static const PRUint8 ike_xcbc_known_key[] = { | 
1227  | 0  |         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | 
1228  | 0  |         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f  | 
1229  | 0  |     };  | 
1230  | 0  |     static const PRUint8 ike_xcbc_known_plain_text[] = { | 
1231  | 0  |         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | 
1232  | 0  |         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f  | 
1233  | 0  |     };  | 
1234  | 0  |     static const PRUint8 ike_xcbc_known_mac[] = { | 
1235  | 0  |         0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7,  | 
1236  | 0  |         0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63  | 
1237  | 0  |     };  | 
1238  |  |     /* test 2 uses the same key as test 1 */  | 
1239  | 0  |     static const PRUint8 ike_xcbc_known_plain_text_2[] = { | 
1240  | 0  |         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | 
1241  | 0  |         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,  | 
1242  | 0  |         0x10, 0x11, 0x12, 0x13  | 
1243  | 0  |     };  | 
1244  | 0  |     static const PRUint8 ike_xcbc_known_mac_2[] = { | 
1245  | 0  |         0x47, 0xf5, 0x1b, 0x45, 0x64, 0x96, 0x62, 0x15,  | 
1246  | 0  |         0xb8, 0x98, 0x5c, 0x63, 0x05, 0x5e, 0xd3, 0x08  | 
1247  | 0  |     };  | 
1248  | 0  |     static const PRUint8 ike_xcbc_known_key_3[] = { | 
1249  | 0  |         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | 
1250  | 0  |         0x08, 0x09  | 
1251  | 0  |     };  | 
1252  |  |     /* test 3 uses the same plaintest as test 2 */  | 
1253  | 0  |     static const PRUint8 ike_xcbc_known_mac_3[] = { | 
1254  | 0  |         0x0f, 0xa0, 0x87, 0xaf, 0x7d, 0x86, 0x6e, 0x76,  | 
1255  | 0  |         0x53, 0x43, 0x4e, 0x60, 0x2f, 0xdd, 0xe8, 0x35  | 
1256  | 0  |     };  | 
1257  | 0  |     static const PRUint8 ike_xcbc_known_key_4[] = { | 
1258  | 0  |         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  | 
1259  | 0  |         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,  | 
1260  | 0  |         0xed, 0xcb  | 
1261  | 0  |     };  | 
1262  |  |     /* test 4 uses the same plaintest as test 2 */  | 
1263  | 0  |     static const PRUint8 ike_xcbc_known_mac_4[] = { | 
1264  | 0  |         0x8c, 0xd3, 0xc9, 0x3a, 0xe5, 0x98, 0xa9, 0x80,  | 
1265  | 0  |         0x30, 0x06, 0xff, 0xb6, 0x7c, 0x40, 0xe9, 0xe4  | 
1266  | 0  |     };  | 
1267  | 0  |     static const PRUint8 ike_sha1_known_key[] = { | 
1268  | 0  |         0x59, 0x98, 0x2b, 0x5b, 0xa5, 0x7e, 0x62, 0xc0,  | 
1269  | 0  |         0x46, 0x0d, 0xef, 0xc7, 0x1e, 0x18, 0x64, 0x63  | 
1270  | 0  |     };  | 
1271  | 0  |     static const PRUint8 ike_sha1_known_plain_text[] = { | 
1272  | 0  |         0x1c, 0x07, 0x32, 0x1a, 0x9a, 0x7e, 0x41, 0xcd,  | 
1273  | 0  |         0x88, 0x0c, 0xa3, 0x7a, 0xdb, 0x10, 0xc7, 0x3b,  | 
1274  | 0  |         0xf0, 0x0e, 0x7a, 0xe3, 0xcf, 0xc6, 0xfd, 0x8b,  | 
1275  | 0  |         0x51, 0xbc, 0xe2, 0xb9, 0x90, 0xe6, 0xf2, 0x01  | 
1276  | 0  |     };  | 
1277  | 0  |     static const PRUint8 ike_sha1_known_mac[] = { | 
1278  | 0  |         0x0c, 0x2a, 0xf3, 0x42, 0x97, 0x15, 0x62, 0x1d,  | 
1279  | 0  |         0x2a, 0xad, 0xc9, 0x94, 0x5a, 0x90, 0x26, 0xfa,  | 
1280  | 0  |         0xc7, 0x91, 0xe2, 0x4b  | 
1281  | 0  |     };  | 
1282  | 0  |     static const PRUint8 ike_sha256_known_key[] = { | 
1283  | 0  |         0x9d, 0xa2, 0xd5, 0x8f, 0x57, 0xf0, 0x39, 0xf9,  | 
1284  | 0  |         0x20, 0x4e, 0x0d, 0xd0, 0xef, 0x04, 0xf3, 0x72  | 
1285  | 0  |     };  | 
1286  | 0  |     static const PRUint8 ike_sha256_known_plain_text[] = { | 
1287  | 0  |         0x33, 0xf1, 0x7a, 0xfc, 0xb6, 0x13, 0x4c, 0xbf,  | 
1288  | 0  |         0x1c, 0xab, 0x59, 0x87, 0x7d, 0x42, 0xdb, 0x35,  | 
1289  | 0  |         0x82, 0x22, 0x6e, 0xff, 0x74, 0xdd, 0x37, 0xeb,  | 
1290  | 0  |         0x8b, 0x75, 0xe6, 0x75, 0x64, 0x5f, 0xc1, 0x69  | 
1291  | 0  |     };  | 
1292  | 0  |     static const PRUint8 ike_sha256_known_mac[] = { | 
1293  | 0  |         0x80, 0x4b, 0x4a, 0x1e, 0x0e, 0xc5, 0x93, 0xcf,  | 
1294  | 0  |         0xb6, 0xe4, 0x54, 0x52, 0x41, 0x49, 0x39, 0x6d,  | 
1295  | 0  |         0xe2, 0x34, 0xd0, 0xda, 0xe2, 0x9f, 0x34, 0xa8,  | 
1296  | 0  |         0xfd, 0xb5, 0xf9, 0xaf, 0xe7, 0x6e, 0xa6, 0x52  | 
1297  | 0  |     };  | 
1298  | 0  |     static const PRUint8 ike_sha384_known_key[] = { | 
1299  | 0  |         0xce, 0xc8, 0x9d, 0x84, 0x5a, 0xdd, 0x83, 0xef,  | 
1300  | 0  |         0xce, 0xbd, 0x43, 0xab, 0x71, 0xd1, 0x7d, 0xb9  | 
1301  | 0  |     };  | 
1302  | 0  |     static const PRUint8 ike_sha384_known_plain_text[] = { | 
1303  | 0  |         0x17, 0x24, 0xdb, 0xd8, 0x93, 0x52, 0x37, 0x64,  | 
1304  | 0  |         0xbf, 0xef, 0x8c, 0x6f, 0xa9, 0x27, 0x85, 0x6f,  | 
1305  | 0  |         0xcc, 0xfb, 0x77, 0xae, 0x25, 0x43, 0x58, 0xcc,  | 
1306  | 0  |         0xe2, 0x9c, 0x27, 0x69, 0xa3, 0x29, 0x15, 0xc1  | 
1307  | 0  |     };  | 
1308  | 0  |     static const PRUint8 ike_sha384_known_mac[] = { | 
1309  | 0  |         0x6e, 0x45, 0x14, 0x61, 0x0b, 0xf8, 0x2d, 0x0a,  | 
1310  | 0  |         0xb7, 0xbf, 0x02, 0x60, 0x09, 0x6f, 0x61, 0x46,  | 
1311  | 0  |         0xa1, 0x53, 0xc7, 0x12, 0x07, 0x1a, 0xbb, 0x63,  | 
1312  | 0  |         0x3c, 0xed, 0x81, 0x3c, 0x57, 0x21, 0x56, 0xc7,  | 
1313  | 0  |         0x83, 0xe3, 0x68, 0x74, 0xa6, 0x5a, 0x64, 0x69,  | 
1314  | 0  |         0x0c, 0xa7, 0x01, 0xd4, 0x0d, 0x56, 0xea, 0x18  | 
1315  | 0  |     };  | 
1316  | 0  |     static const PRUint8 ike_sha512_known_key[] = { | 
1317  | 0  |         0xac, 0xad, 0xc6, 0x31, 0x4a, 0x69, 0xcf, 0xcd,  | 
1318  | 0  |         0x4e, 0x4a, 0xd1, 0x77, 0x18, 0xfe, 0xa7, 0xce  | 
1319  | 0  |     };  | 
1320  | 0  |     static const PRUint8 ike_sha512_known_plain_text[] = { | 
1321  | 0  |         0xb1, 0x5a, 0x9c, 0xfc, 0xe8, 0xc8, 0xd7, 0xea,  | 
1322  | 0  |         0xb8, 0x79, 0xd6, 0x24, 0x30, 0x29, 0xd4, 0x01,  | 
1323  | 0  |         0x88, 0xd3, 0xb7, 0x40, 0x87, 0x5a, 0x6a, 0xc6,  | 
1324  | 0  |         0x2f, 0x56, 0xca, 0xc4, 0x37, 0x7e, 0x2e, 0xdd  | 
1325  | 0  |     };  | 
1326  | 0  |     static const PRUint8 ike_sha512_known_mac[] = { | 
1327  | 0  |         0xf0, 0x5a, 0xa0, 0x36, 0xdf, 0xce, 0x45, 0xa5,  | 
1328  | 0  |         0x58, 0xd4, 0x04, 0x18, 0xde, 0xa9, 0x80, 0x96,  | 
1329  | 0  |         0xe5, 0x19, 0xbc, 0x78, 0x41, 0xe3, 0xdb, 0x3d,  | 
1330  | 0  |         0xd9, 0x36, 0x58, 0xd1, 0x18, 0xc3, 0xe8, 0x3b,  | 
1331  | 0  |         0x50, 0x2f, 0x39, 0x8e, 0xcb, 0x13, 0x61, 0xec,  | 
1332  | 0  |         0x77, 0xd3, 0x8a, 0x88, 0x55, 0xef, 0xff, 0x40,  | 
1333  | 0  |         0x7f, 0x6f, 0x77, 0x2e, 0x5d, 0x65, 0xb5, 0x8e,  | 
1334  | 0  |         0xb1, 0x13, 0x40, 0x96, 0xe8, 0x47, 0x8d, 0x2b  | 
1335  | 0  |     };  | 
1336  | 0  |     static const PRUint8 ike_known_sha256_prf_plus[] = { | 
1337  | 0  |         0xe6, 0xf1, 0x9b, 0x4a, 0x02, 0xe9, 0x73, 0x72,  | 
1338  | 0  |         0x93, 0x9f, 0xdb, 0x46, 0x1d, 0xb1, 0x49, 0xcb,  | 
1339  | 0  |         0x53, 0x08, 0x98, 0x3d, 0x41, 0x36, 0xfa, 0x8b,  | 
1340  | 0  |         0x47, 0x04, 0x49, 0x11, 0x0d, 0x6e, 0x96, 0x1d,  | 
1341  | 0  |         0xab, 0xbe, 0x94, 0x28, 0xa0, 0xb7, 0x9c, 0xa3,  | 
1342  | 0  |         0x29, 0xe1, 0x40, 0xf8, 0xf8, 0x88, 0xb9, 0xb5,  | 
1343  | 0  |         0x40, 0xd4, 0x54, 0x4d, 0x25, 0xab, 0x94, 0xd4,  | 
1344  | 0  |         0x98, 0xd8, 0x00, 0xbf, 0x6f, 0xef, 0xe8, 0x39  | 
1345  | 0  |     };  | 
1346  | 0  |     SECStatus rv;  | 
1347  | 0  |     CK_RV crv;  | 
1348  | 0  |     unsigned char *outKeyData = NULL;  | 
1349  | 0  |     unsigned int outKeySize;  | 
1350  | 0  |     CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike_params;  | 
1351  |  | 
  | 
1352  | 0  |     rv = prf_test(CKM_AES_XCBC_MAC,  | 
1353  | 0  |                   ike_xcbc_known_key, sizeof(ike_xcbc_known_key),  | 
1354  | 0  |                   ike_xcbc_known_plain_text, sizeof(ike_xcbc_known_plain_text),  | 
1355  | 0  |                   ike_xcbc_known_mac, sizeof(ike_xcbc_known_mac));  | 
1356  | 0  |     if (rv != SECSuccess)  | 
1357  | 0  |         return rv;  | 
1358  | 0  |     rv = prf_test(CKM_AES_XCBC_MAC,  | 
1359  | 0  |                   ike_xcbc_known_key, sizeof(ike_xcbc_known_key),  | 
1360  | 0  |                   ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),  | 
1361  | 0  |                   ike_xcbc_known_mac_2, sizeof(ike_xcbc_known_mac_2));  | 
1362  | 0  |     if (rv != SECSuccess)  | 
1363  | 0  |         return rv;  | 
1364  | 0  |     rv = prf_test(CKM_AES_XCBC_MAC,  | 
1365  | 0  |                   ike_xcbc_known_key_3, sizeof(ike_xcbc_known_key_3),  | 
1366  | 0  |                   ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),  | 
1367  | 0  |                   ike_xcbc_known_mac_3, sizeof(ike_xcbc_known_mac_3));  | 
1368  | 0  |     if (rv != SECSuccess)  | 
1369  | 0  |         return rv;  | 
1370  | 0  |     rv = prf_test(CKM_AES_XCBC_MAC,  | 
1371  | 0  |                   ike_xcbc_known_key_4, sizeof(ike_xcbc_known_key_4),  | 
1372  | 0  |                   ike_xcbc_known_plain_text_2, sizeof(ike_xcbc_known_plain_text_2),  | 
1373  | 0  |                   ike_xcbc_known_mac_4, sizeof(ike_xcbc_known_mac_4));  | 
1374  | 0  |     if (rv != SECSuccess)  | 
1375  | 0  |         return rv;  | 
1376  | 0  |     rv = prf_test(CKM_SHA_1_HMAC,  | 
1377  | 0  |                   ike_sha1_known_key, sizeof(ike_sha1_known_key),  | 
1378  | 0  |                   ike_sha1_known_plain_text, sizeof(ike_sha1_known_plain_text),  | 
1379  | 0  |                   ike_sha1_known_mac, sizeof(ike_sha1_known_mac));  | 
1380  | 0  |     if (rv != SECSuccess)  | 
1381  | 0  |         return rv;  | 
1382  | 0  |     rv = prf_test(CKM_SHA256_HMAC,  | 
1383  | 0  |                   ike_sha256_known_key, sizeof(ike_sha256_known_key),  | 
1384  | 0  |                   ike_sha256_known_plain_text,  | 
1385  | 0  |                   sizeof(ike_sha256_known_plain_text),  | 
1386  | 0  |                   ike_sha256_known_mac, sizeof(ike_sha256_known_mac));  | 
1387  | 0  |     if (rv != SECSuccess)  | 
1388  | 0  |         return rv;  | 
1389  | 0  |     rv = prf_test(CKM_SHA384_HMAC,  | 
1390  | 0  |                   ike_sha384_known_key, sizeof(ike_sha384_known_key),  | 
1391  | 0  |                   ike_sha384_known_plain_text,  | 
1392  | 0  |                   sizeof(ike_sha384_known_plain_text),  | 
1393  | 0  |                   ike_sha384_known_mac, sizeof(ike_sha384_known_mac));  | 
1394  | 0  |     if (rv != SECSuccess)  | 
1395  | 0  |         return rv;  | 
1396  | 0  |     rv = prf_test(CKM_SHA512_HMAC,  | 
1397  | 0  |                   ike_sha512_known_key, sizeof(ike_sha512_known_key),  | 
1398  | 0  |                   ike_sha512_known_plain_text,  | 
1399  | 0  |                   sizeof(ike_sha512_known_plain_text),  | 
1400  | 0  |                   ike_sha512_known_mac, sizeof(ike_sha512_known_mac));  | 
1401  |  | 
  | 
1402  | 0  |     ike_params.prfMechanism = CKM_SHA256_HMAC;  | 
1403  | 0  |     ike_params.bHasSeedKey = PR_FALSE;  | 
1404  | 0  |     ike_params.hSeedKey = CK_INVALID_HANDLE;  | 
1405  | 0  |     ike_params.pSeedData = (CK_BYTE_PTR)ike_sha256_known_plain_text;  | 
1406  | 0  |     ike_params.ulSeedDataLen = sizeof(ike_sha256_known_plain_text);  | 
1407  | 0  |     crv = sftk_ike_prf_plus_raw(CK_INVALID_HANDLE, ike_sha256_known_key,  | 
1408  | 0  |                                 sizeof(ike_sha256_known_key), &ike_params,  | 
1409  | 0  |                                 &outKeyData, &outKeySize, 64);  | 
1410  | 0  |     if ((crv != CKR_OK) ||  | 
1411  | 0  |         (outKeySize != sizeof(ike_known_sha256_prf_plus)) ||  | 
1412  | 0  |         (PORT_Memcmp(outKeyData, ike_known_sha256_prf_plus,  | 
1413  | 0  |                      sizeof(ike_known_sha256_prf_plus)) != 0)) { | 
1414  | 0  |         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);  | 
1415  | 0  |         return SECFailure;  | 
1416  | 0  |     }  | 
1417  | 0  |     PORT_ZFree(outKeyData, outKeySize);  | 
1418  | 0  |     return rv;  | 
1419  | 0  | }  |