Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / pk11wrap / pk11akey.c
blobc4c6f906b912b9283a7ca1fba7a16ea19c4d3013
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Dr Stephen Henson <stephen.henson@gemplus.com>
23 * Dr Vipul Gupta <vipul.gupta@sun.com>, and
24 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 * This file contains functions to manage asymetric keys, (public and
41 * private keys).
43 #include "seccomon.h"
44 #include "secmod.h"
45 #include "secmodi.h"
46 #include "secmodti.h"
47 #include "pkcs11.h"
48 #include "pkcs11t.h"
49 #include "pk11func.h"
50 #include "cert.h"
51 #include "key.h"
52 #include "secitem.h"
53 #include "secasn1.h"
54 #include "secoid.h"
55 #include "secerr.h"
56 #include "sslerr.h"
57 #include "sechash.h"
59 #include "secpkcs5.h"
60 #include "ec.h"
63 * import a public key into the desired slot
65 CK_OBJECT_HANDLE
66 PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
67 PRBool isToken)
69 CK_BBOOL cktrue = CK_TRUE;
70 CK_BBOOL ckfalse = CK_FALSE;
71 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
72 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
73 CK_OBJECT_HANDLE objectID;
74 CK_ATTRIBUTE theTemplate[10];
75 CK_ATTRIBUTE *signedattr = NULL;
76 CK_ATTRIBUTE *attrs = theTemplate;
77 int signedcount = 0;
78 int templateCount = 0;
79 SECStatus rv;
81 /* if we already have an object in the desired slot, use it */
82 if (!isToken && pubKey->pkcs11Slot == slot) {
83 return pubKey->pkcs11ID;
86 /* free the existing key */
87 if (pubKey->pkcs11Slot != NULL) {
88 PK11SlotInfo *oSlot = pubKey->pkcs11Slot;
89 PK11_EnterSlotMonitor(oSlot);
90 (void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
91 pubKey->pkcs11ID);
92 PK11_ExitSlotMonitor(oSlot);
93 PK11_FreeSlot(oSlot);
94 pubKey->pkcs11Slot = NULL;
96 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
97 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
98 PK11_SETATTRS(attrs, CKA_TOKEN, isToken ? &cktrue : &ckfalse,
99 sizeof(CK_BBOOL) ); attrs++;
101 /* now import the key */
103 switch (pubKey->keyType) {
104 case rsaKey:
105 keyType = CKK_RSA;
106 PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, sizeof(CK_BBOOL) ); attrs++;
107 PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue,
108 sizeof(CK_BBOOL) ); attrs++;
109 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); attrs++;
110 signedattr = attrs;
111 PK11_SETATTRS(attrs, CKA_MODULUS, pubKey->u.rsa.modulus.data,
112 pubKey->u.rsa.modulus.len); attrs++;
113 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
114 pubKey->u.rsa.publicExponent.data,
115 pubKey->u.rsa.publicExponent.len); attrs++;
116 break;
117 case dsaKey:
118 keyType = CKK_DSA;
119 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
120 signedattr = attrs;
121 PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.dsa.params.prime.data,
122 pubKey->u.dsa.params.prime.len); attrs++;
123 PK11_SETATTRS(attrs,CKA_SUBPRIME,pubKey->u.dsa.params.subPrime.data,
124 pubKey->u.dsa.params.subPrime.len); attrs++;
125 PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.dsa.params.base.data,
126 pubKey->u.dsa.params.base.len); attrs++;
127 PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dsa.publicValue.data,
128 pubKey->u.dsa.publicValue.len); attrs++;
129 break;
130 case fortezzaKey:
131 keyType = CKK_DSA;
132 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
133 signedattr = attrs;
134 PK11_SETATTRS(attrs, CKA_PRIME,pubKey->u.fortezza.params.prime.data,
135 pubKey->u.fortezza.params.prime.len); attrs++;
136 PK11_SETATTRS(attrs,CKA_SUBPRIME,
137 pubKey->u.fortezza.params.subPrime.data,
138 pubKey->u.fortezza.params.subPrime.len);attrs++;
139 PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.fortezza.params.base.data,
140 pubKey->u.fortezza.params.base.len); attrs++;
141 PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.fortezza.DSSKey.data,
142 pubKey->u.fortezza.DSSKey.len); attrs++;
143 break;
144 case dhKey:
145 keyType = CKK_DH;
146 PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
147 signedattr = attrs;
148 PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.dh.prime.data,
149 pubKey->u.dh.prime.len); attrs++;
150 PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.dh.base.data,
151 pubKey->u.dh.base.len); attrs++;
152 PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dh.publicValue.data,
153 pubKey->u.dh.publicValue.len); attrs++;
154 break;
155 case ecKey:
156 keyType = CKK_EC;
157 PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
158 PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
159 signedattr = attrs;
160 PK11_SETATTRS(attrs, CKA_EC_PARAMS,
161 pubKey->u.ec.DEREncodedParams.data,
162 pubKey->u.ec.DEREncodedParams.len); attrs++;
163 PK11_SETATTRS(attrs, CKA_EC_POINT, pubKey->u.ec.publicValue.data,
164 pubKey->u.ec.publicValue.len); attrs++;
165 break;
166 default:
167 PORT_SetError( SEC_ERROR_BAD_KEY );
168 return CK_INVALID_HANDLE;
171 templateCount = attrs - theTemplate;
172 signedcount = attrs - signedattr;
173 PORT_Assert(templateCount <= (sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)));
174 for (attrs=signedattr; signedcount; attrs++, signedcount--) {
175 pk11_SignedToUnsigned(attrs);
177 rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
178 templateCount, isToken, &objectID);
179 if ( rv != SECSuccess) {
180 return CK_INVALID_HANDLE;
184 pubKey->pkcs11ID = objectID;
185 pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
187 return objectID;
191 * take an attribute and copy it into a secitem
193 static CK_RV
194 pk11_Attr2SecItem(PRArenaPool *arena, CK_ATTRIBUTE *attr, SECItem *item)
196 item->data = NULL;
198 (void)SECITEM_AllocItem(arena, item, attr->ulValueLen);
199 if (item->data == NULL) {
200 return CKR_HOST_MEMORY;
202 PORT_Memcpy(item->data, attr->pValue, item->len);
203 return CKR_OK;
207 * extract a public key from a slot and id
209 SECKEYPublicKey *
210 PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id)
212 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
213 PRArenaPool *arena;
214 PRArenaPool *tmp_arena;
215 SECKEYPublicKey *pubKey;
216 int templateCount = 0;
217 CK_KEY_TYPE pk11KeyType;
218 CK_RV crv;
219 CK_ATTRIBUTE template[8];
220 CK_ATTRIBUTE *attrs= template;
221 CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value;
222 CK_ATTRIBUTE *ecparams;
224 /* if we didn't know the key type, get it */
225 if (keyType== nullKey) {
227 pk11KeyType = PK11_ReadULongAttribute(slot,id,CKA_KEY_TYPE);
228 if (pk11KeyType == CK_UNAVAILABLE_INFORMATION) {
229 return NULL;
231 switch (pk11KeyType) {
232 case CKK_RSA:
233 keyType = rsaKey;
234 break;
235 case CKK_DSA:
236 keyType = dsaKey;
237 break;
238 case CKK_DH:
239 keyType = dhKey;
240 break;
241 case CKK_EC:
242 keyType = ecKey;
243 break;
244 default:
245 PORT_SetError( SEC_ERROR_BAD_KEY );
246 return NULL;
251 /* now we need to create space for the public key */
252 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
253 if (arena == NULL) return NULL;
254 tmp_arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
255 if (tmp_arena == NULL) {
256 PORT_FreeArena (arena, PR_FALSE);
257 return NULL;
261 pubKey = (SECKEYPublicKey *)
262 PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
263 if (pubKey == NULL) {
264 PORT_FreeArena (arena, PR_FALSE);
265 PORT_FreeArena (tmp_arena, PR_FALSE);
266 return NULL;
269 pubKey->arena = arena;
270 pubKey->keyType = keyType;
271 pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
272 pubKey->pkcs11ID = id;
273 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass,
274 sizeof(keyClass)); attrs++;
275 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType,
276 sizeof(pk11KeyType) ); attrs++;
277 switch (pubKey->keyType) {
278 case rsaKey:
279 modulus = attrs;
280 PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); attrs++;
281 exponent = attrs;
282 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0); attrs++;
284 templateCount = attrs - template;
285 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
286 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
287 if (crv != CKR_OK) break;
289 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) {
290 crv = CKR_OBJECT_HANDLE_INVALID;
291 break;
293 crv = pk11_Attr2SecItem(arena,modulus,&pubKey->u.rsa.modulus);
294 if (crv != CKR_OK) break;
295 crv = pk11_Attr2SecItem(arena,exponent,&pubKey->u.rsa.publicExponent);
296 if (crv != CKR_OK) break;
297 break;
298 case dsaKey:
299 prime = attrs;
300 PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++;
301 subprime = attrs;
302 PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++;
303 base = attrs;
304 PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++;
305 value = attrs;
306 PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++;
307 templateCount = attrs - template;
308 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
309 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
310 if (crv != CKR_OK) break;
312 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {
313 crv = CKR_OBJECT_HANDLE_INVALID;
314 break;
316 crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dsa.params.prime);
317 if (crv != CKR_OK) break;
318 crv = pk11_Attr2SecItem(arena,subprime,&pubKey->u.dsa.params.subPrime);
319 if (crv != CKR_OK) break;
320 crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dsa.params.base);
321 if (crv != CKR_OK) break;
322 crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dsa.publicValue);
323 if (crv != CKR_OK) break;
324 break;
325 case dhKey:
326 prime = attrs;
327 PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++;
328 base = attrs;
329 PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++;
330 value =attrs;
331 PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++;
332 templateCount = attrs - template;
333 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
334 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
335 if (crv != CKR_OK) break;
337 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) {
338 crv = CKR_OBJECT_HANDLE_INVALID;
339 break;
341 crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dh.prime);
342 if (crv != CKR_OK) break;
343 crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dh.base);
344 if (crv != CKR_OK) break;
345 crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue);
346 if (crv != CKR_OK) break;
347 break;
348 case ecKey:
349 pubKey->u.ec.size = 0;
350 ecparams = attrs;
351 PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0); attrs++;
352 value =attrs;
353 PK11_SETATTRS(attrs, CKA_EC_POINT, NULL, 0); attrs++;
354 templateCount = attrs - template;
355 PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
356 crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
357 if (crv != CKR_OK) break;
359 if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_EC)) {
360 crv = CKR_OBJECT_HANDLE_INVALID;
361 break;
364 crv = pk11_Attr2SecItem(arena,ecparams,
365 &pubKey->u.ec.DEREncodedParams);
366 if (crv != CKR_OK) break;
367 crv = pk11_Attr2SecItem(arena,value,&pubKey->u.ec.publicValue);
368 if (crv != CKR_OK) break;
369 break;
370 case fortezzaKey:
371 case nullKey:
372 default:
373 crv = CKR_OBJECT_HANDLE_INVALID;
374 break;
377 PORT_FreeArena(tmp_arena,PR_FALSE);
379 if (crv != CKR_OK) {
380 PORT_FreeArena(arena,PR_FALSE);
381 PK11_FreeSlot(slot);
382 PORT_SetError( PK11_MapError(crv) );
383 return NULL;
386 return pubKey;
390 * Build a Private Key structure from raw PKCS #11 information.
392 SECKEYPrivateKey *
393 PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
394 PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
396 PRArenaPool *arena;
397 SECKEYPrivateKey *privKey;
398 PRBool isPrivate;
399 SECStatus rv;
401 /* don't know? look it up */
402 if (keyType == nullKey) {
403 CK_KEY_TYPE pk11Type = CKK_RSA;
405 pk11Type = PK11_ReadULongAttribute(slot,privID,CKA_KEY_TYPE);
406 isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN);
407 switch (pk11Type) {
408 case CKK_RSA: keyType = rsaKey; break;
409 case CKK_DSA: keyType = dsaKey; break;
410 case CKK_DH: keyType = dhKey; break;
411 case CKK_KEA: keyType = fortezzaKey; break;
412 case CKK_EC: keyType = ecKey; break;
413 default:
414 break;
418 /* if the key is private, make sure we are authenticated to the
419 * token before we try to use it */
420 isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE);
421 if (isPrivate) {
422 rv = PK11_Authenticate(slot, PR_TRUE, wincx);
423 if (rv != SECSuccess) {
424 return NULL;
428 /* now we need to create space for the private key */
429 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
430 if (arena == NULL) return NULL;
432 privKey = (SECKEYPrivateKey *)
433 PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
434 if (privKey == NULL) {
435 PORT_FreeArena(arena, PR_FALSE);
436 return NULL;
439 privKey->arena = arena;
440 privKey->keyType = keyType;
441 privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
442 privKey->pkcs11ID = privID;
443 privKey->pkcs11IsTemp = isTemp;
444 privKey->wincx = wincx;
446 return privKey;
450 PK11SlotInfo *
451 PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
453 PK11SlotInfo *slot = key->pkcs11Slot;
454 slot = PK11_ReferenceSlot(slot);
455 return slot;
459 * Get the modulus length for raw parsing
462 PK11_GetPrivateModulusLen(SECKEYPrivateKey *key)
464 CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 };
465 PK11SlotInfo *slot = key->pkcs11Slot;
466 CK_RV crv;
467 int length;
469 switch (key->keyType) {
470 case rsaKey:
471 crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1);
472 if (crv != CKR_OK) {
473 PORT_SetError( PK11_MapError(crv) );
474 return -1;
476 length = theTemplate.ulValueLen;
477 if ( *(unsigned char *)theTemplate.pValue == 0) {
478 length--;
480 if (theTemplate.pValue != NULL)
481 PORT_Free(theTemplate.pValue);
482 return (int) length;
484 case fortezzaKey:
485 case dsaKey:
486 case dhKey:
487 default:
488 break;
490 if (theTemplate.pValue != NULL)
491 PORT_Free(theTemplate.pValue);
492 PORT_SetError( SEC_ERROR_INVALID_KEY );
493 return -1;
499 * take a private key in one pkcs11 module and load it into another:
500 * NOTE: the source private key is a rare animal... it can't be sensitive.
501 * This is used to do a key gen using one pkcs11 module and storing the
502 * result into another.
504 static SECKEYPrivateKey *
505 pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey,
506 SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags)
508 CK_ATTRIBUTE privTemplate[] = {
509 /* class must be first */
510 { CKA_CLASS, NULL, 0 },
511 { CKA_KEY_TYPE, NULL, 0 },
512 { CKA_ID, NULL, 0 },
513 #ifdef notdef
514 { CKA_LABEL, NULL, 0 },
515 { CKA_SUBJECT, NULL, 0 },
516 #endif
517 /* RSA */
518 { CKA_MODULUS, NULL, 0 },
519 { CKA_PRIVATE_EXPONENT, NULL, 0 },
520 { CKA_PUBLIC_EXPONENT, NULL, 0 },
521 { CKA_PRIME_1, NULL, 0 },
522 { CKA_PRIME_2, NULL, 0 },
523 { CKA_EXPONENT_1, NULL, 0 },
524 { CKA_EXPONENT_2, NULL, 0 },
525 { CKA_COEFFICIENT, NULL, 0 },
526 /* reserve space for the attributes that may be
527 * specified in attrFlags */
528 { CKA_TOKEN, NULL, 0 },
529 { CKA_PRIVATE, NULL, 0 },
530 { CKA_MODIFIABLE, NULL, 0 },
531 { CKA_SENSITIVE, NULL, 0 },
532 { CKA_EXTRACTABLE, NULL, 0 },
533 #define NUM_RESERVED_ATTRS 5 /* number of reserved attributes above */
535 CK_BBOOL cktrue = CK_TRUE;
536 CK_BBOOL ckfalse = CK_FALSE;
537 CK_ATTRIBUTE *attrs = NULL, *ap;
538 const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]);
539 PRArenaPool *arena;
540 CK_OBJECT_HANDLE objectID;
541 int i, count = 0;
542 int extra_count = 0;
543 CK_RV crv;
544 SECStatus rv;
545 PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
547 if (pk11_BadAttrFlags(attrFlags)) {
548 PORT_SetError(SEC_ERROR_INVALID_ARGS);
549 return NULL;
552 for (i=0; i < templateSize; i++) {
553 if (privTemplate[i].type == CKA_MODULUS) {
554 attrs= &privTemplate[i];
555 count = i;
556 break;
559 PORT_Assert(attrs != NULL);
560 if (attrs == NULL) {
561 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
562 return NULL;
565 ap = attrs;
567 switch (privKey->keyType) {
568 case rsaKey:
569 count = templateSize - NUM_RESERVED_ATTRS;
570 extra_count = count - (attrs - privTemplate);
571 break;
572 case dsaKey:
573 ap->type = CKA_PRIME; ap++; count++; extra_count++;
574 ap->type = CKA_SUBPRIME; ap++; count++; extra_count++;
575 ap->type = CKA_BASE; ap++; count++; extra_count++;
576 ap->type = CKA_VALUE; ap++; count++; extra_count++;
577 break;
578 case dhKey:
579 ap->type = CKA_PRIME; ap++; count++; extra_count++;
580 ap->type = CKA_BASE; ap++; count++; extra_count++;
581 ap->type = CKA_VALUE; ap++; count++; extra_count++;
582 break;
583 case ecKey:
584 ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++;
585 ap->type = CKA_VALUE; ap++; count++; extra_count++;
586 break;
587 default:
588 count = 0;
589 extra_count = 0;
590 break;
593 if (count == 0) {
594 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
595 return NULL;
598 arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
599 if (arena == NULL) return NULL;
601 * read out the old attributes.
603 crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
604 privTemplate,count);
605 if (crv != CKR_OK) {
606 PORT_SetError( PK11_MapError(crv) );
607 PORT_FreeArena(arena, PR_TRUE);
608 return NULL;
611 /* Set token, private, modifiable, sensitive, and extractable */
612 count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
613 &cktrue, &ckfalse);
615 /* Not everyone can handle zero padded key values, give
616 * them the raw data as unsigned */
617 for (ap=attrs; extra_count; ap++, extra_count--) {
618 pk11_SignedToUnsigned(ap);
621 /* now Store the puppies */
622 rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate,
623 count, token, &objectID);
624 PORT_FreeArena(arena, PR_TRUE);
625 if (rv != SECSuccess) {
626 return NULL;
629 /* try loading the public key */
630 if (pubKey) {
631 PK11_ImportPublicKey(slot, pubKey, token);
632 if (pubKey->pkcs11Slot) {
633 PK11_FreeSlot(pubKey->pkcs11Slot);
634 pubKey->pkcs11Slot = NULL;
635 pubKey->pkcs11ID = CK_INVALID_HANDLE;
639 /* build new key structure */
640 return PK11_MakePrivKey(slot, privKey->keyType, !token,
641 objectID, privKey->wincx);
644 static SECKEYPrivateKey *
645 pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey,
646 SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive)
648 PK11AttrFlags attrFlags = 0;
649 if (token) {
650 attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
651 } else {
652 attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC);
654 if (sensitive) {
655 attrFlags |= PK11_ATTR_SENSITIVE;
656 } else {
657 attrFlags |= PK11_ATTR_INSENSITIVE;
659 return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags);
663 * export this for PSM
665 SECKEYPrivateKey *
666 PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey,
667 SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive)
669 return pk11_loadPrivKey(slot,privKey,pubKey,token,sensitive);
674 * Use the token to generate a key pair.
676 SECKEYPrivateKey *
677 PK11_GenerateKeyPairWithOpFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
678 void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags,
679 CK_FLAGS opFlags, CK_FLAGS opFlagsMask, void *wincx)
681 /* we have to use these native types because when we call PKCS 11 modules
682 * we have to make sure that we are using the correct sizes for all the
683 * parameters. */
684 CK_BBOOL ckfalse = CK_FALSE;
685 CK_BBOOL cktrue = CK_TRUE;
686 CK_ULONG modulusBits;
687 CK_BYTE publicExponent[4];
688 CK_ATTRIBUTE privTemplate[] = {
689 { CKA_SENSITIVE, NULL, 0},
690 { CKA_TOKEN, NULL, 0},
691 { CKA_PRIVATE, NULL, 0},
692 { CKA_DERIVE, NULL, 0},
693 { CKA_UNWRAP, NULL, 0},
694 { CKA_SIGN, NULL, 0},
695 { CKA_DECRYPT, NULL, 0},
696 { CKA_EXTRACTABLE, NULL, 0},
697 { CKA_MODIFIABLE, NULL, 0},
699 CK_ATTRIBUTE rsaPubTemplate[] = {
700 { CKA_MODULUS_BITS, NULL, 0},
701 { CKA_PUBLIC_EXPONENT, NULL, 0},
702 { CKA_TOKEN, NULL, 0},
703 { CKA_DERIVE, NULL, 0},
704 { CKA_WRAP, NULL, 0},
705 { CKA_VERIFY, NULL, 0},
706 { CKA_VERIFY_RECOVER, NULL, 0},
707 { CKA_ENCRYPT, NULL, 0},
708 { CKA_MODIFIABLE, NULL, 0},
710 CK_ATTRIBUTE dsaPubTemplate[] = {
711 { CKA_PRIME, NULL, 0 },
712 { CKA_SUBPRIME, NULL, 0 },
713 { CKA_BASE, NULL, 0 },
714 { CKA_TOKEN, NULL, 0},
715 { CKA_DERIVE, NULL, 0},
716 { CKA_WRAP, NULL, 0},
717 { CKA_VERIFY, NULL, 0},
718 { CKA_VERIFY_RECOVER, NULL, 0},
719 { CKA_ENCRYPT, NULL, 0},
720 { CKA_MODIFIABLE, NULL, 0},
722 CK_ATTRIBUTE dhPubTemplate[] = {
723 { CKA_PRIME, NULL, 0 },
724 { CKA_BASE, NULL, 0 },
725 { CKA_TOKEN, NULL, 0},
726 { CKA_DERIVE, NULL, 0},
727 { CKA_WRAP, NULL, 0},
728 { CKA_VERIFY, NULL, 0},
729 { CKA_VERIFY_RECOVER, NULL, 0},
730 { CKA_ENCRYPT, NULL, 0},
731 { CKA_MODIFIABLE, NULL, 0},
733 CK_ATTRIBUTE ecPubTemplate[] = {
734 { CKA_EC_PARAMS, NULL, 0 },
735 { CKA_TOKEN, NULL, 0},
736 { CKA_DERIVE, NULL, 0},
737 { CKA_WRAP, NULL, 0},
738 { CKA_VERIFY, NULL, 0},
739 { CKA_VERIFY_RECOVER, NULL, 0},
740 { CKA_ENCRYPT, NULL, 0},
741 { CKA_MODIFIABLE, NULL, 0},
743 SECKEYECParams * ecParams;
745 /*CK_ULONG key_size = 0;*/
746 CK_ATTRIBUTE *pubTemplate;
747 int privCount = 0;
748 int pubCount = 0;
749 PK11RSAGenParams *rsaParams;
750 SECKEYPQGParams *dsaParams;
751 SECKEYDHParams * dhParams;
752 CK_MECHANISM mechanism;
753 CK_MECHANISM test_mech;
754 CK_MECHANISM test_mech2;
755 CK_SESSION_HANDLE session_handle;
756 CK_RV crv;
757 CK_OBJECT_HANDLE privID,pubID;
758 SECKEYPrivateKey *privKey;
759 KeyType keyType;
760 PRBool restore;
761 int peCount,i;
762 CK_ATTRIBUTE *attrs;
763 CK_ATTRIBUTE *privattrs;
764 SECItem *pubKeyIndex;
765 CK_ATTRIBUTE setTemplate;
766 CK_MECHANISM_INFO mechanism_info;
767 CK_OBJECT_CLASS keyClass;
768 SECItem *cka_id;
769 PRBool haslock = PR_FALSE;
770 PRBool pubIsToken = PR_FALSE;
771 PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
772 /* subset of attrFlags applicable to the public key */
773 PK11AttrFlags pubKeyAttrFlags = attrFlags &
774 (PK11_ATTR_TOKEN | PK11_ATTR_SESSION
775 | PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
777 if (pk11_BadAttrFlags(attrFlags)) {
778 PORT_SetError( SEC_ERROR_INVALID_ARGS );
779 return NULL;
783 * The opFlags and opFlagMask parameters allow us to control the
784 * settings of the key usage attributes (CKA_ENCRYPT and friends).
785 * opFlagMask is set to one if the flag is specified in opFlags and
786 * zero if it is to take on a default value calculated by
787 * PK11_GenerateKeyPairWithOpFlags.
788 * opFlags specifies the actual value of the flag 1 or 0.
789 * Bits not corresponding to one bits in opFlagMask should be zero.
792 /* if we are trying to turn on a flag, it better be in the mask */
793 PORT_Assert ((opFlags & ~opFlagsMask) == 0);
794 opFlags &= opFlagsMask;
796 PORT_Assert(slot != NULL);
797 if (slot == NULL) {
798 PORT_SetError( SEC_ERROR_NO_MODULE);
799 return NULL;
802 /* if our slot really doesn't do this mechanism, Generate the key
803 * in our internal token and write it out */
804 if (!PK11_DoesMechanism(slot,type)) {
805 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
807 /* don't loop forever looking for a slot */
808 if (slot == int_slot) {
809 PK11_FreeSlot(int_slot);
810 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
811 return NULL;
814 /* if there isn't a suitable slot, then we can't do the keygen */
815 if (int_slot == NULL) {
816 PORT_SetError( SEC_ERROR_NO_MODULE );
817 return NULL;
820 /* generate the temporary key to load */
821 privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE,
822 PR_FALSE, wincx);
823 PK11_FreeSlot(int_slot);
825 /* if successful, load the temp key into the new token */
826 if (privKey != NULL) {
827 SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
828 privKey,*pubKey,attrFlags);
829 SECKEY_DestroyPrivateKey(privKey);
830 if (newPrivKey == NULL) {
831 SECKEY_DestroyPublicKey(*pubKey);
832 *pubKey = NULL;
834 return newPrivKey;
836 return NULL;
840 mechanism.mechanism = type;
841 mechanism.pParameter = NULL;
842 mechanism.ulParameterLen = 0;
843 test_mech.pParameter = NULL;
844 test_mech.ulParameterLen = 0;
845 test_mech2.mechanism = CKM_INVALID_MECHANISM;
846 test_mech2.pParameter = NULL;
847 test_mech2.ulParameterLen = 0;
849 /* set up the private key template */
850 privattrs = privTemplate;
851 privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
852 &cktrue, &ckfalse);
854 /* set up the mechanism specific info */
855 switch (type) {
856 case CKM_RSA_PKCS_KEY_PAIR_GEN:
857 case CKM_RSA_X9_31_KEY_PAIR_GEN:
858 rsaParams = (PK11RSAGenParams *)param;
859 if (rsaParams->pe == 0) {
860 PORT_SetError(SEC_ERROR_INVALID_ARGS);
861 return NULL;
863 modulusBits = rsaParams->keySizeInBits;
864 peCount = 0;
866 /* convert pe to a PKCS #11 string */
867 for (i=0; i < 4; i++) {
868 if (peCount || (rsaParams->pe &
869 ((unsigned long)0xff000000L >> (i*8)))) {
870 publicExponent[peCount] =
871 (CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);
872 peCount++;
875 PORT_Assert(peCount != 0);
876 attrs = rsaPubTemplate;
877 PK11_SETATTRS(attrs, CKA_MODULUS_BITS,
878 &modulusBits, sizeof(modulusBits)); attrs++;
879 PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
880 publicExponent, peCount);attrs++;
881 pubTemplate = rsaPubTemplate;
882 keyType = rsaKey;
883 test_mech.mechanism = CKM_RSA_PKCS;
884 break;
885 case CKM_DSA_KEY_PAIR_GEN:
886 dsaParams = (SECKEYPQGParams *)param;
887 attrs = dsaPubTemplate;
888 PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
889 dsaParams->prime.len); attrs++;
890 PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
891 dsaParams->subPrime.len); attrs++;
892 PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
893 dsaParams->base.len); attrs++;
894 pubTemplate = dsaPubTemplate;
895 keyType = dsaKey;
896 test_mech.mechanism = CKM_DSA;
897 break;
898 case CKM_DH_PKCS_KEY_PAIR_GEN:
899 dhParams = (SECKEYDHParams *)param;
900 attrs = dhPubTemplate;
901 PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
902 dhParams->prime.len); attrs++;
903 PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
904 dhParams->base.len); attrs++;
905 pubTemplate = dhPubTemplate;
906 keyType = dhKey;
907 test_mech.mechanism = CKM_DH_PKCS_DERIVE;
908 break;
909 case CKM_EC_KEY_PAIR_GEN:
910 ecParams = (SECKEYECParams *)param;
911 attrs = ecPubTemplate;
912 PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data,
913 ecParams->len); attrs++;
914 pubTemplate = ecPubTemplate;
915 keyType = ecKey;
917 * ECC supports 2 different mechanism types (unlike RSA, which
918 * supports different usages with the same mechanism).
919 * We may need to query both mechanism types and or the results
920 * together -- but we only do that if either the user has
921 * requested both usages, or not specified any usages.
923 if ((opFlags & (CKF_SIGN|CKF_DERIVE)) == (CKF_SIGN|CKF_DERIVE)) {
924 /* We've explicitly turned on both flags, use both mechanism */
925 test_mech.mechanism = CKM_ECDH1_DERIVE;
926 test_mech2.mechanism = CKM_ECDSA;
927 } else if (opFlags & CKF_SIGN) {
928 /* just do signing */
929 test_mech.mechanism = CKM_ECDSA;
930 } else if (opFlags & CKF_DERIVE) {
931 /* just do ECDH */
932 test_mech.mechanism = CKM_ECDH1_DERIVE;
933 } else {
934 /* neither was specified default to both */
935 test_mech.mechanism = CKM_ECDH1_DERIVE;
936 test_mech2.mechanism = CKM_ECDSA;
938 break;
939 default:
940 PORT_SetError( SEC_ERROR_BAD_KEY );
941 return NULL;
944 /* now query the slot to find out how "good" a key we can generate */
945 if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
946 crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
947 test_mech.mechanism,&mechanism_info);
949 * EC keys are used in multiple different types of mechanism, if we
950 * are using dual use keys, we need to query the second mechanism
951 * as well.
953 if (test_mech2.mechanism != CKM_INVALID_MECHANISM) {
954 CK_MECHANISM_INFO mechanism_info2;
955 CK_RV crv2;
957 if (crv != CKR_OK) {
958 /* the first failed, make sure there is no trash in the
959 * mechanism flags when we or it below */
960 mechanism_info.flags = 0;
962 crv2 = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
963 test_mech2.mechanism, &mechanism_info2);
964 if (crv2 == CKR_OK) {
965 crv = CKR_OK; /* succeed if either mechnaism info succeeds */
966 /* combine the 2 sets of mechnanism flags */
967 mechanism_info.flags |= mechanism_info2.flags;
970 if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
971 if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
972 /* must be old module... guess what it should be... */
973 switch (test_mech.mechanism) {
974 case CKM_RSA_PKCS:
975 mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT |
976 CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);
977 break;
978 case CKM_DSA:
979 mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
980 break;
981 case CKM_DH_PKCS_DERIVE:
982 mechanism_info.flags = CKF_DERIVE;
983 break;
984 case CKM_ECDH1_DERIVE:
985 mechanism_info.flags = CKF_DERIVE;
986 if (test_mech2.mechanism == CKM_ECDSA) {
987 mechanism_info.flags |= CKF_SIGN | CKF_VERIFY;
989 break;
990 case CKM_ECDSA:
991 mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
992 break;
993 default:
994 break;
997 /* now adjust our flags according to the user's key usage passed to us */
998 mechanism_info.flags = (mechanism_info.flags & (~opFlagsMask)) | opFlags;
999 /* set the public key attributes */
1000 attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
1001 &cktrue, &ckfalse);
1002 PK11_SETATTRS(attrs, CKA_DERIVE,
1003 mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
1004 sizeof(CK_BBOOL)); attrs++;
1005 PK11_SETATTRS(attrs, CKA_WRAP,
1006 mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
1007 sizeof(CK_BBOOL)); attrs++;
1008 PK11_SETATTRS(attrs, CKA_VERIFY,
1009 mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
1010 sizeof(CK_BBOOL)); attrs++;
1011 PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER,
1012 mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
1013 sizeof(CK_BBOOL)); attrs++;
1014 PK11_SETATTRS(attrs, CKA_ENCRYPT,
1015 mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,
1016 sizeof(CK_BBOOL)); attrs++;
1017 /* set the private key attributes */
1018 PK11_SETATTRS(privattrs, CKA_DERIVE,
1019 mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
1020 sizeof(CK_BBOOL)); privattrs++;
1021 PK11_SETATTRS(privattrs, CKA_UNWRAP,
1022 mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
1023 sizeof(CK_BBOOL)); privattrs++;
1024 PK11_SETATTRS(privattrs, CKA_SIGN,
1025 mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
1026 sizeof(CK_BBOOL)); privattrs++;
1027 PK11_SETATTRS(privattrs, CKA_DECRYPT,
1028 mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
1029 sizeof(CK_BBOOL)); privattrs++;
1031 if (token) {
1032 session_handle = PK11_GetRWSession(slot);
1033 haslock = PK11_RWSessionHasLock(slot,session_handle);
1034 restore = PR_TRUE;
1035 } else {
1036 session_handle = slot->session;
1037 if (session_handle != CK_INVALID_SESSION)
1038 PK11_EnterSlotMonitor(slot);
1039 restore = PR_FALSE;
1040 haslock = PR_TRUE;
1043 if (session_handle == CK_INVALID_SESSION) {
1044 PORT_SetError(SEC_ERROR_BAD_DATA);
1045 return NULL;
1047 privCount = privattrs - privTemplate;
1048 pubCount = attrs - pubTemplate;
1049 crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
1050 pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);
1052 if (crv != CKR_OK) {
1053 if (restore) {
1054 PK11_RestoreROSession(slot,session_handle);
1055 } else PK11_ExitSlotMonitor(slot);
1056 PORT_SetError( PK11_MapError(crv) );
1057 return NULL;
1059 /* This locking code is dangerous and needs to be more thought
1060 * out... the real problem is that we're holding the mutex open this long
1062 if (haslock) { PK11_ExitSlotMonitor(slot); }
1064 /* swap around the ID's for older PKCS #11 modules */
1065 keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);
1066 if (keyClass != CKO_PUBLIC_KEY) {
1067 CK_OBJECT_HANDLE tmp = pubID;
1068 pubID = privID;
1069 privID = tmp;
1072 *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
1073 if (*pubKey == NULL) {
1074 if (restore) {
1075 /* we may have to restore the mutex so it get's exited properly
1076 * in RestoreROSession */
1077 if (haslock) PK11_EnterSlotMonitor(slot);
1078 PK11_RestoreROSession(slot,session_handle);
1080 PK11_DestroyObject(slot,pubID);
1081 PK11_DestroyObject(slot,privID);
1082 return NULL;
1085 /* set the ID to the public key so we can find it again */
1086 pubKeyIndex = NULL;
1087 switch (type) {
1088 case CKM_RSA_PKCS_KEY_PAIR_GEN:
1089 case CKM_RSA_X9_31_KEY_PAIR_GEN:
1090 pubKeyIndex = &(*pubKey)->u.rsa.modulus;
1091 break;
1092 case CKM_DSA_KEY_PAIR_GEN:
1093 pubKeyIndex = &(*pubKey)->u.dsa.publicValue;
1094 break;
1095 case CKM_DH_PKCS_KEY_PAIR_GEN:
1096 pubKeyIndex = &(*pubKey)->u.dh.publicValue;
1097 break;
1098 case CKM_EC_KEY_PAIR_GEN:
1099 pubKeyIndex = &(*pubKey)->u.ec.publicValue;
1100 break;
1102 PORT_Assert(pubKeyIndex != NULL);
1104 cka_id = PK11_MakeIDFromPubKey(pubKeyIndex);
1105 pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);
1107 PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
1109 if (haslock) { PK11_EnterSlotMonitor(slot); }
1110 crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
1111 &setTemplate, 1);
1113 if (crv == CKR_OK && pubIsToken) {
1114 crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
1115 &setTemplate, 1);
1119 if (restore) {
1120 PK11_RestoreROSession(slot,session_handle);
1121 } else {
1122 PK11_ExitSlotMonitor(slot);
1124 SECITEM_FreeItem(cka_id,PR_TRUE);
1127 if (crv != CKR_OK) {
1128 PK11_DestroyObject(slot,pubID);
1129 PK11_DestroyObject(slot,privID);
1130 PORT_SetError( PK11_MapError(crv) );
1131 *pubKey = NULL;
1132 return NULL;
1135 privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx);
1136 if (privKey == NULL) {
1137 SECKEY_DestroyPublicKey(*pubKey);
1138 PK11_DestroyObject(slot,privID);
1139 *pubKey = NULL;
1140 return NULL;
1143 return privKey;
1146 SECKEYPrivateKey *
1147 PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
1148 void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
1150 return PK11_GenerateKeyPairWithOpFlags(slot,type,param,pubKey,attrFlags,
1151 0, 0, wincx);
1155 * Use the token to generate a key pair.
1157 SECKEYPrivateKey *
1158 PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
1159 void *param, SECKEYPublicKey **pubKey, PRBool token,
1160 PRBool sensitive, void *wincx)
1162 PK11AttrFlags attrFlags = 0;
1164 if (token) {
1165 attrFlags |= PK11_ATTR_TOKEN;
1166 } else {
1167 attrFlags |= PK11_ATTR_SESSION;
1169 if (sensitive) {
1170 attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE);
1171 } else {
1172 attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC);
1174 return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey,
1175 attrFlags, wincx);
1178 /* build a public KEA key from the public value */
1179 SECKEYPublicKey *
1180 PK11_MakeKEAPubKey(unsigned char *keyData,int length)
1182 SECKEYPublicKey *pubk;
1183 SECItem pkData;
1184 SECStatus rv;
1185 PRArenaPool *arena;
1187 pkData.data = keyData;
1188 pkData.len = length;
1190 arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1191 if (arena == NULL)
1192 return NULL;
1194 pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
1195 if (pubk == NULL) {
1196 PORT_FreeArena (arena, PR_FALSE);
1197 return NULL;
1200 pubk->arena = arena;
1201 pubk->pkcs11Slot = 0;
1202 pubk->pkcs11ID = CK_INVALID_HANDLE;
1203 pubk->keyType = fortezzaKey;
1204 rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
1205 if (rv != SECSuccess) {
1206 PORT_FreeArena (arena, PR_FALSE);
1207 return NULL;
1209 return pubk;
1212 SECStatus
1213 PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
1214 SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
1215 SECItem *nickname, SECItem *publicValue, PRBool isPerm,
1216 PRBool isPrivate, KeyType keyType,
1217 unsigned int keyUsage, void *wincx)
1219 CK_MECHANISM_TYPE mechanism;
1220 SECItem *pbe_param, crypto_param;
1221 PK11SymKey *key = NULL;
1222 SECStatus rv = SECSuccess;
1223 CK_MECHANISM cryptoMech, pbeMech;
1224 CK_RV crv;
1225 SECKEYPrivateKey *privKey = NULL;
1226 PRBool faulty3DES = PR_FALSE;
1227 int usageCount = 0;
1228 CK_KEY_TYPE key_type;
1229 CK_ATTRIBUTE_TYPE *usage = NULL;
1230 CK_ATTRIBUTE_TYPE rsaUsage[] = {
1231 CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
1232 CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
1233 CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
1234 CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE };
1235 if((epki == NULL) || (pwitem == NULL))
1236 return SECFailure;
1238 crypto_param.data = NULL;
1240 mechanism = PK11_AlgtagToMechanism(SECOID_FindOIDTag(
1241 &epki->algorithm.algorithm));
1243 switch (keyType) {
1244 default:
1245 case rsaKey:
1246 key_type = CKK_RSA;
1247 switch (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
1248 case KU_KEY_ENCIPHERMENT:
1249 usage = rsaUsage;
1250 usageCount = 2;
1251 break;
1252 case KU_DIGITAL_SIGNATURE:
1253 usage = &rsaUsage[2];
1254 usageCount = 2;
1255 break;
1256 case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
1257 case 0: /* default to everything */
1258 usage = rsaUsage;
1259 usageCount = 4;
1260 break;
1262 break;
1263 case dhKey:
1264 key_type = CKK_DH;
1265 usage = dhUsage;
1266 usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
1267 break;
1268 case dsaKey:
1269 key_type = CKK_DSA;
1270 usage = dsaUsage;
1271 usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
1272 break;
1273 case ecKey:
1274 key_type = CKK_EC;
1275 switch (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) {
1276 case KU_DIGITAL_SIGNATURE:
1277 usage = ecUsage;
1278 usageCount = 1;
1279 break;
1280 case KU_KEY_AGREEMENT:
1281 usage = &ecUsage[1];
1282 usageCount = 1;
1283 break;
1284 case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT:
1285 default: /* default to everything */
1286 usage = ecUsage;
1287 usageCount = 2;
1288 break;
1290 break;
1293 try_faulty_3des:
1294 pbe_param = PK11_ParamFromAlgid(&epki->algorithm);
1296 key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem,
1297 faulty3DES, wincx);
1298 if((key == NULL) || (pbe_param == NULL)) {
1299 rv = SECFailure;
1300 goto done;
1303 pbeMech.mechanism = mechanism;
1304 pbeMech.pParameter = pbe_param->data;
1305 pbeMech.ulParameterLen = pbe_param->len;
1307 crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech,
1308 pwitem, faulty3DES);
1309 if(crv != CKR_OK) {
1310 rv = SECFailure;
1311 goto done;
1314 cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
1315 crypto_param.data = (unsigned char*)cryptoMech.pParameter;
1316 crypto_param.len = cryptoMech.ulParameterLen;
1318 PORT_Assert(usage != NULL);
1319 PORT_Assert(usageCount != 0);
1320 privKey = PK11_UnwrapPrivKey(slot, key, cryptoMech.mechanism,
1321 &crypto_param, &epki->encryptedData,
1322 nickname, publicValue, isPerm, isPrivate,
1323 key_type, usage, usageCount, wincx);
1324 if(privKey) {
1325 SECKEY_DestroyPrivateKey(privKey);
1326 privKey = NULL;
1327 rv = SECSuccess;
1328 goto done;
1331 /* if we are unable to import the key and the mechanism is
1332 * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
1333 * the encrypted blob was created with a buggy key generation method
1334 * which is described in the PKCS 12 implementation notes. So we
1335 * need to try importing via that method.
1337 if((mechanism == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) {
1338 /* clean up after ourselves before redoing the key generation. */
1340 PK11_FreeSymKey(key);
1341 key = NULL;
1343 if(pbe_param) {
1344 SECITEM_ZfreeItem(pbe_param, PR_TRUE);
1345 pbe_param = NULL;
1348 if(crypto_param.data) {
1349 SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
1350 crypto_param.data = NULL;
1351 cryptoMech.pParameter = NULL;
1352 crypto_param.len = cryptoMech.ulParameterLen = 0;
1355 faulty3DES = PR_TRUE;
1356 goto try_faulty_3des;
1359 /* key import really did fail */
1360 rv = SECFailure;
1362 done:
1363 if(pbe_param != NULL) {
1364 SECITEM_ZfreeItem(pbe_param, PR_TRUE);
1365 pbe_param = NULL;
1368 if(crypto_param.data != NULL) {
1369 SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
1372 if(key != NULL) {
1373 PK11_FreeSymKey(key);
1376 return rv;
1379 SECKEYPrivateKeyInfo *
1380 PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
1382 return NULL;
1385 SECKEYEncryptedPrivateKeyInfo *
1386 PK11_ExportEncryptedPrivKeyInfo(
1387 PK11SlotInfo *slot, /* optional, encrypt key in this slot */
1388 SECOidTag algTag, /* encrypt key with this algorithm */
1389 SECItem *pwitem, /* password for PBE encryption */
1390 SECKEYPrivateKey *pk, /* encrypt this private key */
1391 int iteration, /* interations for PBE alg */
1392 void *wincx) /* context for password callback ? */
1394 SECKEYEncryptedPrivateKeyInfo *epki = NULL;
1395 PRArenaPool *arena = NULL;
1396 SECAlgorithmID *algid;
1397 SECItem *pbe_param = NULL;
1398 PK11SymKey *key = NULL;
1399 SECKEYPrivateKey *tmpPK = NULL;
1400 SECStatus rv = SECSuccess;
1401 CK_RV crv;
1402 CK_ULONG encBufLen;
1403 CK_MECHANISM_TYPE mechanism;
1404 CK_MECHANISM pbeMech;
1405 CK_MECHANISM cryptoMech;
1406 SECItem crypto_param;
1408 if (!pwitem || !pk) {
1409 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1410 return NULL;
1413 algid = SEC_PKCS5CreateAlgorithmID(algTag, NULL, iteration);
1414 if (algid == NULL) {
1415 return NULL;
1418 crypto_param.data = NULL;
1420 arena = PORT_NewArena(2048);
1421 if (arena)
1422 epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo);
1423 if(epki == NULL) {
1424 rv = SECFailure;
1425 goto loser;
1427 epki->arena = arena;
1429 mechanism = PK11_AlgtagToMechanism(algTag);
1430 pbe_param = PK11_ParamFromAlgid(algid);
1431 if (!pbe_param || mechanism == CKM_INVALID_MECHANISM) {
1432 rv = SECFailure;
1433 goto loser;
1435 pbeMech.mechanism = mechanism;
1436 pbeMech.pParameter = pbe_param->data;
1437 pbeMech.ulParameterLen = pbe_param->len;
1439 /* if we didn't specify a slot, use the slot the private key was in */
1440 if (!slot) {
1441 slot = pk->pkcs11Slot;
1444 /* if we specified a different slot, and the private key slot can do the
1445 * pbe key gen, generate the key in the private key slot so we don't have
1446 * to move it later */
1447 if (slot != pk->pkcs11Slot) {
1448 if (PK11_DoesMechanism(pk->pkcs11Slot,mechanism)) {
1449 slot = pk->pkcs11Slot;
1452 key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem,
1453 PR_FALSE, wincx);
1455 if((key == NULL) || (pbe_param == NULL)) {
1456 rv = SECFailure;
1457 goto loser;
1460 crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech,
1461 pwitem, PR_FALSE);
1462 if(crv != CKR_OK) {
1463 rv = SECFailure;
1464 goto loser;
1466 cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
1467 crypto_param.data = (unsigned char *)cryptoMech.pParameter;
1468 crypto_param.len = cryptoMech.ulParameterLen;
1470 /* If the key isn't in the private key slot, move it */
1471 if (key->slot != pk->pkcs11Slot) {
1472 PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot,
1473 key->type, CKA_WRAP, key);
1474 if (newkey == NULL) {
1475 /* couldn't import the wrapping key, try exporting the
1476 * private key */
1477 tmpPK = pk11_loadPrivKey(key->slot, pk, NULL, PR_FALSE, PR_TRUE);
1478 if (tmpPK == NULL) {
1479 rv = SECFailure;
1480 goto loser;
1482 pk = tmpPK;
1483 } else {
1484 /* free the old key and use the new key */
1485 PK11_FreeSymKey(key);
1486 key = newkey;
1490 /* we are extracting an encrypted privateKey structure.
1491 * which needs to be freed along with the buffer into which it is
1492 * returned. eventually, we should retrieve an encrypted key using
1493 * pkcs8/pkcs5.
1495 encBufLen = 0;
1496 PK11_EnterSlotMonitor(pk->pkcs11Slot);
1497 crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session,
1498 &cryptoMech, key->objectID, pk->pkcs11ID, NULL,
1499 &encBufLen);
1500 PK11_ExitSlotMonitor(pk->pkcs11Slot);
1501 if (crv != CKR_OK) {
1502 rv = SECFailure;
1503 goto loser;
1505 epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen);
1506 if (!epki->encryptedData.data) {
1507 rv = SECFailure;
1508 goto loser;
1510 PK11_EnterSlotMonitor(pk->pkcs11Slot);
1511 crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session,
1512 &cryptoMech, key->objectID, pk->pkcs11ID,
1513 epki->encryptedData.data, &encBufLen);
1514 PK11_ExitSlotMonitor(pk->pkcs11Slot);
1515 epki->encryptedData.len = (unsigned int) encBufLen;
1516 if(crv != CKR_OK) {
1517 rv = SECFailure;
1518 goto loser;
1521 if(!epki->encryptedData.len) {
1522 rv = SECFailure;
1523 goto loser;
1526 rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid);
1528 loser:
1529 if(pbe_param != NULL) {
1530 SECITEM_ZfreeItem(pbe_param, PR_TRUE);
1531 pbe_param = NULL;
1534 if(crypto_param.data != NULL) {
1535 SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
1536 crypto_param.data = NULL;
1539 if(key != NULL) {
1540 PK11_FreeSymKey(key);
1542 if (tmpPK != NULL) {
1543 SECKEY_DestroyPrivateKey(tmpPK);
1545 SECOID_DestroyAlgorithmID(algid, PR_TRUE);
1547 if(rv == SECFailure) {
1548 if(arena != NULL) {
1549 PORT_FreeArena(arena, PR_TRUE);
1551 epki = NULL;
1554 return epki;
1557 SECKEYEncryptedPrivateKeyInfo *
1558 PK11_ExportEncryptedPrivateKeyInfo(
1559 PK11SlotInfo *slot, /* optional, encrypt key in this slot */
1560 SECOidTag algTag, /* encrypt key with this algorithm */
1561 SECItem *pwitem, /* password for PBE encryption */
1562 CERTCertificate *cert, /* wrap priv key for this user cert */
1563 int iteration, /* interations for PBE alg */
1564 void *wincx) /* context for password callback ? */
1566 SECKEYEncryptedPrivateKeyInfo *epki = NULL;
1567 SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, wincx);
1568 if (pk != NULL) {
1569 epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk,
1570 iteration, wincx);
1571 SECKEY_DestroyPrivateKey(pk);
1573 return epki;
1576 SECItem*
1577 PK11_DEREncodePublicKey(SECKEYPublicKey *pubk)
1579 CERTSubjectPublicKeyInfo *spki=NULL;
1580 SECItem *spkiDER = NULL;
1582 if( pubk == NULL ) {
1583 return NULL;
1586 /* get the subjectpublickeyinfo */
1587 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
1588 if( spki == NULL ) {
1589 goto finish;
1592 /* DER-encode the subjectpublickeyinfo */
1593 spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
1594 CERT_SubjectPublicKeyInfoTemplate);
1596 finish:
1597 return spkiDER;
1600 char *
1601 PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey)
1603 return PK11_GetObjectNickname(privKey->pkcs11Slot,privKey->pkcs11ID);
1606 char *
1607 PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey)
1609 return PK11_GetObjectNickname(pubKey->pkcs11Slot,pubKey->pkcs11ID);
1612 SECStatus
1613 PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname)
1615 return PK11_SetObjectNickname(privKey->pkcs11Slot,
1616 privKey->pkcs11ID,nickname);
1619 SECStatus
1620 PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname)
1622 return PK11_SetObjectNickname(pubKey->pkcs11Slot,
1623 pubKey->pkcs11ID,nickname);
1626 SECKEYPQGParams *
1627 PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey)
1629 CK_ATTRIBUTE pTemplate[] = {
1630 { CKA_PRIME, NULL, 0 },
1631 { CKA_SUBPRIME, NULL, 0 },
1632 { CKA_BASE, NULL, 0 },
1634 int pTemplateLen = sizeof(pTemplate)/sizeof(pTemplate[0]);
1635 PRArenaPool *arena = NULL;
1636 SECKEYPQGParams *params;
1637 CK_RV crv;
1640 arena = PORT_NewArena(2048);
1641 if (arena == NULL) {
1642 goto loser;
1644 params=(SECKEYPQGParams *)PORT_ArenaZAlloc(arena,sizeof(SECKEYPQGParams));
1645 if (params == NULL) {
1646 goto loser;
1649 crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
1650 pTemplate, pTemplateLen);
1651 if (crv != CKR_OK) {
1652 PORT_SetError( PK11_MapError(crv) );
1653 goto loser;
1656 params->arena = arena;
1657 params->prime.data = pTemplate[0].pValue;
1658 params->prime.len = pTemplate[0].ulValueLen;
1659 params->subPrime.data = pTemplate[1].pValue;
1660 params->subPrime.len = pTemplate[1].ulValueLen;
1661 params->base.data = pTemplate[2].pValue;
1662 params->base.len = pTemplate[2].ulValueLen;
1664 return params;
1666 loser:
1667 if (arena != NULL) {
1668 PORT_FreeArena(arena,PR_FALSE);
1670 return NULL;
1673 SECKEYPrivateKey*
1674 PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
1675 SECKEYPrivateKey *privKey)
1677 CK_RV crv;
1678 CK_OBJECT_HANDLE newKeyID;
1680 static const CK_BBOOL ckfalse = CK_FALSE;
1681 static const CK_ATTRIBUTE template[1] = {
1682 { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse }
1685 if (destSlot && destSlot != privKey->pkcs11Slot) {
1686 SECKEYPrivateKey *newKey =
1687 pk11_loadPrivKey(destSlot,
1688 privKey,
1689 NULL, /* pubKey */
1690 PR_FALSE, /* token */
1691 PR_FALSE);/* sensitive */
1692 if (newKey)
1693 return newKey;
1695 destSlot = privKey->pkcs11Slot;
1696 PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx);
1697 PK11_EnterSlotMonitor(destSlot);
1698 crv = PK11_GETTAB(destSlot)->C_CopyObject( destSlot->session,
1699 privKey->pkcs11ID,
1700 (CK_ATTRIBUTE *)template,
1701 1, &newKeyID);
1702 PK11_ExitSlotMonitor(destSlot);
1704 if (crv != CKR_OK) {
1705 PORT_SetError( PK11_MapError(crv) );
1706 return NULL;
1709 return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/,
1710 newKeyID, privKey->wincx);
1713 SECKEYPrivateKey*
1714 PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx)
1716 PK11SlotInfo* slot = privk->pkcs11Slot;
1717 CK_ATTRIBUTE template[1];
1718 CK_ATTRIBUTE *attrs = template;
1719 CK_BBOOL cktrue = CK_TRUE;
1720 CK_RV crv;
1721 CK_OBJECT_HANDLE newKeyID;
1722 CK_SESSION_HANDLE rwsession;
1724 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
1726 PK11_Authenticate(slot, PR_TRUE, wincx);
1727 rwsession = PK11_GetRWSession(slot);
1728 if (rwsession == CK_INVALID_SESSION) {
1729 PORT_SetError(SEC_ERROR_BAD_DATA);
1730 return NULL;
1732 crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID,
1733 template, 1, &newKeyID);
1734 PK11_RestoreROSession(slot, rwsession);
1736 if (crv != CKR_OK) {
1737 PORT_SetError( PK11_MapError(crv) );
1738 return NULL;
1741 return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
1742 newKeyID, NULL /*wincx*/);
1746 * destroy a private key if there are no matching certs.
1747 * this function also frees the privKey structure.
1749 SECStatus
1750 PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force)
1752 CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);
1753 SECStatus rv = SECWouldBlock;
1755 if (!cert || force) {
1756 /* now, then it's safe for the key to go away */
1757 rv = PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);
1759 if (cert) {
1760 CERT_DestroyCertificate(cert);
1762 SECKEY_DestroyPrivateKey(privKey);
1763 return rv;
1767 * destroy a private key if there are no matching certs.
1768 * this function also frees the privKey structure.
1770 SECStatus
1771 PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey)
1773 /* now, then it's safe for the key to go away */
1774 if (pubKey->pkcs11Slot == NULL) {
1775 return SECFailure;
1777 PK11_DestroyTokenObject(pubKey->pkcs11Slot,pubKey->pkcs11ID);
1778 SECKEY_DestroyPublicKey(pubKey);
1779 return SECSuccess;
1783 * key call back structure.
1785 typedef struct pk11KeyCallbackStr {
1786 SECStatus (* callback)(SECKEYPrivateKey *,void *);
1787 void *callbackArg;
1788 void *wincx;
1789 } pk11KeyCallback;
1792 * callback to map Object Handles to Private Keys;
1794 SECStatus
1795 pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
1797 SECStatus rv = SECSuccess;
1798 SECKEYPrivateKey *privKey;
1799 pk11KeyCallback *keycb = (pk11KeyCallback *) arg;
1800 if (!arg) {
1801 return SECFailure;
1804 privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);
1806 if (privKey == NULL) {
1807 return SECFailure;
1810 if (keycb->callback) {
1811 rv = (*keycb->callback)(privKey,keycb->callbackArg);
1814 SECKEY_DestroyPrivateKey(privKey);
1815 return rv;
1818 /***********************************************************************
1819 * PK11_TraversePrivateKeysInSlot
1821 * Traverses all the private keys on a slot.
1823 * INPUTS
1824 * slot
1825 * The PKCS #11 slot whose private keys you want to traverse.
1826 * callback
1827 * A callback function that will be called for each key.
1828 * arg
1829 * An argument that will be passed to the callback function.
1831 SECStatus
1832 PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot,
1833 SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg)
1835 pk11KeyCallback perKeyCB;
1836 pk11TraverseSlot perObjectCB;
1837 CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY;
1838 CK_BBOOL ckTrue = CK_TRUE;
1839 CK_ATTRIBUTE theTemplate[2];
1840 int templateSize = 2;
1842 theTemplate[0].type = CKA_CLASS;
1843 theTemplate[0].pValue = &privkClass;
1844 theTemplate[0].ulValueLen = sizeof(privkClass);
1845 theTemplate[1].type = CKA_TOKEN;
1846 theTemplate[1].pValue = &ckTrue;
1847 theTemplate[1].ulValueLen = sizeof(ckTrue);
1849 if(slot==NULL) {
1850 return SECSuccess;
1853 perObjectCB.callback = pk11_DoKeys;
1854 perObjectCB.callbackArg = &perKeyCB;
1855 perObjectCB.findTemplate = theTemplate;
1856 perObjectCB.templateCount = templateSize;
1857 perKeyCB.callback = callback;
1858 perKeyCB.callbackArg = arg;
1859 perKeyCB.wincx = NULL;
1861 return PK11_TraverseSlot(slot, &perObjectCB);
1865 * return the private key with the given ID
1867 CK_OBJECT_HANDLE
1868 pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)
1870 CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
1871 CK_ATTRIBUTE theTemplate[] = {
1872 { CKA_ID, NULL, 0 },
1873 { CKA_CLASS, NULL, 0 },
1875 /* if you change the array, change the variable below as well */
1876 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
1877 CK_ATTRIBUTE *attrs = theTemplate;
1879 PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++;
1880 PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
1882 return pk11_FindObjectByTemplate(slot,theTemplate,tsize);
1886 SECKEYPrivateKey *
1887 PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
1889 CK_OBJECT_HANDLE keyHandle;
1890 SECKEYPrivateKey *privKey;
1892 keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
1893 if (keyHandle == CK_INVALID_HANDLE) {
1894 return NULL;
1896 privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
1897 return privKey;
1901 * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
1902 * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
1903 * smart cards happy.
1905 SECItem *
1906 PK11_MakeIDFromPubKey(SECItem *pubKeyData)
1908 PK11Context *context;
1909 SECItem *certCKA_ID;
1910 SECStatus rv;
1912 context = PK11_CreateDigestContext(SEC_OID_SHA1);
1913 if (context == NULL) {
1914 return NULL;
1917 rv = PK11_DigestBegin(context);
1918 if (rv == SECSuccess) {
1919 rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len);
1921 if (rv != SECSuccess) {
1922 PK11_DestroyContext(context,PR_TRUE);
1923 return NULL;
1926 certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
1927 if (certCKA_ID == NULL) {
1928 PK11_DestroyContext(context,PR_TRUE);
1929 return NULL;
1932 certCKA_ID->len = SHA1_LENGTH;
1933 certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len);
1934 if (certCKA_ID->data == NULL) {
1935 PORT_Free(certCKA_ID);
1936 PK11_DestroyContext(context,PR_TRUE);
1937 return NULL;
1940 rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len,
1941 SHA1_LENGTH);
1942 PK11_DestroyContext(context,PR_TRUE);
1943 if (rv != SECSuccess) {
1944 SECITEM_FreeItem(certCKA_ID,PR_TRUE);
1945 return NULL;
1948 return certCKA_ID;
1951 SECItem *
1952 PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx)
1954 CK_ATTRIBUTE theTemplate[] = {
1955 { CKA_ID, NULL, 0 },
1957 int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
1958 SECItem *item = NULL;
1959 CK_RV crv;
1961 crv = PK11_GetAttributes(NULL,key->pkcs11Slot,key->pkcs11ID,
1962 theTemplate,tsize);
1963 if (crv != CKR_OK) {
1964 PORT_SetError( PK11_MapError(crv) );
1965 goto loser;
1968 item = PORT_ZNew(SECItem);
1969 if (item) {
1970 item->data = (unsigned char*) theTemplate[0].pValue;
1971 item->len = theTemplate[0].ulValueLen;
1974 loser:
1975 return item;
1978 SECItem *
1979 PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey)
1981 return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID);
1984 static SECStatus
1985 privateKeyListCallback(SECKEYPrivateKey *key, void *arg)
1987 SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList*)arg;
1988 return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key));
1991 SECKEYPrivateKeyList*
1992 PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot)
1994 SECStatus status;
1995 SECKEYPrivateKeyList *keys;
1997 keys = SECKEY_NewPrivateKeyList();
1998 if(keys == NULL) return NULL;
2000 status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback,
2001 (void*)keys);
2003 if( status != SECSuccess ) {
2004 SECKEY_DestroyPrivateKeyList(keys);
2005 keys = NULL;
2008 return keys;
2011 SECKEYPublicKeyList*
2012 PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname)
2014 CK_ATTRIBUTE findTemp[4];
2015 CK_ATTRIBUTE *attrs;
2016 CK_BBOOL ckTrue = CK_TRUE;
2017 CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY;
2018 int tsize = 0;
2019 int objCount = 0;
2020 CK_OBJECT_HANDLE *key_ids;
2021 SECKEYPublicKeyList *keys;
2022 int i,len;
2025 attrs = findTemp;
2026 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
2027 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
2028 if (nickname) {
2029 len = PORT_Strlen(nickname);
2030 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
2032 tsize = attrs - findTemp;
2033 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
2035 key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
2036 if (key_ids == NULL) {
2037 return NULL;
2039 keys = SECKEY_NewPublicKeyList();
2040 if (keys == NULL) {
2041 PORT_Free(key_ids);
2042 return NULL;
2045 for (i=0; i < objCount ; i++) {
2046 SECKEYPublicKey *pubKey =
2047 PK11_ExtractPublicKey(slot,nullKey,key_ids[i]);
2048 if (pubKey) {
2049 SECKEY_AddPublicKeyToListTail(keys, pubKey);
2053 PORT_Free(key_ids);
2054 return keys;
2057 SECKEYPrivateKeyList*
2058 PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
2060 CK_ATTRIBUTE findTemp[4];
2061 CK_ATTRIBUTE *attrs;
2062 CK_BBOOL ckTrue = CK_TRUE;
2063 CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
2064 int tsize = 0;
2065 int objCount = 0;
2066 CK_OBJECT_HANDLE *key_ids;
2067 SECKEYPrivateKeyList *keys;
2068 int i,len;
2071 attrs = findTemp;
2072 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
2073 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
2074 if (nickname) {
2075 len = PORT_Strlen(nickname);
2076 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
2078 tsize = attrs - findTemp;
2079 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
2081 key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
2082 if (key_ids == NULL) {
2083 return NULL;
2085 keys = SECKEY_NewPrivateKeyList();
2086 if (keys == NULL) {
2087 PORT_Free(key_ids);
2088 return NULL;
2091 for (i=0; i < objCount ; i++) {
2092 SECKEYPrivateKey *privKey =
2093 PK11_MakePrivKey(slot,nullKey,PR_TRUE,key_ids[i],wincx);
2094 SECKEY_AddPrivateKeyToListTail(keys, privKey);
2097 PORT_Free(key_ids);
2098 return keys;