Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/pk11wrap/pk11akey.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 contains functions to manage asymetric keys, (public and | |
6 * private keys). | |
7 */ | |
8 #include "seccomon.h" | |
9 #include "secmod.h" | |
10 #include "secmodi.h" | |
11 #include "secmodti.h" | |
12 #include "pkcs11.h" | |
13 #include "pkcs11t.h" | |
14 #include "pk11func.h" | |
15 #include "cert.h" | |
16 #include "key.h" | |
17 #include "secitem.h" | |
18 #include "secasn1.h" | |
19 #include "secoid.h" | |
20 #include "secerr.h" | |
21 #include "sslerr.h" | |
22 #include "sechash.h" | |
23 | |
24 #include "secpkcs5.h" | |
25 #include "blapit.h" | |
26 | |
27 static SECItem * | |
28 pk11_MakeIDFromPublicKey(SECKEYPublicKey *pubKey) | |
29 { | |
30 /* set the ID to the public key so we can find it again */ | |
31 SECItem *pubKeyIndex = NULL; | |
32 switch (pubKey->keyType) { | |
33 case rsaKey: | |
34 pubKeyIndex = &pubKey->u.rsa.modulus; | |
35 break; | |
36 case dsaKey: | |
37 pubKeyIndex = &pubKey->u.dsa.publicValue; | |
38 break; | |
39 case dhKey: | |
40 pubKeyIndex = &pubKey->u.dh.publicValue; | |
41 break; | |
42 case ecKey: | |
43 pubKeyIndex = &pubKey->u.ec.publicValue; | |
44 break; | |
45 default: | |
46 return NULL; | |
47 } | |
48 PORT_Assert(pubKeyIndex != NULL); | |
49 | |
50 return PK11_MakeIDFromPubKey(pubKeyIndex); | |
51 } | |
52 | |
53 /* | |
54 * import a public key into the desired slot | |
55 * | |
56 * This function takes a public key structure and creates a public key in a | |
57 * given slot. If isToken is set, then a persistant public key is created. | |
58 * | |
59 * Note: it is possible for this function to return a handle for a key which | |
60 * is persistant, even if isToken is not set. | |
61 */ | |
62 CK_OBJECT_HANDLE | |
63 PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, | |
64 PRBool isToken) | |
65 { | |
66 CK_BBOOL cktrue = CK_TRUE; | |
67 CK_BBOOL ckfalse = CK_FALSE; | |
68 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; | |
69 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
70 CK_OBJECT_HANDLE objectID; | |
71 CK_ATTRIBUTE theTemplate[11]; | |
72 CK_ATTRIBUTE *signedattr = NULL; | |
73 CK_ATTRIBUTE *attrs = theTemplate; | |
74 SECItem *ckaId = NULL; | |
75 SECItem *pubValue = NULL; | |
76 int signedcount = 0; | |
77 int templateCount = 0; | |
78 SECStatus rv; | |
79 | |
80 /* if we already have an object in the desired slot, use it */ | |
81 if (!isToken && pubKey->pkcs11Slot == slot) { | |
82 return pubKey->pkcs11ID; | |
83 } | |
84 | |
85 /* free the existing key */ | |
86 if (pubKey->pkcs11Slot != NULL) { | |
87 PK11SlotInfo *oSlot = pubKey->pkcs11Slot; | |
88 if (!PK11_IsPermObject(pubKey->pkcs11Slot,pubKey->pkcs11ID)) { | |
89 PK11_EnterSlotMonitor(oSlot); | |
90 (void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session, | |
91 pubKey->pkcs11ID); | |
92 PK11_ExitSlotMonitor(oSlot); | |
93 } | |
94 PK11_FreeSlot(oSlot); | |
95 pubKey->pkcs11Slot = NULL; | |
96 } | |
97 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; | |
98 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; | |
99 PK11_SETATTRS(attrs, CKA_TOKEN, isToken ? &cktrue : &ckfalse, | |
100 sizeof(CK_BBOOL) ); attrs++; | |
101 if (isToken) { | |
102 ckaId = pk11_MakeIDFromPublicKey(pubKey); | |
103 if (ckaId == NULL) { | |
104 PORT_SetError( SEC_ERROR_BAD_KEY ); | |
105 return CK_INVALID_HANDLE; | |
106 } | |
107 PK11_SETATTRS(attrs, CKA_ID, ckaId->data, ckaId->len); attrs++; | |
108 } | |
109 | |
110 /* now import the key */ | |
111 { | |
112 switch (pubKey->keyType) { | |
113 case rsaKey: | |
114 keyType = CKK_RSA; | |
115 PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, sizeof(CK_BBOOL) ); attrs++; | |
116 PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue, | |
117 sizeof(CK_BBOOL) ); attrs++; | |
118 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); attrs++; | |
119 signedattr = attrs; | |
120 PK11_SETATTRS(attrs, CKA_MODULUS, pubKey->u.rsa.modulus.data, | |
121 pubKey->u.rsa.modulus.len); attrs++; | |
122 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, | |
123 pubKey->u.rsa.publicExponent.data, | |
124 pubKey->u.rsa.publicExponent.len); attrs++; | |
125 break; | |
126 case dsaKey: | |
127 keyType = CKK_DSA; | |
128 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++; | |
129 signedattr = attrs; | |
130 PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.dsa.params.prime.data, | |
131 pubKey->u.dsa.params.prime.len); attrs++; | |
132 PK11_SETATTRS(attrs,CKA_SUBPRIME,pubKey->u.dsa.params.subPrime.data, | |
133 pubKey->u.dsa.params.subPrime.len); attrs++; | |
134 PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.dsa.params.base.data, | |
135 pubKey->u.dsa.params.base.len); attrs++; | |
136 PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dsa.publicValue.data, | |
137 pubKey->u.dsa.publicValue.len); attrs++; | |
138 break; | |
139 case dhKey: | |
140 keyType = CKK_DH; | |
141 PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++; | |
142 signedattr = attrs; | |
143 PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.dh.prime.data, | |
144 pubKey->u.dh.prime.len); attrs++; | |
145 PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.dh.base.data, | |
146 pubKey->u.dh.base.len); attrs++; | |
147 PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dh.publicValue.data, | |
148 pubKey->u.dh.publicValue.len); attrs++; | |
149 break; | |
150 case ecKey: | |
151 keyType = CKK_EC; | |
152 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++; | |
153 PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++; | |
154 signedattr = attrs; | |
155 PK11_SETATTRS(attrs, CKA_EC_PARAMS, | |
156 pubKey->u.ec.DEREncodedParams.data, | |
157 pubKey->u.ec.DEREncodedParams.len); attrs++; | |
158 if (PR_GetEnv("NSS_USE_DECODED_CKA_EC_POINT")) { | |
159 PK11_SETATTRS(attrs, CKA_EC_POINT, | |
160 pubKey->u.ec.publicValue.data, | |
161 pubKey->u.ec.publicValue.len); attrs++; | |
162 } else { | |
163 pubValue = SEC_ASN1EncodeItem(NULL, NULL, | |
164 &pubKey->u.ec.publicValue, | |
165 SEC_ASN1_GET(SEC_OctetStringTemplate)); | |
166 if (pubValue == NULL) { | |
167 if (ckaId) { | |
168 SECITEM_FreeItem(ckaId,PR_TRUE); | |
169 } | |
170 return CK_INVALID_HANDLE; | |
171 } | |
172 PK11_SETATTRS(attrs, CKA_EC_POINT, | |
173 pubValue->data, pubValue->len); attrs++; | |
174 } | |
175 break; | |
176 default: | |
177 if (ckaId) { | |
178 SECITEM_FreeItem(ckaId,PR_TRUE); | |
179 } | |
180 PORT_SetError( SEC_ERROR_BAD_KEY ); | |
181 return CK_INVALID_HANDLE; | |
182 } | |
183 | |
184 templateCount = attrs - theTemplate; | |
185 signedcount = attrs - signedattr; | |
186 PORT_Assert(templateCount <= (sizeof(theTemplate)/sizeof(CK_ATTRIBUTE))); | |
187 for (attrs=signedattr; signedcount; attrs++, signedcount--) { | |
188 pk11_SignedToUnsigned(attrs); | |
189 } | |
190 rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate, | |
191 templateCount, isToken, &objectID); | |
192 if (ckaId) { | |
193 SECITEM_FreeItem(ckaId,PR_TRUE); | |
194 } | |
195 if (pubValue) { | |
196 SECITEM_FreeItem(pubValue,PR_TRUE); | |
197 } | |
198 if ( rv != SECSuccess) { | |
199 /* CKR_ATTRIBUTE_VALUE_INVALID is mapped to SEC_ERROR_BAD_DATA */ | |
200 if (PORT_GetError() == SEC_ERROR_BAD_DATA) { | |
201 PORT_SetError( SEC_ERROR_BAD_KEY ); | |
202 } | |
203 return CK_INVALID_HANDLE; | |
204 } | |
205 } | |
206 | |
207 pubKey->pkcs11ID = objectID; | |
208 pubKey->pkcs11Slot = PK11_ReferenceSlot(slot); | |
209 | |
210 return objectID; | |
211 } | |
212 | |
213 /* | |
214 * take an attribute and copy it into a secitem | |
215 */ | |
216 static CK_RV | |
217 pk11_Attr2SecItem(PLArenaPool *arena, const CK_ATTRIBUTE *attr, SECItem *item) | |
218 { | |
219 item->data = NULL; | |
220 | |
221 (void)SECITEM_AllocItem(arena, item, attr->ulValueLen); | |
222 if (item->data == NULL) { | |
223 return CKR_HOST_MEMORY; | |
224 } | |
225 PORT_Memcpy(item->data, attr->pValue, item->len); | |
226 return CKR_OK; | |
227 } | |
228 | |
229 | |
230 /* | |
231 * get a curve length from a set of ecParams. | |
232 * | |
233 * We need this so we can reliably determine if the ecPoint passed to us | |
234 * was encoded or not. With out this, for many curves, we would incorrectly | |
235 * identify an unencoded curve as an encoded curve 1 in 65536 times, and for | |
236 * a few we would make that same mistake 1 in 32768 times. These are bad | |
237 * numbers since they are rare enough to pass tests, but common enough to | |
238 * be tripped over in the field. | |
239 * | |
240 * This function will only work for curves we recognized as of March 2009. | |
241 * The assumption is curves in use after March of 2009 would be supplied by | |
242 * PKCS #11 modules that already pass the correct encoding to us. | |
243 * | |
244 * Point length = (Roundup(curveLenInBits/8)*2+1) | |
245 */ | |
246 static int | |
247 pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams) | |
248 { | |
249 SECItem oid; | |
250 SECOidTag tag; | |
251 SECStatus rv; | |
252 | |
253 /* decode the OID tag */ | |
254 rv = SEC_QuickDERDecodeItem(arena, &oid, | |
255 SEC_ASN1_GET(SEC_ObjectIDTemplate), ecParams); | |
256 if (rv != SECSuccess) { | |
257 /* could be explict curves, allow them to work if the | |
258 * PKCS #11 module support them. If we try to parse the | |
259 * explicit curve value in the future, we may return -1 here | |
260 * to indicate an invalid parameter if the explicit curve | |
261 * decode fails. */ | |
262 return 0; | |
263 } | |
264 | |
265 tag = SECOID_FindOIDTag(&oid); | |
266 switch (tag) { | |
267 case SEC_OID_SECG_EC_SECP112R1: | |
268 case SEC_OID_SECG_EC_SECP112R2: | |
269 return 29; /* curve len in bytes = 14 bytes */ | |
270 case SEC_OID_SECG_EC_SECT113R1: | |
271 case SEC_OID_SECG_EC_SECT113R2: | |
272 return 31; /* curve len in bytes = 15 bytes */ | |
273 case SEC_OID_SECG_EC_SECP128R1: | |
274 case SEC_OID_SECG_EC_SECP128R2: | |
275 return 33; /* curve len in bytes = 16 bytes */ | |
276 case SEC_OID_SECG_EC_SECT131R1: | |
277 case SEC_OID_SECG_EC_SECT131R2: | |
278 return 35; /* curve len in bytes = 17 bytes */ | |
279 case SEC_OID_SECG_EC_SECP160K1: | |
280 case SEC_OID_SECG_EC_SECP160R1: | |
281 case SEC_OID_SECG_EC_SECP160R2: | |
282 return 41; /* curve len in bytes = 20 bytes */ | |
283 case SEC_OID_SECG_EC_SECT163K1: | |
284 case SEC_OID_SECG_EC_SECT163R1: | |
285 case SEC_OID_SECG_EC_SECT163R2: | |
286 case SEC_OID_ANSIX962_EC_C2PNB163V1: | |
287 case SEC_OID_ANSIX962_EC_C2PNB163V2: | |
288 case SEC_OID_ANSIX962_EC_C2PNB163V3: | |
289 return 43; /* curve len in bytes = 21 bytes */ | |
290 case SEC_OID_ANSIX962_EC_C2PNB176V1: | |
291 return 45; /* curve len in bytes = 22 bytes */ | |
292 case SEC_OID_ANSIX962_EC_C2TNB191V1: | |
293 case SEC_OID_ANSIX962_EC_C2TNB191V2: | |
294 case SEC_OID_ANSIX962_EC_C2TNB191V3: | |
295 case SEC_OID_SECG_EC_SECP192K1: | |
296 case SEC_OID_ANSIX962_EC_PRIME192V1: | |
297 case SEC_OID_ANSIX962_EC_PRIME192V2: | |
298 case SEC_OID_ANSIX962_EC_PRIME192V3: | |
299 return 49; /*curve len in bytes = 24 bytes */ | |
300 case SEC_OID_SECG_EC_SECT193R1: | |
301 case SEC_OID_SECG_EC_SECT193R2: | |
302 return 51; /*curve len in bytes = 25 bytes */ | |
303 case SEC_OID_ANSIX962_EC_C2PNB208W1: | |
304 return 53; /*curve len in bytes = 26 bytes */ | |
305 case SEC_OID_SECG_EC_SECP224K1: | |
306 case SEC_OID_SECG_EC_SECP224R1: | |
307 return 57; /*curve len in bytes = 28 bytes */ | |
308 case SEC_OID_SECG_EC_SECT233K1: | |
309 case SEC_OID_SECG_EC_SECT233R1: | |
310 case SEC_OID_SECG_EC_SECT239K1: | |
311 case SEC_OID_ANSIX962_EC_PRIME239V1: | |
312 case SEC_OID_ANSIX962_EC_PRIME239V2: | |
313 case SEC_OID_ANSIX962_EC_PRIME239V3: | |
314 case SEC_OID_ANSIX962_EC_C2TNB239V1: | |
315 case SEC_OID_ANSIX962_EC_C2TNB239V2: | |
316 case SEC_OID_ANSIX962_EC_C2TNB239V3: | |
317 return 61; /*curve len in bytes = 30 bytes */ | |
318 case SEC_OID_ANSIX962_EC_PRIME256V1: | |
319 case SEC_OID_SECG_EC_SECP256K1: | |
320 return 65; /*curve len in bytes = 32 bytes */ | |
321 case SEC_OID_ANSIX962_EC_C2PNB272W1: | |
322 return 69; /*curve len in bytes = 34 bytes */ | |
323 case SEC_OID_SECG_EC_SECT283K1: | |
324 case SEC_OID_SECG_EC_SECT283R1: | |
325 return 73; /*curve len in bytes = 36 bytes */ | |
326 case SEC_OID_ANSIX962_EC_C2PNB304W1: | |
327 return 77; /*curve len in bytes = 38 bytes */ | |
328 case SEC_OID_ANSIX962_EC_C2TNB359V1: | |
329 return 91; /*curve len in bytes = 45 bytes */ | |
330 case SEC_OID_ANSIX962_EC_C2PNB368W1: | |
331 return 93; /*curve len in bytes = 46 bytes */ | |
332 case SEC_OID_SECG_EC_SECP384R1: | |
333 return 97; /*curve len in bytes = 48 bytes */ | |
334 case SEC_OID_SECG_EC_SECT409K1: | |
335 case SEC_OID_SECG_EC_SECT409R1: | |
336 return 105; /*curve len in bytes = 52 bytes */ | |
337 case SEC_OID_ANSIX962_EC_C2TNB431R1: | |
338 return 109; /*curve len in bytes = 54 bytes */ | |
339 case SEC_OID_SECG_EC_SECP521R1: | |
340 return 133; /*curve len in bytes = 66 bytes */ | |
341 case SEC_OID_SECG_EC_SECT571K1: | |
342 case SEC_OID_SECG_EC_SECT571R1: | |
343 return 145; /*curve len in bytes = 72 bytes */ | |
344 /* unknown or unrecognized OIDs. return unknown length */ | |
345 default: | |
346 break; | |
347 } | |
348 return 0; | |
349 } | |
350 | |
351 /* | |
352 * returns the decoded point. In some cases the point may already be decoded. | |
353 * this function tries to detect those cases and return the point in | |
354 * publicKeyValue. In other cases it's DER encoded. In those cases the point | |
355 * is first decoded and returned. Space for the point is allocated out of | |
356 * the passed in arena. | |
357 */ | |
358 static CK_RV | |
359 pk11_get_Decoded_ECPoint(PLArenaPool *arena, const SECItem *ecParams, | |
360 const CK_ATTRIBUTE *ecPoint, SECItem *publicKeyValue) | |
361 { | |
362 SECItem encodedPublicValue; | |
363 SECStatus rv; | |
364 int keyLen; | |
365 | |
366 if (ecPoint->ulValueLen == 0) { | |
367 return CKR_ATTRIBUTE_VALUE_INVALID; | |
368 } | |
369 | |
370 /* | |
371 * The PKCS #11 spec requires ecPoints to be encoded as a DER OCTET String. | |
372 * NSS has mistakenly passed unencoded values, and some PKCS #11 vendors | |
373 * followed that mistake. Now we need to detect which encoding we were | |
374 * passed in. The task is made more complicated by the fact the the | |
375 * DER encoding byte (SEC_ASN_OCTET_STRING) is the same as the | |
376 * EC_POINT_FORM_UNCOMPRESSED byte (0x04), so we can't use that to | |
377 * determine which curve we are using. | |
378 */ | |
379 | |
380 /* get the expected key length for the passed in curve. | |
381 * pk11_get_EC_PointLenInBytes only returns valid values for curves | |
382 * NSS has traditionally recognized. If the curve is not recognized, | |
383 * it will return '0', and we have to figure out if the key was | |
384 * encoded or not heuristically. If the ecParams are invalid, it | |
385 * will return -1 for the keyLen. | |
386 */ | |
387 keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams); | |
388 if (keyLen < 0) { | |
389 return CKR_ATTRIBUTE_VALUE_INVALID; | |
390 } | |
391 | |
392 | |
393 /* If the point is uncompressed and the lengths match, it | |
394 * must be an unencoded point */ | |
395 if ((*((char *)ecPoint->pValue) == EC_POINT_FORM_UNCOMPRESSED) | |
396 && (ecPoint->ulValueLen == keyLen)) { | |
397 return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue); | |
398 } | |
399 | |
400 /* now assume the key passed to us was encoded and decode it */ | |
401 if (*((char *)ecPoint->pValue) == SEC_ASN1_OCTET_STRING) { | |
402 /* OK, now let's try to decode it and see if it's valid */ | |
403 encodedPublicValue.data = ecPoint->pValue; | |
404 encodedPublicValue.len = ecPoint->ulValueLen; | |
405 rv = SEC_QuickDERDecodeItem(arena, publicKeyValue, | |
406 SEC_ASN1_GET(SEC_OctetStringTemplate), &encodedPublicValue); | |
407 | |
408 /* it coded correctly & we know the key length (and they match) | |
409 * then we are done, return the results. */ | |
410 if (keyLen && rv == SECSuccess && publicKeyValue->len == keyLen) { | |
411 return CKR_OK; | |
412 } | |
413 | |
414 /* if we know the key length, one of the above tests should have | |
415 * succeded. If it doesn't the module gave us bad data */ | |
416 if (keyLen) { | |
417 return CKR_ATTRIBUTE_VALUE_INVALID; | |
418 } | |
419 | |
420 | |
421 /* We don't know the key length, so we don't know deterministically | |
422 * which encoding was used. We now will try to pick the most likely | |
423 * form that's correct, with a preference for the encoded form if we | |
424 * can't determine for sure. We do this by checking the key we got | |
425 * back from SEC_QuickDERDecodeItem for defects. If no defects are | |
426 * found, we assume the encoded parameter was was passed to us. | |
427 * our defect tests include: | |
428 * 1) it didn't decode. | |
429 * 2) The decode key had an invalid length (must be odd). | |
430 * 3) The decoded key wasn't an UNCOMPRESSED key. | |
431 * 4) The decoded key didn't include the entire encoded block | |
432 * except the DER encoding values. (fixing DER length to one | |
433 * particular value). | |
434 */ | |
435 if ((rv != SECSuccess) | |
436 || ((publicKeyValue->len & 1) != 1) | |
437 || (publicKeyValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) | |
438 || (PORT_Memcmp(&encodedPublicValue.data[encodedPublicValue.len - | |
439 publicKeyValue->len], publicKeyValue->data, | |
440 publicKeyValue->len) != 0)) { | |
441 /* The decoded public key was flawed, the original key must have | |
442 * already been in decoded form. Do a quick sanity check then | |
443 * return the original key value. | |
444 */ | |
445 if ((encodedPublicValue.len & 1) == 0) { | |
446 return CKR_ATTRIBUTE_VALUE_INVALID; | |
447 } | |
448 return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue); | |
449 } | |
450 | |
451 /* as best we can figure, the passed in key was encoded, and we've | |
452 * now decoded it. Note: there is a chance this could be wrong if the | |
453 * following conditions hold: | |
454 * 1) The first byte or bytes of the X point looks like a valid length | |
455 * of precisely the right size (2*curveSize -1). this means for curves | |
456 * less than 512 bits (64 bytes), this will happen 1 in 256 times*. | |
457 * for curves between 512 and 1024, this will happen 1 in 65,536 times* | |
458 * for curves between 1024 and 256K this will happen 1 in 16 million* | |
459 * 2) The length of the 'DER length field' is odd | |
460 * (making both the encoded and decode | |
461 * values an odd length. this is true of all curves less than 512, | |
462 * as well as curves between 1024 and 256K). | |
463 * 3) The X[length of the 'DER length field'] == 0x04, 1 in 256. | |
464 * | |
465 * (* assuming all values are equally likely in the first byte, | |
466 * This isn't true if the curve length is not a multiple of 8. In these | |
467 * cases, if the DER length is possible, it's more likely, | |
468 * if it's not possible, then we have no false decodes). | |
469 * | |
470 * For reference here are the odds for the various curves we currently | |
471 * have support for (and the only curves SSL will negotiate at this | |
472 * time). NOTE: None of the supported curves will show up here | |
473 * because we return a valid length for all of these curves. | |
474 * The only way to get here is to have some application (not SSL) | |
475 * which supports some unknown curve and have some vendor supplied | |
476 * PKCS #11 module support that curve. NOTE: in this case, one | |
477 * presumes that that pkcs #11 module is likely to be using the | |
478 * correct encodings. | |
479 * | |
480 * Prime Curves (GFp): | |
481 * Bit False Odds of | |
482 * Size DER Len False Decode Positive | |
483 * 112 27 1 in 65536 | |
484 * 128 31 1 in 65536 | |
485 * 160 39 1 in 65536 | |
486 * 192 47 1 in 65536 | |
487 * 224 55 1 in 65536 | |
488 * 239 59 1 in 32768 (top byte can only be 0-127) | |
489 * 256 63 1 in 65536 | |
490 * 521 129,131 0 (decoded value would be even) | |
491 * | |
492 * Binary curves (GF2m). | |
493 * Bit False Odds of | |
494 * Size DER Len False Decode Positive | |
495 * 131 33 0 (top byte can only be 0-7) | |
496 * 163 41 0 (top byte can only be 0-7) | |
497 * 176 43 1 in 65536 | |
498 * 191 47 1 in 32768 (top byte can only be 0-127) | |
499 * 193 49 0 (top byte can only be 0-1) | |
500 * 208 51 1 in 65536 | |
501 * 233 59 0 (top byte can only be 0-1) | |
502 * 239 59 1 in 32768 (top byte can only be 0-127) | |
503 * 272 67 1 in 65536 | |
504 * 283 71 0 (top byte can only be 0-7) | |
505 * 304 75 1 in 65536 | |
506 * 359 89 1 in 32768 (top byte can only be 0-127) | |
507 * 368 91 1 in 65536 | |
508 * 409 103 0 (top byte can only be 0-1) | |
509 * 431 107 1 in 32768 (top byte can only be 0-127) | |
510 * 571 129,143 0 (decoded value would be even) | |
511 * | |
512 */ | |
513 | |
514 return CKR_OK; | |
515 } | |
516 | |
517 /* In theory, we should handle the case where the curve == 0 and | |
518 * the first byte is EC_POINT_FORM_UNCOMPRESSED, (which would be | |
519 * handled by doing a santity check on the key length and returning | |
520 * pk11_Attr2SecItem() to copy the ecPoint to the publicKeyValue). | |
521 * | |
522 * This test is unnecessary, however, due to the fact that | |
523 * EC_POINT_FORM_UNCOMPRESSED == SEC_ASIN1_OCTET_STRING, that case is | |
524 * handled in the above if. That means if we get here, the initial | |
525 * byte of our ecPoint value was invalid, so we can safely return. | |
526 * invalid attribute. | |
527 */ | |
528 | |
529 return CKR_ATTRIBUTE_VALUE_INVALID; | |
530 } | |
531 | |
532 /* | |
533 * extract a public key from a slot and id | |
534 */ | |
535 SECKEYPublicKey * | |
536 PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id) | |
537 { | |
538 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY; | |
539 PLArenaPool *arena; | |
540 PLArenaPool *tmp_arena; | |
541 SECKEYPublicKey *pubKey; | |
542 int templateCount = 0; | |
543 CK_KEY_TYPE pk11KeyType; | |
544 CK_RV crv; | |
545 CK_ATTRIBUTE template[8]; | |
546 CK_ATTRIBUTE *attrs= template; | |
547 CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value; | |
548 CK_ATTRIBUTE *ecparams; | |
549 | |
550 /* if we didn't know the key type, get it */ | |
551 if (keyType== nullKey) { | |
552 | |
553 pk11KeyType = PK11_ReadULongAttribute(slot,id,CKA_KEY_TYPE); | |
554 if (pk11KeyType == CK_UNAVAILABLE_INFORMATION) { | |
555 return NULL; | |
556 } | |
557 switch (pk11KeyType) { | |
558 case CKK_RSA: | |
559 keyType = rsaKey; | |
560 break; | |
561 case CKK_DSA: | |
562 keyType = dsaKey; | |
563 break; | |
564 case CKK_DH: | |
565 keyType = dhKey; | |
566 break; | |
567 case CKK_EC: | |
568 keyType = ecKey; | |
569 break; | |
570 default: | |
571 PORT_SetError( SEC_ERROR_BAD_KEY ); | |
572 return NULL; | |
573 } | |
574 } | |
575 | |
576 | |
577 /* now we need to create space for the public key */ | |
578 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); | |
579 if (arena == NULL) return NULL; | |
580 tmp_arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); | |
581 if (tmp_arena == NULL) { | |
582 PORT_FreeArena (arena, PR_FALSE); | |
583 return NULL; | |
584 } | |
585 | |
586 | |
587 pubKey = (SECKEYPublicKey *) | |
588 PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); | |
589 if (pubKey == NULL) { | |
590 PORT_FreeArena (arena, PR_FALSE); | |
591 PORT_FreeArena (tmp_arena, PR_FALSE); | |
592 return NULL; | |
593 } | |
594 | |
595 pubKey->arena = arena; | |
596 pubKey->keyType = keyType; | |
597 pubKey->pkcs11Slot = PK11_ReferenceSlot(slot); | |
598 pubKey->pkcs11ID = id; | |
599 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, | |
600 sizeof(keyClass)); attrs++; | |
601 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType, | |
602 sizeof(pk11KeyType) ); attrs++; | |
603 switch (pubKey->keyType) { | |
604 case rsaKey: | |
605 modulus = attrs; | |
606 PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); attrs++; | |
607 exponent = attrs; | |
608 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0); attrs++; | |
609 | |
610 templateCount = attrs - template; | |
611 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE)); | |
612 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount); | |
613 if (crv != CKR_OK) break; | |
614 | |
615 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) { | |
616 crv = CKR_OBJECT_HANDLE_INVALID; | |
617 break; | |
618 } | |
619 crv = pk11_Attr2SecItem(arena,modulus,&pubKey->u.rsa.modulus); | |
620 if (crv != CKR_OK) break; | |
621 crv = pk11_Attr2SecItem(arena,exponent,&pubKey->u.rsa.publicExponent); | |
622 if (crv != CKR_OK) break; | |
623 break; | |
624 case dsaKey: | |
625 prime = attrs; | |
626 PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; | |
627 subprime = attrs; | |
628 PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++; | |
629 base = attrs; | |
630 PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; | |
631 value = attrs; | |
632 PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; | |
633 templateCount = attrs - template; | |
634 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE)); | |
635 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount); | |
636 if (crv != CKR_OK) break; | |
637 | |
638 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) { | |
639 crv = CKR_OBJECT_HANDLE_INVALID; | |
640 break; | |
641 } | |
642 crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dsa.params.prime); | |
643 if (crv != CKR_OK) break; | |
644 crv = pk11_Attr2SecItem(arena,subprime,&pubKey->u.dsa.params.subPrime); | |
645 if (crv != CKR_OK) break; | |
646 crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dsa.params.base); | |
647 if (crv != CKR_OK) break; | |
648 crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dsa.publicValue); | |
649 if (crv != CKR_OK) break; | |
650 break; | |
651 case dhKey: | |
652 prime = attrs; | |
653 PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; | |
654 base = attrs; | |
655 PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; | |
656 value =attrs; | |
657 PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; | |
658 templateCount = attrs - template; | |
659 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE)); | |
660 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount); | |
661 if (crv != CKR_OK) break; | |
662 | |
663 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) { | |
664 crv = CKR_OBJECT_HANDLE_INVALID; | |
665 break; | |
666 } | |
667 crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dh.prime); | |
668 if (crv != CKR_OK) break; | |
669 crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dh.base); | |
670 if (crv != CKR_OK) break; | |
671 crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue); | |
672 if (crv != CKR_OK) break; | |
673 break; | |
674 case ecKey: | |
675 pubKey->u.ec.size = 0; | |
676 ecparams = attrs; | |
677 PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0); attrs++; | |
678 value =attrs; | |
679 PK11_SETATTRS(attrs, CKA_EC_POINT, NULL, 0); attrs++; | |
680 templateCount = attrs - template; | |
681 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE)); | |
682 crv = PK11_GetAttributes(arena,slot,id,template,templateCount); | |
683 if (crv != CKR_OK) break; | |
684 | |
685 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_EC)) { | |
686 crv = CKR_OBJECT_HANDLE_INVALID; | |
687 break; | |
688 } | |
689 | |
690 crv = pk11_Attr2SecItem(arena,ecparams, | |
691 &pubKey->u.ec.DEREncodedParams); | |
692 if (crv != CKR_OK) break; | |
693 crv = pk11_get_Decoded_ECPoint(arena, | |
694 &pubKey->u.ec.DEREncodedParams, value, | |
695 &pubKey->u.ec.publicValue); | |
696 break; | |
697 case fortezzaKey: | |
698 case nullKey: | |
699 default: | |
700 crv = CKR_OBJECT_HANDLE_INVALID; | |
701 break; | |
702 } | |
703 | |
704 PORT_FreeArena(tmp_arena,PR_FALSE); | |
705 | |
706 if (crv != CKR_OK) { | |
707 PORT_FreeArena(arena,PR_FALSE); | |
708 PK11_FreeSlot(slot); | |
709 PORT_SetError( PK11_MapError(crv) ); | |
710 return NULL; | |
711 } | |
712 | |
713 return pubKey; | |
714 } | |
715 | |
716 /* | |
717 * Build a Private Key structure from raw PKCS #11 information. | |
718 */ | |
719 SECKEYPrivateKey * | |
720 PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, | |
721 PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx) | |
722 { | |
723 PLArenaPool *arena; | |
724 SECKEYPrivateKey *privKey; | |
725 PRBool isPrivate; | |
726 SECStatus rv; | |
727 | |
728 /* don't know? look it up */ | |
729 if (keyType == nullKey) { | |
730 CK_KEY_TYPE pk11Type = CKK_RSA; | |
731 | |
732 pk11Type = PK11_ReadULongAttribute(slot,privID,CKA_KEY_TYPE); | |
733 isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN,PR_FALSE); | |
734 switch (pk11Type) { | |
735 case CKK_RSA: keyType = rsaKey; break; | |
736 case CKK_DSA: keyType = dsaKey; break; | |
737 case CKK_DH: keyType = dhKey; break; | |
738 case CKK_KEA: keyType = fortezzaKey; break; | |
739 case CKK_EC: keyType = ecKey; break; | |
740 default: | |
741 break; | |
742 } | |
743 } | |
744 | |
745 /* if the key is private, make sure we are authenticated to the | |
746 * token before we try to use it */ | |
747 isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE,PR_FALSE); | |
748 if (isPrivate) { | |
749 rv = PK11_Authenticate(slot, PR_TRUE, wincx); | |
750 if (rv != SECSuccess) { | |
751 return NULL; | |
752 } | |
753 } | |
754 | |
755 /* now we need to create space for the private key */ | |
756 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); | |
757 if (arena == NULL) return NULL; | |
758 | |
759 privKey = (SECKEYPrivateKey *) | |
760 PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey)); | |
761 if (privKey == NULL) { | |
762 PORT_FreeArena(arena, PR_FALSE); | |
763 return NULL; | |
764 } | |
765 | |
766 privKey->arena = arena; | |
767 privKey->keyType = keyType; | |
768 privKey->pkcs11Slot = PK11_ReferenceSlot(slot); | |
769 privKey->pkcs11ID = privID; | |
770 privKey->pkcs11IsTemp = isTemp; | |
771 privKey->wincx = wincx; | |
772 | |
773 return privKey; | |
774 } | |
775 | |
776 | |
777 PK11SlotInfo * | |
778 PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key) | |
779 { | |
780 PK11SlotInfo *slot = key->pkcs11Slot; | |
781 slot = PK11_ReferenceSlot(slot); | |
782 return slot; | |
783 } | |
784 | |
785 /* | |
786 * Get the modulus length for raw parsing | |
787 */ | |
788 int | |
789 PK11_GetPrivateModulusLen(SECKEYPrivateKey *key) | |
790 { | |
791 CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 }; | |
792 PK11SlotInfo *slot = key->pkcs11Slot; | |
793 CK_RV crv; | |
794 int length; | |
795 | |
796 switch (key->keyType) { | |
797 case rsaKey: | |
798 crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1); | |
799 if (crv != CKR_OK) { | |
800 PORT_SetError( PK11_MapError(crv) ); | |
801 return -1; | |
802 } | |
803 length = theTemplate.ulValueLen; | |
804 if ( *(unsigned char *)theTemplate.pValue == 0) { | |
805 length--; | |
806 } | |
807 if (theTemplate.pValue != NULL) | |
808 PORT_Free(theTemplate.pValue); | |
809 return (int) length; | |
810 | |
811 case fortezzaKey: | |
812 case dsaKey: | |
813 case dhKey: | |
814 default: | |
815 break; | |
816 } | |
817 if (theTemplate.pValue != NULL) | |
818 PORT_Free(theTemplate.pValue); | |
819 PORT_SetError( SEC_ERROR_INVALID_KEY ); | |
820 return -1; | |
821 } | |
822 | |
823 | |
824 | |
825 /* | |
826 * take a private key in one pkcs11 module and load it into another: | |
827 * NOTE: the source private key is a rare animal... it can't be sensitive. | |
828 * This is used to do a key gen using one pkcs11 module and storing the | |
829 * result into another. | |
830 */ | |
831 static SECKEYPrivateKey * | |
832 pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, | |
833 SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags) | |
834 { | |
835 CK_ATTRIBUTE privTemplate[] = { | |
836 /* class must be first */ | |
837 { CKA_CLASS, NULL, 0 }, | |
838 { CKA_KEY_TYPE, NULL, 0 }, | |
839 { CKA_ID, NULL, 0 }, | |
840 /* RSA - the attributes below will be replaced for other | |
841 * key types. | |
842 */ | |
843 { CKA_MODULUS, NULL, 0 }, | |
844 { CKA_PRIVATE_EXPONENT, NULL, 0 }, | |
845 { CKA_PUBLIC_EXPONENT, NULL, 0 }, | |
846 { CKA_PRIME_1, NULL, 0 }, | |
847 { CKA_PRIME_2, NULL, 0 }, | |
848 { CKA_EXPONENT_1, NULL, 0 }, | |
849 { CKA_EXPONENT_2, NULL, 0 }, | |
850 { CKA_COEFFICIENT, NULL, 0 }, | |
851 { CKA_DECRYPT, NULL, 0 }, | |
852 { CKA_DERIVE, NULL, 0 }, | |
853 { CKA_SIGN, NULL, 0 }, | |
854 { CKA_SIGN_RECOVER, NULL, 0 }, | |
855 { CKA_UNWRAP, NULL, 0 }, | |
856 /* reserve space for the attributes that may be | |
857 * specified in attrFlags */ | |
858 { CKA_TOKEN, NULL, 0 }, | |
859 { CKA_PRIVATE, NULL, 0 }, | |
860 { CKA_MODIFIABLE, NULL, 0 }, | |
861 { CKA_SENSITIVE, NULL, 0 }, | |
862 { CKA_EXTRACTABLE, NULL, 0 }, | |
863 #define NUM_RESERVED_ATTRS 5 /* number of reserved attributes above */ | |
864 }; | |
865 CK_BBOOL cktrue = CK_TRUE; | |
866 CK_BBOOL ckfalse = CK_FALSE; | |
867 CK_ATTRIBUTE *attrs = NULL, *ap; | |
868 const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]); | |
869 PLArenaPool *arena; | |
870 CK_OBJECT_HANDLE objectID; | |
871 int i, count = 0; | |
872 int extra_count = 0; | |
873 CK_RV crv; | |
874 SECStatus rv; | |
875 PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0); | |
876 | |
877 if (pk11_BadAttrFlags(attrFlags)) { | |
878 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
879 return NULL; | |
880 } | |
881 | |
882 for (i=0; i < templateSize; i++) { | |
883 if (privTemplate[i].type == CKA_MODULUS) { | |
884 attrs= &privTemplate[i]; | |
885 count = i; | |
886 break; | |
887 } | |
888 } | |
889 PORT_Assert(attrs != NULL); | |
890 if (attrs == NULL) { | |
891 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
892 return NULL; | |
893 } | |
894 | |
895 ap = attrs; | |
896 | |
897 switch (privKey->keyType) { | |
898 case rsaKey: | |
899 count = templateSize - NUM_RESERVED_ATTRS; | |
900 extra_count = count - (attrs - privTemplate); | |
901 break; | |
902 case dsaKey: | |
903 ap->type = CKA_PRIME; ap++; count++; extra_count++; | |
904 ap->type = CKA_SUBPRIME; ap++; count++; extra_count++; | |
905 ap->type = CKA_BASE; ap++; count++; extra_count++; | |
906 ap->type = CKA_VALUE; ap++; count++; extra_count++; | |
907 ap->type = CKA_SIGN; ap++; count++; extra_count++; | |
908 break; | |
909 case dhKey: | |
910 ap->type = CKA_PRIME; ap++; count++; extra_count++; | |
911 ap->type = CKA_BASE; ap++; count++; extra_count++; | |
912 ap->type = CKA_VALUE; ap++; count++; extra_count++; | |
913 ap->type = CKA_DERIVE; ap++; count++; extra_count++; | |
914 break; | |
915 case ecKey: | |
916 ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++; | |
917 ap->type = CKA_VALUE; ap++; count++; extra_count++; | |
918 ap->type = CKA_DERIVE; ap++; count++; extra_count++; | |
919 ap->type = CKA_SIGN; ap++; count++; extra_count++; | |
920 break; | |
921 default: | |
922 count = 0; | |
923 extra_count = 0; | |
924 break; | |
925 } | |
926 | |
927 if (count == 0) { | |
928 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
929 return NULL; | |
930 } | |
931 | |
932 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); | |
933 if (arena == NULL) return NULL; | |
934 /* | |
935 * read out the old attributes. | |
936 */ | |
937 crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, | |
938 privTemplate,count); | |
939 if (crv != CKR_OK) { | |
940 PORT_SetError( PK11_MapError(crv) ); | |
941 PORT_FreeArena(arena, PR_TRUE); | |
942 return NULL; | |
943 } | |
944 | |
945 /* Set token, private, modifiable, sensitive, and extractable */ | |
946 count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count], | |
947 &cktrue, &ckfalse); | |
948 | |
949 /* Not everyone can handle zero padded key values, give | |
950 * them the raw data as unsigned */ | |
951 for (ap=attrs; extra_count; ap++, extra_count--) { | |
952 pk11_SignedToUnsigned(ap); | |
953 } | |
954 | |
955 /* now Store the puppies */ | |
956 rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate, | |
957 count, token, &objectID); | |
958 PORT_FreeArena(arena, PR_TRUE); | |
959 if (rv != SECSuccess) { | |
960 return NULL; | |
961 } | |
962 | |
963 /* try loading the public key */ | |
964 if (pubKey) { | |
965 PK11_ImportPublicKey(slot, pubKey, token); | |
966 if (pubKey->pkcs11Slot) { | |
967 PK11_FreeSlot(pubKey->pkcs11Slot); | |
968 pubKey->pkcs11Slot = NULL; | |
969 pubKey->pkcs11ID = CK_INVALID_HANDLE; | |
970 } | |
971 } | |
972 | |
973 /* build new key structure */ | |
974 return PK11_MakePrivKey(slot, privKey->keyType, !token, | |
975 objectID, privKey->wincx); | |
976 } | |
977 | |
978 static SECKEYPrivateKey * | |
979 pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, | |
980 SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) | |
981 { | |
982 PK11AttrFlags attrFlags = 0; | |
983 if (token) { | |
984 attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); | |
985 } else { | |
986 attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC); | |
987 } | |
988 if (sensitive) { | |
989 attrFlags |= PK11_ATTR_SENSITIVE; | |
990 } else { | |
991 attrFlags |= PK11_ATTR_INSENSITIVE; | |
992 } | |
993 return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags); | |
994 } | |
995 | |
996 /* | |
997 * export this for PSM | |
998 */ | |
999 SECKEYPrivateKey * | |
1000 PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, | |
1001 SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) | |
1002 { | |
1003 return pk11_loadPrivKey(slot,privKey,pubKey,token,sensitive); | |
1004 } | |
1005 | |
1006 | |
1007 /* | |
1008 * Use the token to generate a key pair. | |
1009 */ | |
1010 SECKEYPrivateKey * | |
1011 PK11_GenerateKeyPairWithOpFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, | |
1012 void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, | |
1013 CK_FLAGS opFlags, CK_FLAGS opFlagsMask, void *wincx) | |
1014 { | |
1015 /* we have to use these native types because when we call PKCS 11 modules | |
1016 * we have to make sure that we are using the correct sizes for all the | |
1017 * parameters. */ | |
1018 CK_BBOOL ckfalse = CK_FALSE; | |
1019 CK_BBOOL cktrue = CK_TRUE; | |
1020 CK_ULONG modulusBits; | |
1021 CK_BYTE publicExponent[4]; | |
1022 CK_ATTRIBUTE privTemplate[] = { | |
1023 { CKA_SENSITIVE, NULL, 0}, | |
1024 { CKA_TOKEN, NULL, 0}, | |
1025 { CKA_PRIVATE, NULL, 0}, | |
1026 { CKA_DERIVE, NULL, 0}, | |
1027 { CKA_UNWRAP, NULL, 0}, | |
1028 { CKA_SIGN, NULL, 0}, | |
1029 { CKA_DECRYPT, NULL, 0}, | |
1030 { CKA_EXTRACTABLE, NULL, 0}, | |
1031 { CKA_MODIFIABLE, NULL, 0}, | |
1032 }; | |
1033 CK_ATTRIBUTE rsaPubTemplate[] = { | |
1034 { CKA_MODULUS_BITS, NULL, 0}, | |
1035 { CKA_PUBLIC_EXPONENT, NULL, 0}, | |
1036 { CKA_TOKEN, NULL, 0}, | |
1037 { CKA_DERIVE, NULL, 0}, | |
1038 { CKA_WRAP, NULL, 0}, | |
1039 { CKA_VERIFY, NULL, 0}, | |
1040 { CKA_VERIFY_RECOVER, NULL, 0}, | |
1041 { CKA_ENCRYPT, NULL, 0}, | |
1042 { CKA_MODIFIABLE, NULL, 0}, | |
1043 }; | |
1044 CK_ATTRIBUTE dsaPubTemplate[] = { | |
1045 { CKA_PRIME, NULL, 0 }, | |
1046 { CKA_SUBPRIME, NULL, 0 }, | |
1047 { CKA_BASE, NULL, 0 }, | |
1048 { CKA_TOKEN, NULL, 0}, | |
1049 { CKA_DERIVE, NULL, 0}, | |
1050 { CKA_WRAP, NULL, 0}, | |
1051 { CKA_VERIFY, NULL, 0}, | |
1052 { CKA_VERIFY_RECOVER, NULL, 0}, | |
1053 { CKA_ENCRYPT, NULL, 0}, | |
1054 { CKA_MODIFIABLE, NULL, 0}, | |
1055 }; | |
1056 CK_ATTRIBUTE dhPubTemplate[] = { | |
1057 { CKA_PRIME, NULL, 0 }, | |
1058 { CKA_BASE, NULL, 0 }, | |
1059 { CKA_TOKEN, NULL, 0}, | |
1060 { CKA_DERIVE, NULL, 0}, | |
1061 { CKA_WRAP, NULL, 0}, | |
1062 { CKA_VERIFY, NULL, 0}, | |
1063 { CKA_VERIFY_RECOVER, NULL, 0}, | |
1064 { CKA_ENCRYPT, NULL, 0}, | |
1065 { CKA_MODIFIABLE, NULL, 0}, | |
1066 }; | |
1067 CK_ATTRIBUTE ecPubTemplate[] = { | |
1068 { CKA_EC_PARAMS, NULL, 0 }, | |
1069 { CKA_TOKEN, NULL, 0}, | |
1070 { CKA_DERIVE, NULL, 0}, | |
1071 { CKA_WRAP, NULL, 0}, | |
1072 { CKA_VERIFY, NULL, 0}, | |
1073 { CKA_VERIFY_RECOVER, NULL, 0}, | |
1074 { CKA_ENCRYPT, NULL, 0}, | |
1075 { CKA_MODIFIABLE, NULL, 0}, | |
1076 }; | |
1077 SECKEYECParams * ecParams; | |
1078 | |
1079 /*CK_ULONG key_size = 0;*/ | |
1080 CK_ATTRIBUTE *pubTemplate; | |
1081 int privCount = 0; | |
1082 int pubCount = 0; | |
1083 PK11RSAGenParams *rsaParams; | |
1084 SECKEYPQGParams *dsaParams; | |
1085 SECKEYDHParams * dhParams; | |
1086 CK_MECHANISM mechanism; | |
1087 CK_MECHANISM test_mech; | |
1088 CK_MECHANISM test_mech2; | |
1089 CK_SESSION_HANDLE session_handle; | |
1090 CK_RV crv; | |
1091 CK_OBJECT_HANDLE privID,pubID; | |
1092 SECKEYPrivateKey *privKey; | |
1093 KeyType keyType; | |
1094 PRBool restore; | |
1095 int peCount,i; | |
1096 CK_ATTRIBUTE *attrs; | |
1097 CK_ATTRIBUTE *privattrs; | |
1098 CK_ATTRIBUTE setTemplate; | |
1099 CK_MECHANISM_INFO mechanism_info; | |
1100 CK_OBJECT_CLASS keyClass; | |
1101 SECItem *cka_id; | |
1102 PRBool haslock = PR_FALSE; | |
1103 PRBool pubIsToken = PR_FALSE; | |
1104 PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0); | |
1105 /* subset of attrFlags applicable to the public key */ | |
1106 PK11AttrFlags pubKeyAttrFlags = attrFlags & | |
1107 (PK11_ATTR_TOKEN | PK11_ATTR_SESSION | |
1108 | PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE); | |
1109 | |
1110 if (pk11_BadAttrFlags(attrFlags)) { | |
1111 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
1112 return NULL; | |
1113 } | |
1114 | |
1115 if (!param) { | |
1116 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
1117 return NULL; | |
1118 } | |
1119 | |
1120 /* | |
1121 * The opFlags and opFlagMask parameters allow us to control the | |
1122 * settings of the key usage attributes (CKA_ENCRYPT and friends). | |
1123 * opFlagMask is set to one if the flag is specified in opFlags and | |
1124 * zero if it is to take on a default value calculated by | |
1125 * PK11_GenerateKeyPairWithOpFlags. | |
1126 * opFlags specifies the actual value of the flag 1 or 0. | |
1127 * Bits not corresponding to one bits in opFlagMask should be zero. | |
1128 */ | |
1129 | |
1130 /* if we are trying to turn on a flag, it better be in the mask */ | |
1131 PORT_Assert ((opFlags & ~opFlagsMask) == 0); | |
1132 opFlags &= opFlagsMask; | |
1133 | |
1134 PORT_Assert(slot != NULL); | |
1135 if (slot == NULL) { | |
1136 PORT_SetError( SEC_ERROR_NO_MODULE); | |
1137 return NULL; | |
1138 } | |
1139 | |
1140 /* if our slot really doesn't do this mechanism, Generate the key | |
1141 * in our internal token and write it out */ | |
1142 if (!PK11_DoesMechanism(slot,type)) { | |
1143 PK11SlotInfo *int_slot = PK11_GetInternalSlot(); | |
1144 | |
1145 /* don't loop forever looking for a slot */ | |
1146 if (slot == int_slot) { | |
1147 PK11_FreeSlot(int_slot); | |
1148 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
1149 return NULL; | |
1150 } | |
1151 | |
1152 /* if there isn't a suitable slot, then we can't do the keygen */ | |
1153 if (int_slot == NULL) { | |
1154 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
1155 return NULL; | |
1156 } | |
1157 | |
1158 /* generate the temporary key to load */ | |
1159 privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE, | |
1160 PR_FALSE, wincx); | |
1161 PK11_FreeSlot(int_slot); | |
1162 | |
1163 /* if successful, load the temp key into the new token */ | |
1164 if (privKey != NULL) { | |
1165 SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot, | |
1166 privKey,*pubKey,attrFlags); | |
1167 SECKEY_DestroyPrivateKey(privKey); | |
1168 if (newPrivKey == NULL) { | |
1169 SECKEY_DestroyPublicKey(*pubKey); | |
1170 *pubKey = NULL; | |
1171 } | |
1172 return newPrivKey; | |
1173 } | |
1174 return NULL; | |
1175 } | |
1176 | |
1177 | |
1178 mechanism.mechanism = type; | |
1179 mechanism.pParameter = NULL; | |
1180 mechanism.ulParameterLen = 0; | |
1181 test_mech.pParameter = NULL; | |
1182 test_mech.ulParameterLen = 0; | |
1183 test_mech2.mechanism = CKM_INVALID_MECHANISM; | |
1184 test_mech2.pParameter = NULL; | |
1185 test_mech2.ulParameterLen = 0; | |
1186 | |
1187 /* set up the private key template */ | |
1188 privattrs = privTemplate; | |
1189 privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs, | |
1190 &cktrue, &ckfalse); | |
1191 | |
1192 /* set up the mechanism specific info */ | |
1193 switch (type) { | |
1194 case CKM_RSA_PKCS_KEY_PAIR_GEN: | |
1195 case CKM_RSA_X9_31_KEY_PAIR_GEN: | |
1196 rsaParams = (PK11RSAGenParams *)param; | |
1197 if (rsaParams->pe == 0) { | |
1198 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1199 return NULL; | |
1200 } | |
1201 modulusBits = rsaParams->keySizeInBits; | |
1202 peCount = 0; | |
1203 | |
1204 /* convert pe to a PKCS #11 string */ | |
1205 for (i=0; i < 4; i++) { | |
1206 if (peCount || (rsaParams->pe & | |
1207 ((unsigned long)0xff000000L >> (i*8)))) { | |
1208 publicExponent[peCount] = | |
1209 (CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff); | |
1210 peCount++; | |
1211 } | |
1212 } | |
1213 PORT_Assert(peCount != 0); | |
1214 attrs = rsaPubTemplate; | |
1215 PK11_SETATTRS(attrs, CKA_MODULUS_BITS, | |
1216 &modulusBits, sizeof(modulusBits)); attrs++; | |
1217 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, | |
1218 publicExponent, peCount);attrs++; | |
1219 pubTemplate = rsaPubTemplate; | |
1220 keyType = rsaKey; | |
1221 test_mech.mechanism = CKM_RSA_PKCS; | |
1222 break; | |
1223 case CKM_DSA_KEY_PAIR_GEN: | |
1224 dsaParams = (SECKEYPQGParams *)param; | |
1225 attrs = dsaPubTemplate; | |
1226 PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data, | |
1227 dsaParams->prime.len); attrs++; | |
1228 PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data, | |
1229 dsaParams->subPrime.len); attrs++; | |
1230 PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data, | |
1231 dsaParams->base.len); attrs++; | |
1232 pubTemplate = dsaPubTemplate; | |
1233 keyType = dsaKey; | |
1234 test_mech.mechanism = CKM_DSA; | |
1235 break; | |
1236 case CKM_DH_PKCS_KEY_PAIR_GEN: | |
1237 dhParams = (SECKEYDHParams *)param; | |
1238 attrs = dhPubTemplate; | |
1239 PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data, | |
1240 dhParams->prime.len); attrs++; | |
1241 PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data, | |
1242 dhParams->base.len); attrs++; | |
1243 pubTemplate = dhPubTemplate; | |
1244 keyType = dhKey; | |
1245 test_mech.mechanism = CKM_DH_PKCS_DERIVE; | |
1246 break; | |
1247 case CKM_EC_KEY_PAIR_GEN: | |
1248 ecParams = (SECKEYECParams *)param; | |
1249 attrs = ecPubTemplate; | |
1250 PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, | |
1251 ecParams->len); attrs++; | |
1252 pubTemplate = ecPubTemplate; | |
1253 keyType = ecKey; | |
1254 /* | |
1255 * ECC supports 2 different mechanism types (unlike RSA, which | |
1256 * supports different usages with the same mechanism). | |
1257 * We may need to query both mechanism types and or the results | |
1258 * together -- but we only do that if either the user has | |
1259 * requested both usages, or not specified any usages. | |
1260 */ | |
1261 if ((opFlags & (CKF_SIGN|CKF_DERIVE)) == (CKF_SIGN|CKF_DERIVE)) { | |
1262 /* We've explicitly turned on both flags, use both mechanism */ | |
1263 test_mech.mechanism = CKM_ECDH1_DERIVE; | |
1264 test_mech2.mechanism = CKM_ECDSA; | |
1265 } else if (opFlags & CKF_SIGN) { | |
1266 /* just do signing */ | |
1267 test_mech.mechanism = CKM_ECDSA; | |
1268 } else if (opFlags & CKF_DERIVE) { | |
1269 /* just do ECDH */ | |
1270 test_mech.mechanism = CKM_ECDH1_DERIVE; | |
1271 } else { | |
1272 /* neither was specified default to both */ | |
1273 test_mech.mechanism = CKM_ECDH1_DERIVE; | |
1274 test_mech2.mechanism = CKM_ECDSA; | |
1275 } | |
1276 break; | |
1277 default: | |
1278 PORT_SetError( SEC_ERROR_BAD_KEY ); | |
1279 return NULL; | |
1280 } | |
1281 | |
1282 /* now query the slot to find out how "good" a key we can generate */ | |
1283 if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); | |
1284 crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, | |
1285 test_mech.mechanism,&mechanism_info); | |
1286 /* | |
1287 * EC keys are used in multiple different types of mechanism, if we | |
1288 * are using dual use keys, we need to query the second mechanism | |
1289 * as well. | |
1290 */ | |
1291 if (test_mech2.mechanism != CKM_INVALID_MECHANISM) { | |
1292 CK_MECHANISM_INFO mechanism_info2; | |
1293 CK_RV crv2; | |
1294 | |
1295 if (crv != CKR_OK) { | |
1296 /* the first failed, make sure there is no trash in the | |
1297 * mechanism flags when we or it below */ | |
1298 mechanism_info.flags = 0; | |
1299 } | |
1300 crv2 = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, | |
1301 test_mech2.mechanism, &mechanism_info2); | |
1302 if (crv2 == CKR_OK) { | |
1303 crv = CKR_OK; /* succeed if either mechnaism info succeeds */ | |
1304 /* combine the 2 sets of mechnanism flags */ | |
1305 mechanism_info.flags |= mechanism_info2.flags; | |
1306 } | |
1307 } | |
1308 if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); | |
1309 if ((crv != CKR_OK) || (mechanism_info.flags == 0)) { | |
1310 /* must be old module... guess what it should be... */ | |
1311 switch (test_mech.mechanism) { | |
1312 case CKM_RSA_PKCS: | |
1313 mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT | | |
1314 CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP); | |
1315 break; | |
1316 case CKM_DSA: | |
1317 mechanism_info.flags = CKF_SIGN | CKF_VERIFY; | |
1318 break; | |
1319 case CKM_DH_PKCS_DERIVE: | |
1320 mechanism_info.flags = CKF_DERIVE; | |
1321 break; | |
1322 case CKM_ECDH1_DERIVE: | |
1323 mechanism_info.flags = CKF_DERIVE; | |
1324 if (test_mech2.mechanism == CKM_ECDSA) { | |
1325 mechanism_info.flags |= CKF_SIGN | CKF_VERIFY; | |
1326 } | |
1327 break; | |
1328 case CKM_ECDSA: | |
1329 mechanism_info.flags = CKF_SIGN | CKF_VERIFY; | |
1330 break; | |
1331 default: | |
1332 break; | |
1333 } | |
1334 } | |
1335 /* now adjust our flags according to the user's key usage passed to us */ | |
1336 mechanism_info.flags = (mechanism_info.flags & (~opFlagsMask)) | opFlags; | |
1337 /* set the public key attributes */ | |
1338 attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs, | |
1339 &cktrue, &ckfalse); | |
1340 PK11_SETATTRS(attrs, CKA_DERIVE, | |
1341 mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse, | |
1342 sizeof(CK_BBOOL)); attrs++; | |
1343 PK11_SETATTRS(attrs, CKA_WRAP, | |
1344 mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse, | |
1345 sizeof(CK_BBOOL)); attrs++; | |
1346 PK11_SETATTRS(attrs, CKA_VERIFY, | |
1347 mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse, | |
1348 sizeof(CK_BBOOL)); attrs++; | |
1349 PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER, | |
1350 mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse, | |
1351 sizeof(CK_BBOOL)); attrs++; | |
1352 PK11_SETATTRS(attrs, CKA_ENCRYPT, | |
1353 mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse, | |
1354 sizeof(CK_BBOOL)); attrs++; | |
1355 /* set the private key attributes */ | |
1356 PK11_SETATTRS(privattrs, CKA_DERIVE, | |
1357 mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse, | |
1358 sizeof(CK_BBOOL)); privattrs++; | |
1359 PK11_SETATTRS(privattrs, CKA_UNWRAP, | |
1360 mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse, | |
1361 sizeof(CK_BBOOL)); privattrs++; | |
1362 PK11_SETATTRS(privattrs, CKA_SIGN, | |
1363 mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse, | |
1364 sizeof(CK_BBOOL)); privattrs++; | |
1365 PK11_SETATTRS(privattrs, CKA_DECRYPT, | |
1366 mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse, | |
1367 sizeof(CK_BBOOL)); privattrs++; | |
1368 | |
1369 if (token) { | |
1370 session_handle = PK11_GetRWSession(slot); | |
1371 haslock = PK11_RWSessionHasLock(slot,session_handle); | |
1372 restore = PR_TRUE; | |
1373 } else { | |
1374 session_handle = slot->session; | |
1375 if (session_handle != CK_INVALID_SESSION) | |
1376 PK11_EnterSlotMonitor(slot); | |
1377 restore = PR_FALSE; | |
1378 haslock = PR_TRUE; | |
1379 } | |
1380 | |
1381 if (session_handle == CK_INVALID_SESSION) { | |
1382 PORT_SetError(SEC_ERROR_BAD_DATA); | |
1383 return NULL; | |
1384 } | |
1385 privCount = privattrs - privTemplate; | |
1386 pubCount = attrs - pubTemplate; | |
1387 crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism, | |
1388 pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID); | |
1389 | |
1390 if (crv != CKR_OK) { | |
1391 if (restore) { | |
1392 PK11_RestoreROSession(slot,session_handle); | |
1393 } else PK11_ExitSlotMonitor(slot); | |
1394 PORT_SetError( PK11_MapError(crv) ); | |
1395 return NULL; | |
1396 } | |
1397 /* This locking code is dangerous and needs to be more thought | |
1398 * out... the real problem is that we're holding the mutex open this long | |
1399 */ | |
1400 if (haslock) { PK11_ExitSlotMonitor(slot); } | |
1401 | |
1402 /* swap around the ID's for older PKCS #11 modules */ | |
1403 keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS); | |
1404 if (keyClass != CKO_PUBLIC_KEY) { | |
1405 CK_OBJECT_HANDLE tmp = pubID; | |
1406 pubID = privID; | |
1407 privID = tmp; | |
1408 } | |
1409 | |
1410 *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID); | |
1411 if (*pubKey == NULL) { | |
1412 if (restore) { | |
1413 /* we may have to restore the mutex so it get's exited properly | |
1414 * in RestoreROSession */ | |
1415 if (haslock) PK11_EnterSlotMonitor(slot); | |
1416 PK11_RestoreROSession(slot,session_handle); | |
1417 } | |
1418 PK11_DestroyObject(slot,pubID); | |
1419 PK11_DestroyObject(slot,privID); | |
1420 return NULL; | |
1421 } | |
1422 | |
1423 /* set the ID to the public key so we can find it again */ | |
1424 cka_id = pk11_MakeIDFromPublicKey(*pubKey); | |
1425 pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN,PR_FALSE); | |
1426 | |
1427 PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len); | |
1428 | |
1429 if (haslock) { PK11_EnterSlotMonitor(slot); } | |
1430 crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID, | |
1431 &setTemplate, 1); | |
1432 | |
1433 if (crv == CKR_OK && pubIsToken) { | |
1434 crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID, | |
1435 &setTemplate, 1); | |
1436 } | |
1437 | |
1438 | |
1439 if (restore) { | |
1440 PK11_RestoreROSession(slot,session_handle); | |
1441 } else { | |
1442 PK11_ExitSlotMonitor(slot); | |
1443 } | |
1444 SECITEM_FreeItem(cka_id,PR_TRUE); | |
1445 | |
1446 | |
1447 if (crv != CKR_OK) { | |
1448 PK11_DestroyObject(slot,pubID); | |
1449 PK11_DestroyObject(slot,privID); | |
1450 PORT_SetError( PK11_MapError(crv) ); | |
1451 *pubKey = NULL; | |
1452 return NULL; | |
1453 } | |
1454 | |
1455 privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx); | |
1456 if (privKey == NULL) { | |
1457 SECKEY_DestroyPublicKey(*pubKey); | |
1458 PK11_DestroyObject(slot,privID); | |
1459 *pubKey = NULL; | |
1460 return NULL; | |
1461 } | |
1462 | |
1463 return privKey; | |
1464 } | |
1465 | |
1466 SECKEYPrivateKey * | |
1467 PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, | |
1468 void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx) | |
1469 { | |
1470 return PK11_GenerateKeyPairWithOpFlags(slot,type,param,pubKey,attrFlags, | |
1471 0, 0, wincx); | |
1472 } | |
1473 | |
1474 /* | |
1475 * Use the token to generate a key pair. | |
1476 */ | |
1477 SECKEYPrivateKey * | |
1478 PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, | |
1479 void *param, SECKEYPublicKey **pubKey, PRBool token, | |
1480 PRBool sensitive, void *wincx) | |
1481 { | |
1482 PK11AttrFlags attrFlags = 0; | |
1483 | |
1484 if (token) { | |
1485 attrFlags |= PK11_ATTR_TOKEN; | |
1486 } else { | |
1487 attrFlags |= PK11_ATTR_SESSION; | |
1488 } | |
1489 if (sensitive) { | |
1490 attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE); | |
1491 } else { | |
1492 attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC); | |
1493 } | |
1494 return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey, | |
1495 attrFlags, wincx); | |
1496 } | |
1497 | |
1498 /* build a public KEA key from the public value */ | |
1499 SECKEYPublicKey * | |
1500 PK11_MakeKEAPubKey(unsigned char *keyData,int length) | |
1501 { | |
1502 SECKEYPublicKey *pubk; | |
1503 SECItem pkData; | |
1504 SECStatus rv; | |
1505 PLArenaPool *arena; | |
1506 | |
1507 pkData.data = keyData; | |
1508 pkData.len = length; | |
1509 | |
1510 arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE); | |
1511 if (arena == NULL) | |
1512 return NULL; | |
1513 | |
1514 pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); | |
1515 if (pubk == NULL) { | |
1516 PORT_FreeArena (arena, PR_FALSE); | |
1517 return NULL; | |
1518 } | |
1519 | |
1520 pubk->arena = arena; | |
1521 pubk->pkcs11Slot = 0; | |
1522 pubk->pkcs11ID = CK_INVALID_HANDLE; | |
1523 pubk->keyType = fortezzaKey; | |
1524 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData); | |
1525 if (rv != SECSuccess) { | |
1526 PORT_FreeArena (arena, PR_FALSE); | |
1527 return NULL; | |
1528 } | |
1529 return pubk; | |
1530 } | |
1531 | |
1532 /* | |
1533 * NOTE: This function doesn't return a SECKEYPrivateKey struct to represent | |
1534 * the new private key object. If it were to create a session object that | |
1535 * could later be looked up by its nickname, it would leak a SECKEYPrivateKey. | |
1536 * So isPerm must be true. | |
1537 */ | |
1538 SECStatus | |
1539 PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, | |
1540 SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem, | |
1541 SECItem *nickname, SECItem *publicValue, PRBool isPerm, | |
1542 PRBool isPrivate, KeyType keyType, | |
1543 unsigned int keyUsage, void *wincx) | |
1544 { | |
1545 if (!isPerm) { | |
1546 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1547 return SECFailure; | |
1548 } | |
1549 return PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(slot, epki, | |
1550 pwitem, nickname, publicValue, isPerm, isPrivate, keyType, | |
1551 keyUsage, NULL, wincx); | |
1552 } | |
1553 | |
1554 SECStatus | |
1555 PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, | |
1556 SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem, | |
1557 SECItem *nickname, SECItem *publicValue, PRBool isPerm, | |
1558 PRBool isPrivate, KeyType keyType, | |
1559 unsigned int keyUsage, SECKEYPrivateKey **privk, | |
1560 void *wincx) | |
1561 { | |
1562 CK_MECHANISM_TYPE pbeMechType; | |
1563 SECItem *crypto_param = NULL; | |
1564 PK11SymKey *key = NULL; | |
1565 SECStatus rv = SECSuccess; | |
1566 CK_MECHANISM_TYPE cryptoMechType; | |
1567 SECKEYPrivateKey *privKey = NULL; | |
1568 PRBool faulty3DES = PR_FALSE; | |
1569 int usageCount = 0; | |
1570 CK_KEY_TYPE key_type; | |
1571 CK_ATTRIBUTE_TYPE *usage = NULL; | |
1572 CK_ATTRIBUTE_TYPE rsaUsage[] = { | |
1573 CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER }; | |
1574 CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN }; | |
1575 CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE }; | |
1576 CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE }; | |
1577 if((epki == NULL) || (pwitem == NULL)) | |
1578 return SECFailure; | |
1579 | |
1580 pbeMechType = PK11_AlgtagToMechanism(SECOID_FindOIDTag( | |
1581 &epki->algorithm.algorithm)); | |
1582 | |
1583 switch (keyType) { | |
1584 default: | |
1585 case rsaKey: | |
1586 key_type = CKK_RSA; | |
1587 switch (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) { | |
1588 case KU_KEY_ENCIPHERMENT: | |
1589 usage = rsaUsage; | |
1590 usageCount = 2; | |
1591 break; | |
1592 case KU_DIGITAL_SIGNATURE: | |
1593 usage = &rsaUsage[2]; | |
1594 usageCount = 2; | |
1595 break; | |
1596 case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE: | |
1597 case 0: /* default to everything */ | |
1598 usage = rsaUsage; | |
1599 usageCount = 4; | |
1600 break; | |
1601 } | |
1602 break; | |
1603 case dhKey: | |
1604 key_type = CKK_DH; | |
1605 usage = dhUsage; | |
1606 usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]); | |
1607 break; | |
1608 case dsaKey: | |
1609 key_type = CKK_DSA; | |
1610 usage = dsaUsage; | |
1611 usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]); | |
1612 break; | |
1613 case ecKey: | |
1614 key_type = CKK_EC; | |
1615 switch (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) { | |
1616 case KU_DIGITAL_SIGNATURE: | |
1617 usage = ecUsage; | |
1618 usageCount = 1; | |
1619 break; | |
1620 case KU_KEY_AGREEMENT: | |
1621 usage = &ecUsage[1]; | |
1622 usageCount = 1; | |
1623 break; | |
1624 case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT: | |
1625 default: /* default to everything */ | |
1626 usage = ecUsage; | |
1627 usageCount = 2; | |
1628 break; | |
1629 } | |
1630 break; | |
1631 } | |
1632 | |
1633 try_faulty_3des: | |
1634 | |
1635 key = PK11_PBEKeyGen(slot, &epki->algorithm, pwitem, faulty3DES, wincx); | |
1636 if (key == NULL) { | |
1637 rv = SECFailure; | |
1638 goto done; | |
1639 } | |
1640 cryptoMechType = pk11_GetPBECryptoMechanism(&epki->algorithm, | |
1641 &crypto_param, pwitem, faulty3DES); | |
1642 if (cryptoMechType == CKM_INVALID_MECHANISM) { | |
1643 rv = SECFailure; | |
1644 goto done; | |
1645 } | |
1646 | |
1647 | |
1648 cryptoMechType = PK11_GetPadMechanism(cryptoMechType); | |
1649 | |
1650 PORT_Assert(usage != NULL); | |
1651 PORT_Assert(usageCount != 0); | |
1652 privKey = PK11_UnwrapPrivKey(slot, key, cryptoMechType, | |
1653 crypto_param, &epki->encryptedData, | |
1654 nickname, publicValue, isPerm, isPrivate, | |
1655 key_type, usage, usageCount, wincx); | |
1656 if(privKey) { | |
1657 if (privk) { | |
1658 *privk = privKey; | |
1659 } else { | |
1660 SECKEY_DestroyPrivateKey(privKey); | |
1661 } | |
1662 privKey = NULL; | |
1663 rv = SECSuccess; | |
1664 goto done; | |
1665 } | |
1666 | |
1667 /* if we are unable to import the key and the pbeMechType is | |
1668 * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that | |
1669 * the encrypted blob was created with a buggy key generation method | |
1670 * which is described in the PKCS 12 implementation notes. So we | |
1671 * need to try importing via that method. | |
1672 */ | |
1673 if((pbeMechType == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) { | |
1674 /* clean up after ourselves before redoing the key generation. */ | |
1675 | |
1676 PK11_FreeSymKey(key); | |
1677 key = NULL; | |
1678 | |
1679 if(crypto_param) { | |
1680 SECITEM_ZfreeItem(crypto_param, PR_TRUE); | |
1681 crypto_param = NULL; | |
1682 } | |
1683 | |
1684 faulty3DES = PR_TRUE; | |
1685 goto try_faulty_3des; | |
1686 } | |
1687 | |
1688 /* key import really did fail */ | |
1689 rv = SECFailure; | |
1690 | |
1691 done: | |
1692 if(crypto_param != NULL) { | |
1693 SECITEM_ZfreeItem(crypto_param, PR_TRUE); | |
1694 } | |
1695 | |
1696 if(key != NULL) { | |
1697 PK11_FreeSymKey(key); | |
1698 } | |
1699 | |
1700 return rv; | |
1701 } | |
1702 | |
1703 SECKEYPrivateKeyInfo * | |
1704 PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx) | |
1705 { | |
1706 SECKEYPrivateKeyInfo *pki = NULL; | |
1707 SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, wincx); | |
1708 if (pk != NULL) { | |
1709 pki = PK11_ExportPrivKeyInfo(pk, wincx); | |
1710 SECKEY_DestroyPrivateKey(pk); | |
1711 } | |
1712 return pki; | |
1713 } | |
1714 | |
1715 SECKEYEncryptedPrivateKeyInfo * | |
1716 PK11_ExportEncryptedPrivKeyInfo( | |
1717 PK11SlotInfo *slot, /* optional, encrypt key in this slot */ | |
1718 SECOidTag algTag, /* encrypt key with this algorithm */ | |
1719 SECItem *pwitem, /* password for PBE encryption */ | |
1720 SECKEYPrivateKey *pk, /* encrypt this private key */ | |
1721 int iteration, /* interations for PBE alg */ | |
1722 void *wincx) /* context for password callback ? */ | |
1723 { | |
1724 SECKEYEncryptedPrivateKeyInfo *epki = NULL; | |
1725 PLArenaPool *arena = NULL; | |
1726 SECAlgorithmID *algid; | |
1727 SECOidTag pbeAlgTag = SEC_OID_UNKNOWN; | |
1728 SECItem *crypto_param = NULL; | |
1729 PK11SymKey *key = NULL; | |
1730 SECKEYPrivateKey *tmpPK = NULL; | |
1731 SECStatus rv = SECSuccess; | |
1732 CK_RV crv; | |
1733 CK_ULONG encBufLen; | |
1734 CK_MECHANISM_TYPE pbeMechType; | |
1735 CK_MECHANISM_TYPE cryptoMechType; | |
1736 CK_MECHANISM cryptoMech; | |
1737 | |
1738 if (!pwitem || !pk) { | |
1739 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1740 return NULL; | |
1741 } | |
1742 | |
1743 algid = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, | |
1744 &pbeAlgTag, 0, NULL, iteration); | |
1745 if (algid == NULL) { | |
1746 return NULL; | |
1747 } | |
1748 | |
1749 arena = PORT_NewArena(2048); | |
1750 if (arena) | |
1751 epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo); | |
1752 if(epki == NULL) { | |
1753 rv = SECFailure; | |
1754 goto loser; | |
1755 } | |
1756 epki->arena = arena; | |
1757 | |
1758 | |
1759 /* if we didn't specify a slot, use the slot the private key was in */ | |
1760 if (!slot) { | |
1761 slot = pk->pkcs11Slot; | |
1762 } | |
1763 | |
1764 /* if we specified a different slot, and the private key slot can do the | |
1765 * pbe key gen, generate the key in the private key slot so we don't have | |
1766 * to move it later */ | |
1767 pbeMechType = PK11_AlgtagToMechanism(pbeAlgTag); | |
1768 if (slot != pk->pkcs11Slot) { | |
1769 if (PK11_DoesMechanism(pk->pkcs11Slot,pbeMechType)) { | |
1770 slot = pk->pkcs11Slot; | |
1771 } | |
1772 } | |
1773 key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, wincx); | |
1774 if (key == NULL) { | |
1775 rv = SECFailure; | |
1776 goto loser; | |
1777 } | |
1778 | |
1779 cryptoMechType = PK11_GetPBECryptoMechanism(algid, &crypto_param, pwitem); | |
1780 if (cryptoMechType == CKM_INVALID_MECHANISM) { | |
1781 rv = SECFailure; | |
1782 goto loser; | |
1783 } | |
1784 | |
1785 cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMechType); | |
1786 cryptoMech.pParameter = crypto_param ? crypto_param->data : NULL; | |
1787 cryptoMech.ulParameterLen = crypto_param ? crypto_param->len : 0; | |
1788 | |
1789 /* If the key isn't in the private key slot, move it */ | |
1790 if (key->slot != pk->pkcs11Slot) { | |
1791 PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot, | |
1792 key->type, CKA_WRAP, key); | |
1793 if (newkey == NULL) { | |
1794 /* couldn't import the wrapping key, try exporting the | |
1795 * private key */ | |
1796 tmpPK = pk11_loadPrivKey(key->slot, pk, NULL, PR_FALSE, PR_TRUE); | |
1797 if (tmpPK == NULL) { | |
1798 rv = SECFailure; | |
1799 goto loser; | |
1800 } | |
1801 pk = tmpPK; | |
1802 } else { | |
1803 /* free the old key and use the new key */ | |
1804 PK11_FreeSymKey(key); | |
1805 key = newkey; | |
1806 } | |
1807 } | |
1808 | |
1809 /* we are extracting an encrypted privateKey structure. | |
1810 * which needs to be freed along with the buffer into which it is | |
1811 * returned. eventually, we should retrieve an encrypted key using | |
1812 * pkcs8/pkcs5. | |
1813 */ | |
1814 encBufLen = 0; | |
1815 PK11_EnterSlotMonitor(pk->pkcs11Slot); | |
1816 crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, | |
1817 &cryptoMech, key->objectID, pk->pkcs11ID, NULL, | |
1818 &encBufLen); | |
1819 PK11_ExitSlotMonitor(pk->pkcs11Slot); | |
1820 if (crv != CKR_OK) { | |
1821 rv = SECFailure; | |
1822 goto loser; | |
1823 } | |
1824 epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen); | |
1825 if (!epki->encryptedData.data) { | |
1826 rv = SECFailure; | |
1827 goto loser; | |
1828 } | |
1829 PK11_EnterSlotMonitor(pk->pkcs11Slot); | |
1830 crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, | |
1831 &cryptoMech, key->objectID, pk->pkcs11ID, | |
1832 epki->encryptedData.data, &encBufLen); | |
1833 PK11_ExitSlotMonitor(pk->pkcs11Slot); | |
1834 epki->encryptedData.len = (unsigned int) encBufLen; | |
1835 if(crv != CKR_OK) { | |
1836 rv = SECFailure; | |
1837 goto loser; | |
1838 } | |
1839 | |
1840 if(!epki->encryptedData.len) { | |
1841 rv = SECFailure; | |
1842 goto loser; | |
1843 } | |
1844 | |
1845 rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid); | |
1846 | |
1847 loser: | |
1848 if(crypto_param != NULL) { | |
1849 SECITEM_ZfreeItem(crypto_param, PR_TRUE); | |
1850 crypto_param = NULL; | |
1851 } | |
1852 | |
1853 if(key != NULL) { | |
1854 PK11_FreeSymKey(key); | |
1855 } | |
1856 if (tmpPK != NULL) { | |
1857 SECKEY_DestroyPrivateKey(tmpPK); | |
1858 } | |
1859 SECOID_DestroyAlgorithmID(algid, PR_TRUE); | |
1860 | |
1861 if(rv == SECFailure) { | |
1862 if(arena != NULL) { | |
1863 PORT_FreeArena(arena, PR_TRUE); | |
1864 } | |
1865 epki = NULL; | |
1866 } | |
1867 | |
1868 return epki; | |
1869 } | |
1870 | |
1871 SECKEYEncryptedPrivateKeyInfo * | |
1872 PK11_ExportEncryptedPrivateKeyInfo( | |
1873 PK11SlotInfo *slot, /* optional, encrypt key in this slot */ | |
1874 SECOidTag algTag, /* encrypt key with this algorithm */ | |
1875 SECItem *pwitem, /* password for PBE encryption */ | |
1876 CERTCertificate *cert, /* wrap priv key for this user cert */ | |
1877 int iteration, /* interations for PBE alg */ | |
1878 void *wincx) /* context for password callback ? */ | |
1879 { | |
1880 SECKEYEncryptedPrivateKeyInfo *epki = NULL; | |
1881 SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, wincx); | |
1882 if (pk != NULL) { | |
1883 epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk, | |
1884 iteration, wincx); | |
1885 SECKEY_DestroyPrivateKey(pk); | |
1886 } | |
1887 return epki; | |
1888 } | |
1889 | |
1890 SECItem* | |
1891 PK11_DEREncodePublicKey(const SECKEYPublicKey *pubk) | |
1892 { | |
1893 return SECKEY_EncodeDERSubjectPublicKeyInfo(pubk); | |
1894 } | |
1895 | |
1896 char * | |
1897 PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey) | |
1898 { | |
1899 return PK11_GetObjectNickname(privKey->pkcs11Slot,privKey->pkcs11ID); | |
1900 } | |
1901 | |
1902 char * | |
1903 PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey) | |
1904 { | |
1905 return PK11_GetObjectNickname(pubKey->pkcs11Slot,pubKey->pkcs11ID); | |
1906 } | |
1907 | |
1908 SECStatus | |
1909 PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname) | |
1910 { | |
1911 return PK11_SetObjectNickname(privKey->pkcs11Slot, | |
1912 privKey->pkcs11ID,nickname); | |
1913 } | |
1914 | |
1915 SECStatus | |
1916 PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname) | |
1917 { | |
1918 return PK11_SetObjectNickname(pubKey->pkcs11Slot, | |
1919 pubKey->pkcs11ID,nickname); | |
1920 } | |
1921 | |
1922 SECKEYPQGParams * | |
1923 PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey) | |
1924 { | |
1925 CK_ATTRIBUTE pTemplate[] = { | |
1926 { CKA_PRIME, NULL, 0 }, | |
1927 { CKA_SUBPRIME, NULL, 0 }, | |
1928 { CKA_BASE, NULL, 0 }, | |
1929 }; | |
1930 int pTemplateLen = sizeof(pTemplate)/sizeof(pTemplate[0]); | |
1931 PLArenaPool *arena = NULL; | |
1932 SECKEYPQGParams *params; | |
1933 CK_RV crv; | |
1934 | |
1935 | |
1936 arena = PORT_NewArena(2048); | |
1937 if (arena == NULL) { | |
1938 goto loser; | |
1939 } | |
1940 params=(SECKEYPQGParams *)PORT_ArenaZAlloc(arena,sizeof(SECKEYPQGParams)); | |
1941 if (params == NULL) { | |
1942 goto loser; | |
1943 } | |
1944 | |
1945 crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, | |
1946 pTemplate, pTemplateLen); | |
1947 if (crv != CKR_OK) { | |
1948 PORT_SetError( PK11_MapError(crv) ); | |
1949 goto loser; | |
1950 } | |
1951 | |
1952 params->arena = arena; | |
1953 params->prime.data = pTemplate[0].pValue; | |
1954 params->prime.len = pTemplate[0].ulValueLen; | |
1955 params->subPrime.data = pTemplate[1].pValue; | |
1956 params->subPrime.len = pTemplate[1].ulValueLen; | |
1957 params->base.data = pTemplate[2].pValue; | |
1958 params->base.len = pTemplate[2].ulValueLen; | |
1959 | |
1960 return params; | |
1961 | |
1962 loser: | |
1963 if (arena != NULL) { | |
1964 PORT_FreeArena(arena,PR_FALSE); | |
1965 } | |
1966 return NULL; | |
1967 } | |
1968 | |
1969 SECKEYPrivateKey* | |
1970 PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot, | |
1971 SECKEYPrivateKey *privKey) | |
1972 { | |
1973 CK_RV crv; | |
1974 CK_OBJECT_HANDLE newKeyID; | |
1975 | |
1976 static const CK_BBOOL ckfalse = CK_FALSE; | |
1977 static const CK_ATTRIBUTE template[1] = { | |
1978 { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse } | |
1979 }; | |
1980 | |
1981 if (destSlot && destSlot != privKey->pkcs11Slot) { | |
1982 SECKEYPrivateKey *newKey = | |
1983 pk11_loadPrivKey(destSlot, | |
1984 privKey, | |
1985 NULL, /* pubKey */ | |
1986 PR_FALSE, /* token */ | |
1987 PR_FALSE);/* sensitive */ | |
1988 if (newKey) | |
1989 return newKey; | |
1990 } | |
1991 destSlot = privKey->pkcs11Slot; | |
1992 PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx); | |
1993 PK11_EnterSlotMonitor(destSlot); | |
1994 crv = PK11_GETTAB(destSlot)->C_CopyObject( destSlot->session, | |
1995 privKey->pkcs11ID, | |
1996 (CK_ATTRIBUTE *)template, | |
1997 1, &newKeyID); | |
1998 PK11_ExitSlotMonitor(destSlot); | |
1999 | |
2000 if (crv != CKR_OK) { | |
2001 PORT_SetError( PK11_MapError(crv) ); | |
2002 return NULL; | |
2003 } | |
2004 | |
2005 return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/, | |
2006 newKeyID, privKey->wincx); | |
2007 } | |
2008 | |
2009 SECKEYPrivateKey* | |
2010 PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx) | |
2011 { | |
2012 PK11SlotInfo* slot = privk->pkcs11Slot; | |
2013 CK_ATTRIBUTE template[1]; | |
2014 CK_ATTRIBUTE *attrs = template; | |
2015 CK_BBOOL cktrue = CK_TRUE; | |
2016 CK_RV crv; | |
2017 CK_OBJECT_HANDLE newKeyID; | |
2018 CK_SESSION_HANDLE rwsession; | |
2019 | |
2020 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; | |
2021 | |
2022 PK11_Authenticate(slot, PR_TRUE, wincx); | |
2023 rwsession = PK11_GetRWSession(slot); | |
2024 if (rwsession == CK_INVALID_SESSION) { | |
2025 PORT_SetError(SEC_ERROR_BAD_DATA); | |
2026 return NULL; | |
2027 } | |
2028 crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID, | |
2029 template, 1, &newKeyID); | |
2030 PK11_RestoreROSession(slot, rwsession); | |
2031 | |
2032 if (crv != CKR_OK) { | |
2033 PORT_SetError( PK11_MapError(crv) ); | |
2034 return NULL; | |
2035 } | |
2036 | |
2037 return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/, | |
2038 newKeyID, NULL /*wincx*/); | |
2039 } | |
2040 | |
2041 /* | |
2042 * destroy a private key if there are no matching certs. | |
2043 * this function also frees the privKey structure. | |
2044 */ | |
2045 SECStatus | |
2046 PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force) | |
2047 { | |
2048 CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey); | |
2049 SECStatus rv = SECWouldBlock; | |
2050 | |
2051 if (!cert || force) { | |
2052 /* now, then it's safe for the key to go away */ | |
2053 rv = PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID); | |
2054 } | |
2055 if (cert) { | |
2056 CERT_DestroyCertificate(cert); | |
2057 } | |
2058 SECKEY_DestroyPrivateKey(privKey); | |
2059 return rv; | |
2060 } | |
2061 | |
2062 /* | |
2063 * destroy a private key if there are no matching certs. | |
2064 * this function also frees the privKey structure. | |
2065 */ | |
2066 SECStatus | |
2067 PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey) | |
2068 { | |
2069 /* now, then it's safe for the key to go away */ | |
2070 if (pubKey->pkcs11Slot == NULL) { | |
2071 return SECFailure; | |
2072 } | |
2073 PK11_DestroyTokenObject(pubKey->pkcs11Slot,pubKey->pkcs11ID); | |
2074 SECKEY_DestroyPublicKey(pubKey); | |
2075 return SECSuccess; | |
2076 } | |
2077 | |
2078 /* | |
2079 * key call back structure. | |
2080 */ | |
2081 typedef struct pk11KeyCallbackStr { | |
2082 SECStatus (* callback)(SECKEYPrivateKey *,void *); | |
2083 void *callbackArg; | |
2084 void *wincx; | |
2085 } pk11KeyCallback; | |
2086 | |
2087 /* | |
2088 * callback to map Object Handles to Private Keys; | |
2089 */ | |
2090 SECStatus | |
2091 pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg) | |
2092 { | |
2093 SECStatus rv = SECSuccess; | |
2094 SECKEYPrivateKey *privKey; | |
2095 pk11KeyCallback *keycb = (pk11KeyCallback *) arg; | |
2096 if (!arg) { | |
2097 return SECFailure; | |
2098 } | |
2099 | |
2100 privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx); | |
2101 | |
2102 if (privKey == NULL) { | |
2103 return SECFailure; | |
2104 } | |
2105 | |
2106 if (keycb->callback) { | |
2107 rv = (*keycb->callback)(privKey,keycb->callbackArg); | |
2108 } | |
2109 | |
2110 SECKEY_DestroyPrivateKey(privKey); | |
2111 return rv; | |
2112 } | |
2113 | |
2114 /*********************************************************************** | |
2115 * PK11_TraversePrivateKeysInSlot | |
2116 * | |
2117 * Traverses all the private keys on a slot. | |
2118 * | |
2119 * INPUTS | |
2120 * slot | |
2121 * The PKCS #11 slot whose private keys you want to traverse. | |
2122 * callback | |
2123 * A callback function that will be called for each key. | |
2124 * arg | |
2125 * An argument that will be passed to the callback function. | |
2126 */ | |
2127 SECStatus | |
2128 PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot, | |
2129 SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg) | |
2130 { | |
2131 pk11KeyCallback perKeyCB; | |
2132 pk11TraverseSlot perObjectCB; | |
2133 CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY; | |
2134 CK_BBOOL ckTrue = CK_TRUE; | |
2135 CK_ATTRIBUTE theTemplate[2]; | |
2136 int templateSize = 2; | |
2137 | |
2138 theTemplate[0].type = CKA_CLASS; | |
2139 theTemplate[0].pValue = &privkClass; | |
2140 theTemplate[0].ulValueLen = sizeof(privkClass); | |
2141 theTemplate[1].type = CKA_TOKEN; | |
2142 theTemplate[1].pValue = &ckTrue; | |
2143 theTemplate[1].ulValueLen = sizeof(ckTrue); | |
2144 | |
2145 if(slot==NULL) { | |
2146 return SECSuccess; | |
2147 } | |
2148 | |
2149 perObjectCB.callback = pk11_DoKeys; | |
2150 perObjectCB.callbackArg = &perKeyCB; | |
2151 perObjectCB.findTemplate = theTemplate; | |
2152 perObjectCB.templateCount = templateSize; | |
2153 perKeyCB.callback = callback; | |
2154 perKeyCB.callbackArg = arg; | |
2155 perKeyCB.wincx = NULL; | |
2156 | |
2157 return PK11_TraverseSlot(slot, &perObjectCB); | |
2158 } | |
2159 | |
2160 /* | |
2161 * return the private key with the given ID | |
2162 */ | |
2163 CK_OBJECT_HANDLE | |
2164 pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID) | |
2165 { | |
2166 CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY; | |
2167 CK_ATTRIBUTE theTemplate[] = { | |
2168 { CKA_ID, NULL, 0 }, | |
2169 { CKA_CLASS, NULL, 0 }, | |
2170 }; | |
2171 /* if you change the array, change the variable below as well */ | |
2172 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); | |
2173 CK_ATTRIBUTE *attrs = theTemplate; | |
2174 | |
2175 PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++; | |
2176 PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey)); | |
2177 | |
2178 return pk11_FindObjectByTemplate(slot,theTemplate,tsize); | |
2179 } | |
2180 | |
2181 | |
2182 SECKEYPrivateKey * | |
2183 PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx) | |
2184 { | |
2185 CK_OBJECT_HANDLE keyHandle; | |
2186 SECKEYPrivateKey *privKey; | |
2187 | |
2188 keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID); | |
2189 if (keyHandle == CK_INVALID_HANDLE) { | |
2190 return NULL; | |
2191 } | |
2192 privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); | |
2193 return privKey; | |
2194 } | |
2195 | |
2196 /* | |
2197 * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated | |
2198 * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make | |
2199 * smart cards happy. | |
2200 */ | |
2201 SECItem * | |
2202 PK11_MakeIDFromPubKey(SECItem *pubKeyData) | |
2203 { | |
2204 PK11Context *context; | |
2205 SECItem *certCKA_ID; | |
2206 SECStatus rv; | |
2207 | |
2208 if (pubKeyData->len <= SHA1_LENGTH) { | |
2209 /* probably an already hashed value. The strongest known public | |
2210 * key values <= 160 bits would be less than 40 bit symetric in | |
2211 * strength. Don't hash them, just return the value. There are | |
2212 * none at the time of this writing supported by previous versions | |
2213 * of NSS, so change is binary compatible safe */ | |
2214 return SECITEM_DupItem(pubKeyData); | |
2215 } | |
2216 | |
2217 context = PK11_CreateDigestContext(SEC_OID_SHA1); | |
2218 if (context == NULL) { | |
2219 return NULL; | |
2220 } | |
2221 | |
2222 rv = PK11_DigestBegin(context); | |
2223 if (rv == SECSuccess) { | |
2224 rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len); | |
2225 } | |
2226 if (rv != SECSuccess) { | |
2227 PK11_DestroyContext(context,PR_TRUE); | |
2228 return NULL; | |
2229 } | |
2230 | |
2231 certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem)); | |
2232 if (certCKA_ID == NULL) { | |
2233 PK11_DestroyContext(context,PR_TRUE); | |
2234 return NULL; | |
2235 } | |
2236 | |
2237 certCKA_ID->len = SHA1_LENGTH; | |
2238 certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len); | |
2239 if (certCKA_ID->data == NULL) { | |
2240 PORT_Free(certCKA_ID); | |
2241 PK11_DestroyContext(context,PR_TRUE); | |
2242 return NULL; | |
2243 } | |
2244 | |
2245 rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len, | |
2246 SHA1_LENGTH); | |
2247 PK11_DestroyContext(context,PR_TRUE); | |
2248 if (rv != SECSuccess) { | |
2249 SECITEM_FreeItem(certCKA_ID,PR_TRUE); | |
2250 return NULL; | |
2251 } | |
2252 | |
2253 return certCKA_ID; | |
2254 } | |
2255 | |
2256 /* Looking for PK11_GetKeyIDFromPrivateKey? | |
2257 * Call PK11_GetLowLevelKeyIDForPrivateKey instead. | |
2258 */ | |
2259 | |
2260 | |
2261 SECItem * | |
2262 PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey) | |
2263 { | |
2264 return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID); | |
2265 } | |
2266 | |
2267 static SECStatus | |
2268 privateKeyListCallback(SECKEYPrivateKey *key, void *arg) | |
2269 { | |
2270 SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList*)arg; | |
2271 return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key)); | |
2272 } | |
2273 | |
2274 SECKEYPrivateKeyList* | |
2275 PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot) | |
2276 { | |
2277 SECStatus status; | |
2278 SECKEYPrivateKeyList *keys; | |
2279 | |
2280 keys = SECKEY_NewPrivateKeyList(); | |
2281 if(keys == NULL) return NULL; | |
2282 | |
2283 status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback, | |
2284 (void*)keys); | |
2285 | |
2286 if( status != SECSuccess ) { | |
2287 SECKEY_DestroyPrivateKeyList(keys); | |
2288 keys = NULL; | |
2289 } | |
2290 | |
2291 return keys; | |
2292 } | |
2293 | |
2294 SECKEYPublicKeyList* | |
2295 PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname) | |
2296 { | |
2297 CK_ATTRIBUTE findTemp[4]; | |
2298 CK_ATTRIBUTE *attrs; | |
2299 CK_BBOOL ckTrue = CK_TRUE; | |
2300 CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY; | |
2301 int tsize = 0; | |
2302 int objCount = 0; | |
2303 CK_OBJECT_HANDLE *key_ids; | |
2304 SECKEYPublicKeyList *keys; | |
2305 int i,len; | |
2306 | |
2307 | |
2308 attrs = findTemp; | |
2309 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; | |
2310 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; | |
2311 if (nickname) { | |
2312 len = PORT_Strlen(nickname); | |
2313 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++; | |
2314 } | |
2315 tsize = attrs - findTemp; | |
2316 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); | |
2317 | |
2318 key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount); | |
2319 if (key_ids == NULL) { | |
2320 return NULL; | |
2321 } | |
2322 keys = SECKEY_NewPublicKeyList(); | |
2323 if (keys == NULL) { | |
2324 PORT_Free(key_ids); | |
2325 return NULL; | |
2326 } | |
2327 | |
2328 for (i=0; i < objCount ; i++) { | |
2329 SECKEYPublicKey *pubKey = | |
2330 PK11_ExtractPublicKey(slot,nullKey,key_ids[i]); | |
2331 if (pubKey) { | |
2332 SECKEY_AddPublicKeyToListTail(keys, pubKey); | |
2333 } | |
2334 } | |
2335 | |
2336 PORT_Free(key_ids); | |
2337 return keys; | |
2338 } | |
2339 | |
2340 SECKEYPrivateKeyList* | |
2341 PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) | |
2342 { | |
2343 CK_ATTRIBUTE findTemp[4]; | |
2344 CK_ATTRIBUTE *attrs; | |
2345 CK_BBOOL ckTrue = CK_TRUE; | |
2346 CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY; | |
2347 int tsize = 0; | |
2348 int objCount = 0; | |
2349 CK_OBJECT_HANDLE *key_ids; | |
2350 SECKEYPrivateKeyList *keys; | |
2351 int i,len; | |
2352 | |
2353 | |
2354 attrs = findTemp; | |
2355 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; | |
2356 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; | |
2357 if (nickname) { | |
2358 len = PORT_Strlen(nickname); | |
2359 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++; | |
2360 } | |
2361 tsize = attrs - findTemp; | |
2362 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); | |
2363 | |
2364 key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount); | |
2365 if (key_ids == NULL) { | |
2366 return NULL; | |
2367 } | |
2368 keys = SECKEY_NewPrivateKeyList(); | |
2369 if (keys == NULL) { | |
2370 PORT_Free(key_ids); | |
2371 return NULL; | |
2372 } | |
2373 | |
2374 for (i=0; i < objCount ; i++) { | |
2375 SECKEYPrivateKey *privKey = | |
2376 PK11_MakePrivKey(slot,nullKey,PR_TRUE,key_ids[i],wincx); | |
2377 SECKEY_AddPrivateKeyToListTail(keys, privKey); | |
2378 } | |
2379 | |
2380 PORT_Free(key_ids); | |
2381 return keys; | |
2382 } | |
2383 |