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
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.
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
63
* import a public key into the desired slot
66
PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
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;
78
int templateCount = 0;
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,
92
PK11_ExitSlotMonitor(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) {
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++;
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++;
119
PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));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++;
132
PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));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++;
146
PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));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++;
157
PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
158
PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));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++;
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);
191
* take an attribute and copy it into a secitem
194
pk11_Attr2SecItem(PRArenaPool *arena, CK_ATTRIBUTE *attr, SECItem *item)
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);
207
* extract a public key from a slot and id
210
PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id)
212
CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
214
PRArenaPool *tmp_arena;
215
SECKEYPublicKey *pubKey;
216
int templateCount = 0;
217
CK_KEY_TYPE pk11KeyType;
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) {
231
switch (pk11KeyType) {
245
PORT_SetError( SEC_ERROR_BAD_KEY );
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);
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);
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) {
280
PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); 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;
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;
300
PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++;
302
PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++;
304
PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); 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;
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;
327
PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++;
329
PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); 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;
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;
349
pubKey->u.ec.size = 0;
351
PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0); 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;
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;
373
crv = CKR_OBJECT_HANDLE_INVALID;
377
PORT_FreeArena(tmp_arena,PR_FALSE);
380
PORT_FreeArena(arena,PR_FALSE);
382
PORT_SetError( PK11_MapError(crv) );
390
* Build a Private Key structure from raw PKCS #11 information.
393
PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
394
PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
397
SECKEYPrivateKey *privKey;
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);
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;
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);
422
rv = PK11_Authenticate(slot, PR_TRUE, wincx);
423
if (rv != SECSuccess) {
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);
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;
451
PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
453
PK11SlotInfo *slot = key->pkcs11Slot;
454
slot = PK11_ReferenceSlot(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;
469
switch (key->keyType) {
471
crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1);
473
PORT_SetError( PK11_MapError(crv) );
476
length = theTemplate.ulValueLen;
477
if ( *(unsigned char *)theTemplate.pValue == 0) {
480
if (theTemplate.pValue != NULL)
481
PORT_Free(theTemplate.pValue);
490
if (theTemplate.pValue != NULL)
491
PORT_Free(theTemplate.pValue);
492
PORT_SetError( SEC_ERROR_INVALID_KEY );
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 },
514
{ CKA_LABEL, NULL, 0 },
515
{ CKA_SUBJECT, NULL, 0 },
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]);
540
CK_OBJECT_HANDLE objectID;
545
PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
547
if (pk11_BadAttrFlags(attrFlags)) {
548
PORT_SetError(SEC_ERROR_INVALID_ARGS);
552
for (i=0; i < templateSize; i++) {
553
if (privTemplate[i].type == CKA_MODULUS) {
554
attrs= &privTemplate[i];
559
PORT_Assert(attrs != NULL);
561
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
567
switch (privKey->keyType) {
569
count = templateSize - NUM_RESERVED_ATTRS;
570
extra_count = count - (attrs - privTemplate);
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++;
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++;
584
ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++;
585
ap->type = CKA_VALUE; ap++; count++; extra_count++;
594
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
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,
606
PORT_SetError( PK11_MapError(crv) );
607
PORT_FreeArena(arena, PR_TRUE);
611
/* Set token, private, modifiable, sensitive, and extractable */
612
count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
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) {
629
/* try loading the public key */
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;
650
attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
652
attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC);
655
attrFlags |= PK11_ATTR_SENSITIVE;
657
attrFlags |= PK11_ATTR_INSENSITIVE;
659
return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags);
663
* export this for PSM
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.
677
PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
678
void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
680
/* we have to use these native types because when we call PKCS 11 modules
681
* we have to make sure that we are using the correct sizes for all the
683
CK_BBOOL ckfalse = CK_FALSE;
684
CK_BBOOL cktrue = CK_TRUE;
685
CK_ULONG modulusBits;
686
CK_BYTE publicExponent[4];
687
CK_ATTRIBUTE privTemplate[] = {
688
{ CKA_SENSITIVE, NULL, 0},
689
{ CKA_TOKEN, NULL, 0},
690
{ CKA_PRIVATE, NULL, 0},
691
{ CKA_DERIVE, NULL, 0},
692
{ CKA_UNWRAP, NULL, 0},
693
{ CKA_SIGN, NULL, 0},
694
{ CKA_DECRYPT, NULL, 0},
695
{ CKA_EXTRACTABLE, NULL, 0},
696
{ CKA_MODIFIABLE, NULL, 0},
698
CK_ATTRIBUTE rsaPubTemplate[] = {
699
{ CKA_MODULUS_BITS, NULL, 0},
700
{ CKA_PUBLIC_EXPONENT, NULL, 0},
701
{ CKA_TOKEN, NULL, 0},
702
{ CKA_DERIVE, NULL, 0},
703
{ CKA_WRAP, NULL, 0},
704
{ CKA_VERIFY, NULL, 0},
705
{ CKA_VERIFY_RECOVER, NULL, 0},
706
{ CKA_ENCRYPT, NULL, 0},
707
{ CKA_MODIFIABLE, NULL, 0},
709
CK_ATTRIBUTE dsaPubTemplate[] = {
710
{ CKA_PRIME, NULL, 0 },
711
{ CKA_SUBPRIME, NULL, 0 },
712
{ CKA_BASE, NULL, 0 },
713
{ CKA_TOKEN, NULL, 0},
714
{ CKA_DERIVE, NULL, 0},
715
{ CKA_WRAP, NULL, 0},
716
{ CKA_VERIFY, NULL, 0},
717
{ CKA_VERIFY_RECOVER, NULL, 0},
718
{ CKA_ENCRYPT, NULL, 0},
719
{ CKA_MODIFIABLE, NULL, 0},
721
CK_ATTRIBUTE dhPubTemplate[] = {
722
{ CKA_PRIME, NULL, 0 },
723
{ CKA_BASE, NULL, 0 },
724
{ CKA_TOKEN, NULL, 0},
725
{ CKA_DERIVE, NULL, 0},
726
{ CKA_WRAP, NULL, 0},
727
{ CKA_VERIFY, NULL, 0},
728
{ CKA_VERIFY_RECOVER, NULL, 0},
729
{ CKA_ENCRYPT, NULL, 0},
730
{ CKA_MODIFIABLE, NULL, 0},
732
CK_ATTRIBUTE ecPubTemplate[] = {
733
{ CKA_EC_PARAMS, NULL, 0 },
734
{ CKA_TOKEN, NULL, 0},
735
{ CKA_DERIVE, NULL, 0},
736
{ CKA_WRAP, NULL, 0},
737
{ CKA_VERIFY, NULL, 0},
738
{ CKA_VERIFY_RECOVER, NULL, 0},
739
{ CKA_ENCRYPT, NULL, 0},
740
{ CKA_MODIFIABLE, NULL, 0},
742
SECKEYECParams * ecParams;
744
/*CK_ULONG key_size = 0;*/
745
CK_ATTRIBUTE *pubTemplate;
748
PK11RSAGenParams *rsaParams;
749
SECKEYPQGParams *dsaParams;
750
SECKEYDHParams * dhParams;
751
CK_MECHANISM mechanism;
752
CK_MECHANISM test_mech;
753
CK_SESSION_HANDLE session_handle;
755
CK_OBJECT_HANDLE privID,pubID;
756
SECKEYPrivateKey *privKey;
761
CK_ATTRIBUTE *privattrs;
762
SECItem *pubKeyIndex;
763
CK_ATTRIBUTE setTemplate;
764
CK_MECHANISM_INFO mechanism_info;
765
CK_OBJECT_CLASS keyClass;
767
PRBool haslock = PR_FALSE;
768
PRBool pubIsToken = PR_FALSE;
769
PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
770
/* subset of attrFlags applicable to the public key */
771
PK11AttrFlags pubKeyAttrFlags = attrFlags &
772
(PK11_ATTR_TOKEN | PK11_ATTR_SESSION
773
| PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
775
if (pk11_BadAttrFlags(attrFlags)) {
776
PORT_SetError( SEC_ERROR_INVALID_ARGS );
780
PORT_Assert(slot != NULL);
782
PORT_SetError( SEC_ERROR_NO_MODULE);
786
/* if our slot really doesn't do this mechanism, Generate the key
787
* in our internal token and write it out */
788
if (!PK11_DoesMechanism(slot,type)) {
789
PK11SlotInfo *int_slot = PK11_GetInternalSlot();
791
/* don't loop forever looking for a slot */
792
if (slot == int_slot) {
793
PK11_FreeSlot(int_slot);
794
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
798
/* if there isn't a suitable slot, then we can't do the keygen */
799
if (int_slot == NULL) {
800
PORT_SetError( SEC_ERROR_NO_MODULE );
804
/* generate the temporary key to load */
805
privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE,
807
PK11_FreeSlot(int_slot);
809
/* if successful, load the temp key into the new token */
810
if (privKey != NULL) {
811
SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
812
privKey,*pubKey,attrFlags);
813
SECKEY_DestroyPrivateKey(privKey);
814
if (newPrivKey == NULL) {
815
SECKEY_DestroyPublicKey(*pubKey);
824
mechanism.mechanism = type;
825
mechanism.pParameter = NULL;
826
mechanism.ulParameterLen = 0;
827
test_mech.pParameter = NULL;
828
test_mech.ulParameterLen = 0;
830
/* set up the private key template */
831
privattrs = privTemplate;
832
privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
835
/* set up the mechanism specific info */
837
case CKM_RSA_PKCS_KEY_PAIR_GEN:
838
case CKM_RSA_X9_31_KEY_PAIR_GEN:
839
rsaParams = (PK11RSAGenParams *)param;
840
if (rsaParams->pe == 0) {
841
PORT_SetError(SEC_ERROR_INVALID_ARGS);
844
modulusBits = rsaParams->keySizeInBits;
847
/* convert pe to a PKCS #11 string */
848
for (i=0; i < 4; i++) {
849
if (peCount || (rsaParams->pe &
850
((unsigned long)0xff000000L >> (i*8)))) {
851
publicExponent[peCount] =
852
(CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);
856
PORT_Assert(peCount != 0);
857
attrs = rsaPubTemplate;
858
PK11_SETATTRS(attrs, CKA_MODULUS_BITS,
859
&modulusBits, sizeof(modulusBits)); attrs++;
860
PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
861
publicExponent, peCount);attrs++;
862
pubTemplate = rsaPubTemplate;
864
test_mech.mechanism = CKM_RSA_PKCS;
866
case CKM_DSA_KEY_PAIR_GEN:
867
dsaParams = (SECKEYPQGParams *)param;
868
attrs = dsaPubTemplate;
869
PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
870
dsaParams->prime.len); attrs++;
871
PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
872
dsaParams->subPrime.len); attrs++;
873
PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
874
dsaParams->base.len); attrs++;
875
pubTemplate = dsaPubTemplate;
877
test_mech.mechanism = CKM_DSA;
879
case CKM_DH_PKCS_KEY_PAIR_GEN:
880
dhParams = (SECKEYDHParams *)param;
881
attrs = dhPubTemplate;
882
PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
883
dhParams->prime.len); attrs++;
884
PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
885
dhParams->base.len); attrs++;
886
pubTemplate = dhPubTemplate;
888
test_mech.mechanism = CKM_DH_PKCS_DERIVE;
890
case CKM_EC_KEY_PAIR_GEN:
891
ecParams = (SECKEYECParams *)param;
892
attrs = ecPubTemplate;
893
PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data,
894
ecParams->len); attrs++;
895
pubTemplate = ecPubTemplate;
897
/* XXX An EC key can be used for other mechanisms too such
898
* as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect
899
* that in test_mech.mechanism so the CKA_SIGN, CKA_VERIFY
900
* attributes are set correctly?
902
test_mech.mechanism = CKM_ECDH1_DERIVE;
905
PORT_SetError( SEC_ERROR_BAD_KEY );
909
/* now query the slot to find out how "good" a key we can generate */
910
if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
911
crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
912
test_mech.mechanism,&mechanism_info);
913
if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
914
if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
915
/* must be old module... guess what it should be... */
916
switch (test_mech.mechanism) {
918
mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT |
919
CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);;
922
mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
924
case CKM_DH_PKCS_DERIVE:
925
mechanism_info.flags = CKF_DERIVE;
927
case CKM_ECDH1_DERIVE:
928
mechanism_info.flags = CKF_DERIVE;
932
mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
938
/* set the public key attributes */
939
attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
941
PK11_SETATTRS(attrs, CKA_DERIVE,
942
mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
943
sizeof(CK_BBOOL)); attrs++;
944
PK11_SETATTRS(attrs, CKA_WRAP,
945
mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
946
sizeof(CK_BBOOL)); attrs++;
947
PK11_SETATTRS(attrs, CKA_VERIFY,
948
mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
949
sizeof(CK_BBOOL)); attrs++;
950
PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER,
951
mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
952
sizeof(CK_BBOOL)); attrs++;
953
PK11_SETATTRS(attrs, CKA_ENCRYPT,
954
mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,
955
sizeof(CK_BBOOL)); attrs++;
956
/* set the private key attributes */
957
PK11_SETATTRS(privattrs, CKA_DERIVE,
958
mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
959
sizeof(CK_BBOOL)); privattrs++;
960
PK11_SETATTRS(privattrs, CKA_UNWRAP,
961
mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
962
sizeof(CK_BBOOL)); privattrs++;
963
PK11_SETATTRS(privattrs, CKA_SIGN,
964
mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
965
sizeof(CK_BBOOL)); privattrs++;
966
PK11_SETATTRS(privattrs, CKA_DECRYPT,
967
mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
968
sizeof(CK_BBOOL)); privattrs++;
971
session_handle = PK11_GetRWSession(slot);
972
haslock = PK11_RWSessionHasLock(slot,session_handle);
975
session_handle = slot->session;
976
if (session_handle != CK_INVALID_SESSION)
977
PK11_EnterSlotMonitor(slot);
982
if (session_handle == CK_INVALID_SESSION) {
983
PORT_SetError(SEC_ERROR_BAD_DATA);
986
privCount = privattrs - privTemplate;
987
pubCount = attrs - pubTemplate;
988
crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
989
pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);
993
PK11_RestoreROSession(slot,session_handle);
994
} else PK11_ExitSlotMonitor(slot);
995
PORT_SetError( PK11_MapError(crv) );
998
/* This locking code is dangerous and needs to be more thought
999
* out... the real problem is that we're holding the mutex open this long
1001
if (haslock) { PK11_ExitSlotMonitor(slot); }
1003
/* swap around the ID's for older PKCS #11 modules */
1004
keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);
1005
if (keyClass != CKO_PUBLIC_KEY) {
1006
CK_OBJECT_HANDLE tmp = pubID;
1011
*pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
1012
if (*pubKey == NULL) {
1014
/* we may have to restore the mutex so it get's exited properly
1015
* in RestoreROSession */
1016
if (haslock) PK11_EnterSlotMonitor(slot);
1017
PK11_RestoreROSession(slot,session_handle);
1019
PK11_DestroyObject(slot,pubID);
1020
PK11_DestroyObject(slot,privID);
1024
/* set the ID to the public key so we can find it again */
1027
case CKM_RSA_PKCS_KEY_PAIR_GEN:
1028
case CKM_RSA_X9_31_KEY_PAIR_GEN:
1029
pubKeyIndex = &(*pubKey)->u.rsa.modulus;
1031
case CKM_DSA_KEY_PAIR_GEN:
1032
pubKeyIndex = &(*pubKey)->u.dsa.publicValue;
1034
case CKM_DH_PKCS_KEY_PAIR_GEN:
1035
pubKeyIndex = &(*pubKey)->u.dh.publicValue;
1037
case CKM_EC_KEY_PAIR_GEN:
1038
pubKeyIndex = &(*pubKey)->u.ec.publicValue;
1041
PORT_Assert(pubKeyIndex != NULL);
1043
cka_id = PK11_MakeIDFromPubKey(pubKeyIndex);
1044
pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);
1046
PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
1048
if (haslock) { PK11_EnterSlotMonitor(slot); }
1049
crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
1052
if (crv == CKR_OK && pubIsToken) {
1053
crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
1059
PK11_RestoreROSession(slot,session_handle);
1061
PK11_ExitSlotMonitor(slot);
1063
SECITEM_FreeItem(cka_id,PR_TRUE);
1066
if (crv != CKR_OK) {
1067
PK11_DestroyObject(slot,pubID);
1068
PK11_DestroyObject(slot,privID);
1069
PORT_SetError( PK11_MapError(crv) );
1074
privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx);
1075
if (privKey == NULL) {
1076
SECKEY_DestroyPublicKey(*pubKey);
1077
PK11_DestroyObject(slot,privID);
1086
* Use the token to generate a key pair.
1089
PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type,
1090
void *param, SECKEYPublicKey **pubKey, PRBool token,
1091
PRBool sensitive, void *wincx)
1093
PK11AttrFlags attrFlags = 0;
1096
attrFlags |= PK11_ATTR_TOKEN;
1098
attrFlags |= PK11_ATTR_SESSION;
1101
attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE);
1103
attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC);
1105
return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey,
1109
/* build a public KEA key from the public value */
1111
PK11_MakeKEAPubKey(unsigned char *keyData,int length)
1113
SECKEYPublicKey *pubk;
1118
pkData.data = keyData;
1119
pkData.len = length;
1121
arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
1125
pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
1127
PORT_FreeArena (arena, PR_FALSE);
1131
pubk->arena = arena;
1132
pubk->pkcs11Slot = 0;
1133
pubk->pkcs11ID = CK_INVALID_HANDLE;
1134
pubk->keyType = fortezzaKey;
1135
rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
1136
if (rv != SECSuccess) {
1137
PORT_FreeArena (arena, PR_FALSE);
1144
PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
1145
SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
1146
SECItem *nickname, SECItem *publicValue, PRBool isPerm,
1147
PRBool isPrivate, KeyType keyType,
1148
unsigned int keyUsage, void *wincx)
1150
CK_MECHANISM_TYPE mechanism;
1151
SECItem *pbe_param, crypto_param;
1152
PK11SymKey *key = NULL;
1153
SECStatus rv = SECSuccess;
1154
CK_MECHANISM cryptoMech, pbeMech;
1156
SECKEYPrivateKey *privKey = NULL;
1157
PRBool faulty3DES = PR_FALSE;
1159
CK_KEY_TYPE key_type;
1160
CK_ATTRIBUTE_TYPE *usage = NULL;
1161
CK_ATTRIBUTE_TYPE rsaUsage[] = {
1162
CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
1163
CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
1164
CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
1165
CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE };
1166
if((epki == NULL) || (pwitem == NULL))
1169
crypto_param.data = NULL;
1171
mechanism = PK11_AlgtagToMechanism(SECOID_FindOIDTag(
1172
&epki->algorithm.algorithm));
1178
switch (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
1179
case KU_KEY_ENCIPHERMENT:
1183
case KU_DIGITAL_SIGNATURE:
1184
usage = &rsaUsage[2];
1187
case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
1188
case 0: /* default to everything */
1197
usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
1202
usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
1206
switch (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) {
1207
case KU_DIGITAL_SIGNATURE:
1211
case KU_KEY_AGREEMENT:
1212
usage = &ecUsage[1];
1215
case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT:
1216
default: /* default to everything */
1225
pbe_param = PK11_ParamFromAlgid(&epki->algorithm);
1227
key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem,
1229
if((key == NULL) || (pbe_param == NULL)) {
1234
pbeMech.mechanism = mechanism;
1235
pbeMech.pParameter = pbe_param->data;
1236
pbeMech.ulParameterLen = pbe_param->len;
1238
crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech,
1239
pwitem, faulty3DES);
1245
cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
1246
crypto_param.data = (unsigned char*)cryptoMech.pParameter;
1247
crypto_param.len = cryptoMech.ulParameterLen;
1249
PORT_Assert(usage != NULL);
1250
PORT_Assert(usageCount != 0);
1251
privKey = PK11_UnwrapPrivKey(slot, key, cryptoMech.mechanism,
1252
&crypto_param, &epki->encryptedData,
1253
nickname, publicValue, isPerm, isPrivate,
1254
key_type, usage, usageCount, wincx);
1256
SECKEY_DestroyPrivateKey(privKey);
1262
/* if we are unable to import the key and the mechanism is
1263
* CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
1264
* the encrypted blob was created with a buggy key generation method
1265
* which is described in the PKCS 12 implementation notes. So we
1266
* need to try importing via that method.
1268
if((mechanism == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) {
1269
/* clean up after ourselves before redoing the key generation. */
1271
PK11_FreeSymKey(key);
1275
SECITEM_ZfreeItem(pbe_param, PR_TRUE);
1279
if(crypto_param.data) {
1280
SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
1281
crypto_param.data = NULL;
1282
cryptoMech.pParameter = NULL;
1283
crypto_param.len = cryptoMech.ulParameterLen = 0;
1286
faulty3DES = PR_TRUE;
1287
goto try_faulty_3des;
1290
/* key import really did fail */
1294
if(pbe_param != NULL) {
1295
SECITEM_ZfreeItem(pbe_param, PR_TRUE);
1299
if(crypto_param.data != NULL) {
1300
SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
1304
PK11_FreeSymKey(key);
1310
SECKEYPrivateKeyInfo *
1311
PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
1316
SECKEYEncryptedPrivateKeyInfo *
1317
PK11_ExportEncryptedPrivKeyInfo(
1318
PK11SlotInfo *slot, /* optional, encrypt key in this slot */
1319
SECOidTag algTag, /* encrypt key with this algorithm */
1320
SECItem *pwitem, /* password for PBE encryption */
1321
SECKEYPrivateKey *pk, /* encrypt this private key */
1322
int iteration, /* interations for PBE alg */
1323
void *wincx) /* context for password callback ? */
1325
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
1326
PRArenaPool *arena = NULL;
1327
SECAlgorithmID *algid;
1328
SECItem *pbe_param = NULL;
1329
PK11SymKey *key = NULL;
1330
SECStatus rv = SECSuccess;
1333
CK_MECHANISM_TYPE mechanism;
1334
CK_MECHANISM pbeMech;
1335
CK_MECHANISM cryptoMech;
1336
SECItem crypto_param;
1338
if (!pwitem || !pk) {
1339
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1343
algid = SEC_PKCS5CreateAlgorithmID(algTag, NULL, iteration);
1344
if (algid == NULL) {
1348
crypto_param.data = NULL;
1350
arena = PORT_NewArena(2048);
1352
epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo);
1357
epki->arena = arena;
1359
mechanism = PK11_AlgtagToMechanism(algTag);
1360
pbe_param = PK11_ParamFromAlgid(algid);
1361
if (!pbe_param || mechanism == CKM_INVALID_MECHANISM) {
1365
pbeMech.mechanism = mechanism;
1366
pbeMech.pParameter = pbe_param->data;
1367
pbeMech.ulParameterLen = pbe_param->len;
1369
/* if we didn't specify a slot, use the slot the private key was in */
1371
slot = pk->pkcs11Slot;
1374
/* if we specified a different slot, and the private key slot can do the
1375
* pbe key gen, generate the key in the private key slot so we don't have
1376
* to move it later */
1377
if (slot != pk->pkcs11Slot) {
1378
if (PK11_DoesMechanism(pk->pkcs11Slot,mechanism)) {
1379
slot = pk->pkcs11Slot;
1382
key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem,
1385
if((key == NULL) || (pbe_param == NULL)) {
1390
crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech,
1396
cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
1397
crypto_param.data = (unsigned char *)cryptoMech.pParameter;
1398
crypto_param.len = cryptoMech.ulParameterLen;
1400
/* If the key isn't in the private key slot, move it */
1401
if (key->slot != pk->pkcs11Slot) {
1402
PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot,
1403
key->type, CKA_WRAP, key);
1404
if (newkey == NULL) {
1409
/* free the old key and use the new key */
1410
PK11_FreeSymKey(key);
1414
/* we are extracting an encrypted privateKey structure.
1415
* which needs to be freed along with the buffer into which it is
1416
* returned. eventually, we should retrieve an encrypted key using
1420
PK11_EnterSlotMonitor(pk->pkcs11Slot);
1421
crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session,
1422
&cryptoMech, key->objectID, pk->pkcs11ID, NULL,
1424
PK11_ExitSlotMonitor(pk->pkcs11Slot);
1425
if (crv != CKR_OK) {
1429
epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen);
1430
if (!epki->encryptedData.data) {
1434
PK11_EnterSlotMonitor(pk->pkcs11Slot);
1435
crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session,
1436
&cryptoMech, key->objectID, pk->pkcs11ID,
1437
epki->encryptedData.data, &encBufLen);
1438
PK11_ExitSlotMonitor(pk->pkcs11Slot);
1439
epki->encryptedData.len = (unsigned int) encBufLen;
1445
if(!epki->encryptedData.len) {
1450
rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid);
1453
if(pbe_param != NULL) {
1454
SECITEM_ZfreeItem(pbe_param, PR_TRUE);
1458
if(crypto_param.data != NULL) {
1459
SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
1460
crypto_param.data = NULL;
1464
PK11_FreeSymKey(key);
1466
SECOID_DestroyAlgorithmID(algid, PR_TRUE);
1468
if(rv == SECFailure) {
1470
PORT_FreeArena(arena, PR_TRUE);
1478
SECKEYEncryptedPrivateKeyInfo *
1479
PK11_ExportEncryptedPrivateKeyInfo(
1480
PK11SlotInfo *slot, /* optional, encrypt key in this slot */
1481
SECOidTag algTag, /* encrypt key with this algorithm */
1482
SECItem *pwitem, /* password for PBE encryption */
1483
CERTCertificate *cert, /* wrap priv key for this user cert */
1484
int iteration, /* interations for PBE alg */
1485
void *wincx) /* context for password callback ? */
1487
SECKEYEncryptedPrivateKeyInfo *epki = NULL;
1488
SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, wincx);
1490
epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk,
1492
SECKEY_DestroyPrivateKey(pk);
1498
PK11_DEREncodePublicKey(SECKEYPublicKey *pubk)
1500
CERTSubjectPublicKeyInfo *spki=NULL;
1501
SECItem *spkiDER = NULL;
1503
if( pubk == NULL ) {
1507
/* get the subjectpublickeyinfo */
1508
spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
1509
if( spki == NULL ) {
1513
/* DER-encode the subjectpublickeyinfo */
1514
spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
1515
CERT_SubjectPublicKeyInfoTemplate);
1522
PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey)
1524
return PK11_GetObjectNickname(privKey->pkcs11Slot,privKey->pkcs11ID);
1528
PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey)
1530
return PK11_GetObjectNickname(pubKey->pkcs11Slot,pubKey->pkcs11ID);
1534
PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname)
1536
return PK11_SetObjectNickname(privKey->pkcs11Slot,
1537
privKey->pkcs11ID,nickname);
1541
PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname)
1543
return PK11_SetObjectNickname(pubKey->pkcs11Slot,
1544
pubKey->pkcs11ID,nickname);
1548
PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey)
1550
CK_ATTRIBUTE pTemplate[] = {
1551
{ CKA_PRIME, NULL, 0 },
1552
{ CKA_SUBPRIME, NULL, 0 },
1553
{ CKA_BASE, NULL, 0 },
1555
int pTemplateLen = sizeof(pTemplate)/sizeof(pTemplate[0]);
1556
PRArenaPool *arena = NULL;
1557
SECKEYPQGParams *params;
1561
arena = PORT_NewArena(2048);
1562
if (arena == NULL) {
1565
params=(SECKEYPQGParams *)PORT_ArenaZAlloc(arena,sizeof(SECKEYPQGParams));
1566
if (params == NULL) {
1570
crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
1571
pTemplate, pTemplateLen);
1572
if (crv != CKR_OK) {
1573
PORT_SetError( PK11_MapError(crv) );
1577
params->arena = arena;
1578
params->prime.data = pTemplate[0].pValue;
1579
params->prime.len = pTemplate[0].ulValueLen;
1580
params->subPrime.data = pTemplate[1].pValue;
1581
params->subPrime.len = pTemplate[1].ulValueLen;
1582
params->base.data = pTemplate[2].pValue;
1583
params->base.len = pTemplate[2].ulValueLen;
1588
if (arena != NULL) {
1589
PORT_FreeArena(arena,PR_FALSE);
1595
PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
1596
SECKEYPrivateKey *privKey)
1599
CK_OBJECT_HANDLE newKeyID;
1601
static const CK_BBOOL ckfalse = CK_FALSE;
1602
static const CK_ATTRIBUTE template[1] = {
1603
{ CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse }
1606
if (destSlot && destSlot != privKey->pkcs11Slot) {
1607
SECKEYPrivateKey *newKey =
1608
pk11_loadPrivKey(destSlot,
1611
PR_FALSE, /* token */
1612
PR_FALSE);/* sensitive */
1616
destSlot = privKey->pkcs11Slot;
1617
PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx);
1618
PK11_EnterSlotMonitor(destSlot);
1619
crv = PK11_GETTAB(destSlot)->C_CopyObject( destSlot->session,
1621
(CK_ATTRIBUTE *)template,
1623
PK11_ExitSlotMonitor(destSlot);
1625
if (crv != CKR_OK) {
1626
PORT_SetError( PK11_MapError(crv) );
1630
return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/,
1631
newKeyID, privKey->wincx);
1635
PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx)
1637
PK11SlotInfo* slot = privk->pkcs11Slot;
1638
CK_ATTRIBUTE template[1];
1639
CK_ATTRIBUTE *attrs = template;
1640
CK_BBOOL cktrue = CK_TRUE;
1642
CK_OBJECT_HANDLE newKeyID;
1643
CK_SESSION_HANDLE rwsession;
1645
PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
1647
PK11_Authenticate(slot, PR_TRUE, wincx);
1648
rwsession = PK11_GetRWSession(slot);
1649
if (rwsession == CK_INVALID_SESSION) {
1650
PORT_SetError(SEC_ERROR_BAD_DATA);
1653
crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID,
1654
template, 1, &newKeyID);
1655
PK11_RestoreROSession(slot, rwsession);
1657
if (crv != CKR_OK) {
1658
PORT_SetError( PK11_MapError(crv) );
1662
return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
1663
newKeyID, NULL /*wincx*/);
1667
* destroy a private key if there are no matching certs.
1668
* this function also frees the privKey structure.
1671
PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force)
1673
CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);
1675
/* found a cert matching the private key?. */
1676
if (!force && cert != NULL) {
1677
/* yes, don't delete the key */
1678
CERT_DestroyCertificate(cert);
1679
SECKEY_DestroyPrivateKey(privKey);
1680
return SECWouldBlock;
1682
/* now, then it's safe for the key to go away */
1683
PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);
1684
SECKEY_DestroyPrivateKey(privKey);
1689
* destroy a private key if there are no matching certs.
1690
* this function also frees the privKey structure.
1693
PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey)
1695
/* now, then it's safe for the key to go away */
1696
if (pubKey->pkcs11Slot == NULL) {
1699
PK11_DestroyTokenObject(pubKey->pkcs11Slot,pubKey->pkcs11ID);
1700
SECKEY_DestroyPublicKey(pubKey);
1705
* key call back structure.
1707
typedef struct pk11KeyCallbackStr {
1708
SECStatus (* callback)(SECKEYPrivateKey *,void *);
1714
* callback to map Object Handles to Private Keys;
1717
pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
1719
SECStatus rv = SECSuccess;
1720
SECKEYPrivateKey *privKey;
1721
pk11KeyCallback *keycb = (pk11KeyCallback *) arg;
1726
privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);
1728
if (privKey == NULL) {
1732
if (keycb->callback) {
1733
rv = (*keycb->callback)(privKey,keycb->callbackArg);
1736
SECKEY_DestroyPrivateKey(privKey);
1740
/***********************************************************************
1741
* PK11_TraversePrivateKeysInSlot
1743
* Traverses all the private keys on a slot.
1747
* The PKCS #11 slot whose private keys you want to traverse.
1749
* A callback function that will be called for each key.
1751
* An argument that will be passed to the callback function.
1754
PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot,
1755
SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg)
1757
pk11KeyCallback perKeyCB;
1758
pk11TraverseSlot perObjectCB;
1759
CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY;
1760
CK_BBOOL ckTrue = CK_TRUE;
1761
CK_ATTRIBUTE theTemplate[2];
1762
int templateSize = 2;
1764
theTemplate[0].type = CKA_CLASS;
1765
theTemplate[0].pValue = &privkClass;
1766
theTemplate[0].ulValueLen = sizeof(privkClass);
1767
theTemplate[1].type = CKA_TOKEN;
1768
theTemplate[1].pValue = &ckTrue;
1769
theTemplate[1].ulValueLen = sizeof(ckTrue);
1775
perObjectCB.callback = pk11_DoKeys;
1776
perObjectCB.callbackArg = &perKeyCB;
1777
perObjectCB.findTemplate = theTemplate;
1778
perObjectCB.templateCount = templateSize;
1779
perKeyCB.callback = callback;
1780
perKeyCB.callbackArg = arg;
1781
perKeyCB.wincx = NULL;
1783
return PK11_TraverseSlot(slot, &perObjectCB);
1787
* return the private key with the given ID
1790
pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)
1792
CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
1793
CK_ATTRIBUTE theTemplate[] = {
1794
{ CKA_ID, NULL, 0 },
1795
{ CKA_CLASS, NULL, 0 },
1797
/* if you change the array, change the variable below as well */
1798
int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
1799
CK_ATTRIBUTE *attrs = theTemplate;
1801
PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++;
1802
PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
1804
return pk11_FindObjectByTemplate(slot,theTemplate,tsize);
1809
PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
1811
CK_OBJECT_HANDLE keyHandle;
1812
SECKEYPrivateKey *privKey;
1814
keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
1815
if (keyHandle == CK_INVALID_HANDLE) {
1818
privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
1823
* Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
1824
* from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
1825
* smart cards happy.
1828
PK11_MakeIDFromPubKey(SECItem *pubKeyData)
1830
PK11Context *context;
1831
SECItem *certCKA_ID;
1834
context = PK11_CreateDigestContext(SEC_OID_SHA1);
1835
if (context == NULL) {
1839
rv = PK11_DigestBegin(context);
1840
if (rv == SECSuccess) {
1841
rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len);
1843
if (rv != SECSuccess) {
1844
PK11_DestroyContext(context,PR_TRUE);
1848
certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
1849
if (certCKA_ID == NULL) {
1850
PK11_DestroyContext(context,PR_TRUE);
1854
certCKA_ID->len = SHA1_LENGTH;
1855
certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len);
1856
if (certCKA_ID->data == NULL) {
1857
PORT_Free(certCKA_ID);
1858
PK11_DestroyContext(context,PR_TRUE);
1862
rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len,
1864
PK11_DestroyContext(context,PR_TRUE);
1865
if (rv != SECSuccess) {
1866
SECITEM_FreeItem(certCKA_ID,PR_TRUE);
1874
PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx)
1876
CK_ATTRIBUTE theTemplate[] = {
1877
{ CKA_ID, NULL, 0 },
1879
int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
1880
SECItem *item = NULL;
1883
crv = PK11_GetAttributes(NULL,key->pkcs11Slot,key->pkcs11ID,
1885
if (crv != CKR_OK) {
1886
PORT_SetError( PK11_MapError(crv) );
1890
item = PORT_ZNew(SECItem);
1892
item->data = (unsigned char*) theTemplate[0].pValue;
1893
item->len = theTemplate[0].ulValueLen;
1901
PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey)
1903
return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID);
1907
privateKeyListCallback(SECKEYPrivateKey *key, void *arg)
1909
SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList*)arg;
1910
return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key));
1913
SECKEYPrivateKeyList*
1914
PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot)
1917
SECKEYPrivateKeyList *keys;
1919
keys = SECKEY_NewPrivateKeyList();
1920
if(keys == NULL) return NULL;
1922
status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback,
1925
if( status != SECSuccess ) {
1926
SECKEY_DestroyPrivateKeyList(keys);
1933
SECKEYPublicKeyList*
1934
PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname)
1936
CK_ATTRIBUTE findTemp[4];
1937
CK_ATTRIBUTE *attrs;
1938
CK_BBOOL ckTrue = CK_TRUE;
1939
CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY;
1942
CK_OBJECT_HANDLE *key_ids;
1943
SECKEYPublicKeyList *keys;
1948
PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
1949
PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
1951
len = PORT_Strlen(nickname)-1;
1952
PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
1954
tsize = attrs - findTemp;
1955
PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
1957
key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
1958
if (key_ids == NULL) {
1961
keys = SECKEY_NewPublicKeyList();
1967
for (i=0; i < objCount ; i++) {
1968
SECKEYPublicKey *pubKey =
1969
PK11_ExtractPublicKey(slot,nullKey,key_ids[i]);
1971
SECKEY_AddPublicKeyToListTail(keys, pubKey);
1979
SECKEYPrivateKeyList*
1980
PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
1982
CK_ATTRIBUTE findTemp[4];
1983
CK_ATTRIBUTE *attrs;
1984
CK_BBOOL ckTrue = CK_TRUE;
1985
CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
1988
CK_OBJECT_HANDLE *key_ids;
1989
SECKEYPrivateKeyList *keys;
1994
PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
1995
PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
1997
len = PORT_Strlen(nickname)-1;
1998
PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
2000
tsize = attrs - findTemp;
2001
PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
2003
key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
2004
if (key_ids == NULL) {
2007
keys = SECKEY_NewPrivateKeyList();
2013
for (i=0; i < objCount ; i++) {
2014
SECKEYPrivateKey *privKey =
2015
PK11_MakePrivKey(slot,nullKey,PR_TRUE,key_ids[i],wincx);
2016
SECKEY_AddPrivateKeyToListTail(keys, privKey);