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