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 Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
38
* Internal PKCS #11 functions. Should only be called by pkcs11.c
48
#include "prnetdb.h" /* for PR_ntohl */
51
* ******************** Attribute Utilities *******************************
55
* create a new attribute with type, value, and length. Space is allocated
58
static SFTKAttribute *
59
sftk_NewAttribute(SFTKObject *object,
60
CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, CK_ULONG len)
62
SFTKAttribute *attribute;
64
SFTKSessionObject *so = sftk_narrowToSessionObject(object);
68
/* allocate new attribute in a buffer */
73
* We attempt to keep down contention on Malloc and Arena locks by
74
* limiting the number of these calls on high traversed paths. This
75
* is done for attributes by 'allocating' them from a pool already
76
* allocated by the parent object.
78
PZ_Lock(so->attributeLock);
79
index = so->nextAttr++;
80
PZ_Unlock(so->attributeLock);
81
PORT_Assert(index < MAX_OBJS_ATTRS);
82
if (index >= MAX_OBJS_ATTRS) return NULL;
84
attribute = &so->attrList[index];
85
attribute->attrib.type = type;
86
attribute->freeAttr = PR_FALSE;
87
attribute->freeData = PR_FALSE;
89
if (len <= ATTR_SPACE) {
90
attribute->attrib.pValue = attribute->space;
92
attribute->attrib.pValue = PORT_Alloc(len);
93
attribute->freeData = PR_TRUE;
95
if (attribute->attrib.pValue == NULL) {
98
PORT_Memcpy(attribute->attrib.pValue,value,len);
99
attribute->attrib.ulValueLen = len;
101
attribute->attrib.pValue = NULL;
102
attribute->attrib.ulValueLen = 0;
104
attribute->attrib.type = type;
105
attribute->handle = type;
106
attribute->next = attribute->prev = NULL;
110
static SFTKAttribute *
111
sftk_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
112
CK_ULONG len, PRBool copy)
114
SFTKAttribute *attribute;
116
attribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute));
118
if (attribute == NULL) return NULL;
119
attribute->attrib.type = type;
120
attribute->handle = type;
121
attribute->next = attribute->prev = NULL;
122
attribute->freeAttr = PR_TRUE;
123
attribute->freeData = PR_FALSE;
124
attribute->attrib.type = type;
126
attribute->attrib.pValue = value;
127
attribute->attrib.ulValueLen = len;
132
if (len <= ATTR_SPACE) {
133
attribute->attrib.pValue = attribute->space;
135
attribute->attrib.pValue = PORT_Alloc(len);
136
attribute->freeData = PR_TRUE;
138
if (attribute->attrib.pValue == NULL) {
139
PORT_Free(attribute);
142
PORT_Memcpy(attribute->attrib.pValue,value,len);
143
attribute->attrib.ulValueLen = len;
145
attribute->attrib.pValue = NULL;
146
attribute->attrib.ulValueLen = 0;
151
static SFTKAttribute *
152
sftk_NewTokenAttributeSigned(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
153
CK_ULONG len, PRBool copy)
155
unsigned char * dval = (unsigned char *)value;
160
return sftk_NewTokenAttribute(type,dval,len,copy);
164
* Free up all the memory associated with an attribute. Reference count
165
* must be zero to call this.
168
sftk_DestroyAttribute(SFTKAttribute *attribute)
170
if (attribute->freeData) {
171
if (attribute->attrib.pValue) {
172
/* clear out the data in the attribute value... it may have been
174
PORT_Memset(attribute->attrib.pValue, 0,
175
attribute->attrib.ulValueLen);
177
PORT_Free(attribute->attrib.pValue);
179
PORT_Free(attribute);
183
* release a reference to an attribute structure
186
sftk_FreeAttribute(SFTKAttribute *attribute)
188
if (attribute->freeAttr) {
189
sftk_DestroyAttribute(attribute);
194
#define SFTK_DEF_ATTRIBUTE(value,len) \
195
{ NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } }
197
#define SFTK_CLONE_ATTR(type, staticAttr) \
198
sftk_NewTokenAttribute( type, staticAttr.attrib.pValue, \
199
staticAttr.attrib.ulValueLen, PR_FALSE)
201
CK_BBOOL sftk_staticTrueValue = CK_TRUE;
202
CK_BBOOL sftk_staticFalseValue = CK_FALSE;
203
static const SFTKAttribute sftk_StaticTrueAttr =
204
SFTK_DEF_ATTRIBUTE(&sftk_staticTrueValue,sizeof(sftk_staticTrueValue));
205
static const SFTKAttribute sftk_StaticFalseAttr =
206
SFTK_DEF_ATTRIBUTE(&sftk_staticFalseValue,sizeof(sftk_staticFalseValue));
207
static const SFTKAttribute sftk_StaticNullAttr = SFTK_DEF_ATTRIBUTE(NULL,0);
208
char sftk_StaticOneValue = 1;
209
static const SFTKAttribute sftk_StaticOneAttr =
210
SFTK_DEF_ATTRIBUTE(&sftk_StaticOneValue,sizeof(sftk_StaticOneValue));
212
CK_CERTIFICATE_TYPE sftk_staticX509Value = CKC_X_509;
213
static const SFTKAttribute sftk_StaticX509Attr =
214
SFTK_DEF_ATTRIBUTE(&sftk_staticX509Value, sizeof(sftk_staticX509Value));
215
CK_TRUST sftk_staticTrustedValue = CKT_NETSCAPE_TRUSTED;
216
CK_TRUST sftk_staticTrustedDelegatorValue = CKT_NETSCAPE_TRUSTED_DELEGATOR;
217
CK_TRUST sftk_staticValidDelegatorValue = CKT_NETSCAPE_VALID_DELEGATOR;
218
CK_TRUST sftk_staticUnTrustedValue = CKT_NETSCAPE_UNTRUSTED;
219
CK_TRUST sftk_staticTrustUnknownValue = CKT_NETSCAPE_TRUST_UNKNOWN;
220
CK_TRUST sftk_staticValidPeerValue = CKT_NETSCAPE_VALID;
221
CK_TRUST sftk_staticMustVerifyValue = CKT_NETSCAPE_MUST_VERIFY;
222
static const SFTKAttribute sftk_StaticTrustedAttr =
223
SFTK_DEF_ATTRIBUTE(&sftk_staticTrustedValue,
224
sizeof(sftk_staticTrustedValue));
225
static const SFTKAttribute sftk_StaticTrustedDelegatorAttr =
226
SFTK_DEF_ATTRIBUTE(&sftk_staticTrustedDelegatorValue,
227
sizeof(sftk_staticTrustedDelegatorValue));
228
static const SFTKAttribute sftk_StaticValidDelegatorAttr =
229
SFTK_DEF_ATTRIBUTE(&sftk_staticValidDelegatorValue,
230
sizeof(sftk_staticValidDelegatorValue));
231
static const SFTKAttribute sftk_StaticUnTrustedAttr =
232
SFTK_DEF_ATTRIBUTE(&sftk_staticUnTrustedValue,
233
sizeof(sftk_staticUnTrustedValue));
234
static const SFTKAttribute sftk_StaticTrustUnknownAttr =
235
SFTK_DEF_ATTRIBUTE(&sftk_staticTrustUnknownValue,
236
sizeof(sftk_staticTrustUnknownValue));
237
static const SFTKAttribute sftk_StaticValidPeerAttr =
238
SFTK_DEF_ATTRIBUTE(&sftk_staticValidPeerValue,
239
sizeof(sftk_staticValidPeerValue));
240
static const SFTKAttribute sftk_StaticMustVerifyAttr =
241
SFTK_DEF_ATTRIBUTE(&sftk_staticMustVerifyValue,
242
sizeof(sftk_staticMustVerifyValue));
245
* helper functions which get the database and call the underlying
246
* low level database function.
249
sftk_FindKeyNicknameByPublicKey(SFTKSlot *slot, SECItem *dbKey)
251
NSSLOWKEYDBHandle *keyHandle;
254
keyHandle = sftk_getKeyDB(slot);
259
label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey,
261
sftk_freeKeyDB(keyHandle);
266
NSSLOWKEYPrivateKey *
267
sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey)
269
NSSLOWKEYPrivateKey *privKey;
270
NSSLOWKEYDBHandle *keyHandle;
272
keyHandle = sftk_getKeyDB(slot);
273
if (keyHandle == NULL) {
276
privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, slot->password);
277
sftk_freeKeyDB(keyHandle);
278
if (privKey == NULL) {
284
static certDBEntrySMime *
285
sftk_getSMime(SFTKTokenObject *object)
287
certDBEntrySMime *entry;
288
NSSLOWCERTCertDBHandle *certHandle;
290
if (object->obj.objclass != CKO_NETSCAPE_SMIME) {
293
if (object->obj.objectInfo) {
294
return (certDBEntrySMime *)object->obj.objectInfo;
297
certHandle = sftk_getCertDB(object->obj.slot);
301
entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)object->dbKey.data);
302
object->obj.objectInfo = (void *)entry;
303
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
304
sftk_freeCertDB(certHandle);
308
static certDBEntryRevocation *
309
sftk_getCrl(SFTKTokenObject *object)
311
certDBEntryRevocation *crl;
313
NSSLOWCERTCertDBHandle *certHandle;
315
if (object->obj.objclass != CKO_NETSCAPE_CRL) {
318
if (object->obj.objectInfo) {
319
return (certDBEntryRevocation *)object->obj.objectInfo;
322
isKrl = (PRBool) (object->obj.handle == SFTK_TOKEN_KRL_HANDLE);
323
certHandle = sftk_getCertDB(object->obj.slot);
328
crl = nsslowcert_FindCrlByKey(certHandle, &object->dbKey, isKrl);
329
object->obj.objectInfo = (void *)crl;
330
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
331
sftk_freeCertDB(certHandle);
335
static NSSLOWCERTCertificate *
336
sftk_getCert(SFTKTokenObject *object, NSSLOWCERTCertDBHandle *certHandle)
338
NSSLOWCERTCertificate *cert;
339
CK_OBJECT_CLASS objClass = object->obj.objclass;
341
if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NETSCAPE_TRUST)) {
344
if (objClass == CKO_CERTIFICATE && object->obj.objectInfo) {
345
return (NSSLOWCERTCertificate *)object->obj.objectInfo;
347
cert = nsslowcert_FindCertByKey(certHandle, &object->dbKey);
348
if (objClass == CKO_CERTIFICATE) {
349
object->obj.objectInfo = (void *)cert;
350
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyCertificate ;
355
static NSSLOWCERTTrust *
356
sftk_getTrust(SFTKTokenObject *object)
358
NSSLOWCERTTrust *trust;
359
NSSLOWCERTCertDBHandle *certHandle;
361
if (object->obj.objclass != CKO_NETSCAPE_TRUST) {
364
if (object->obj.objectInfo) {
365
return (NSSLOWCERTTrust *)object->obj.objectInfo;
367
certHandle = sftk_getCertDB(object->obj.slot);
371
trust = nsslowcert_FindTrustByKey(certHandle, &object->dbKey);
372
object->obj.objectInfo = (void *)trust;
373
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyTrust ;
374
sftk_freeCertDB(certHandle);
378
static NSSLOWKEYPublicKey *
379
sftk_GetPublicKey(SFTKTokenObject *object)
381
NSSLOWKEYPublicKey *pubKey;
382
NSSLOWKEYPrivateKey *privKey;
384
if (object->obj.objclass != CKO_PUBLIC_KEY) {
387
if (object->obj.objectInfo) {
388
return (NSSLOWKEYPublicKey *)object->obj.objectInfo;
390
privKey = sftk_FindKeyByPublicKey(object->obj.slot, &object->dbKey);
391
if (privKey == NULL) {
394
pubKey = nsslowkey_ConvertToPublicKey(privKey);
395
nsslowkey_DestroyPrivateKey(privKey);
396
object->obj.objectInfo = (void *) pubKey;
397
object->obj.infoFree = (SFTKFree) nsslowkey_DestroyPublicKey ;
402
* we need two versions of sftk_GetPrivateKey. One version that takes the
403
* DB handle so we can pass the handle we have already acquired in,
404
* rather than going through the 'getKeyDB' code again,
405
* which may fail the second time and another which just aquires
406
* the key handle from the slot (where we don't already have a key handle.
407
* This version does the former.
409
static NSSLOWKEYPrivateKey *
410
sftk_GetPrivateKeyWithDB(SFTKTokenObject *object, NSSLOWKEYDBHandle *keyHandle)
412
NSSLOWKEYPrivateKey *privKey;
414
if ((object->obj.objclass != CKO_PRIVATE_KEY) &&
415
(object->obj.objclass != CKO_SECRET_KEY)) {
418
if (object->obj.objectInfo) {
419
return (NSSLOWKEYPrivateKey *)object->obj.objectInfo;
421
privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &object->dbKey,
422
object->obj.slot->password);
423
if (privKey == NULL) {
426
object->obj.objectInfo = (void *) privKey;
427
object->obj.infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey ;
431
/* this version does the latter */
432
static NSSLOWKEYPrivateKey *
433
sftk_GetPrivateKey(SFTKTokenObject *object)
435
NSSLOWKEYDBHandle *keyHandle;
436
NSSLOWKEYPrivateKey *privKey;
438
keyHandle = sftk_getKeyDB(object->obj.slot);
442
privKey = sftk_GetPrivateKeyWithDB(object, keyHandle);
443
sftk_freeKeyDB(keyHandle);
447
/* sftk_GetPubItem returns data associated with the public key.
448
* one only needs to free the public key. This comment is here
449
* because this sematic would be non-obvious otherwise. All callers
450
* should include this comment.
453
sftk_GetPubItem(NSSLOWKEYPublicKey *pubKey) {
454
SECItem *pubItem = NULL;
455
/* get value to compare from the cert's public key */
456
switch ( pubKey->keyType ) {
457
case NSSLOWKEYRSAKey:
458
pubItem = &pubKey->u.rsa.modulus;
460
case NSSLOWKEYDSAKey:
461
pubItem = &pubKey->u.dsa.publicValue;
464
pubItem = &pubKey->u.dh.publicValue;
466
#ifdef NSS_ENABLE_ECC
468
pubItem = &pubKey->u.ec.publicValue;
470
#endif /* NSS_ENABLE_ECC */
477
static const SEC_ASN1Template sftk_SerialTemplate[] = {
478
{ SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
482
static SFTKAttribute *
483
sftk_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
485
unsigned char hash[SHA1_LENGTH];
486
CK_KEY_TYPE keyType = CKK_RSA;
490
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
492
SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
493
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
495
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
498
case CKA_VERIFY_RECOVER:
500
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
502
return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
503
key->u.rsa.modulus.len, PR_FALSE);
504
case CKA_PUBLIC_EXPONENT:
505
return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
506
key->u.rsa.publicExponent.len, PR_FALSE);
513
static SFTKAttribute *
514
sftk_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
516
unsigned char hash[SHA1_LENGTH];
517
CK_KEY_TYPE keyType = CKK_DSA;
521
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
523
SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
524
key->u.dsa.publicValue.len);
525
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
528
case CKA_VERIFY_RECOVER:
530
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
532
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
534
return sftk_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data,
535
key->u.dsa.publicValue.len, PR_FALSE);
537
return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
538
key->u.dsa.params.prime.len, PR_FALSE);
540
return sftk_NewTokenAttributeSigned(type,
541
key->u.dsa.params.subPrime.data,
542
key->u.dsa.params.subPrime.len, PR_FALSE);
544
return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
545
key->u.dsa.params.base.len, PR_FALSE);
552
static SFTKAttribute *
553
sftk_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
555
unsigned char hash[SHA1_LENGTH];
556
CK_KEY_TYPE keyType = CKK_DH;
560
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
562
SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
563
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
565
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
568
case CKA_VERIFY_RECOVER:
570
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
572
return sftk_NewTokenAttributeSigned(type,key->u.dh.publicValue.data,
573
key->u.dh.publicValue.len, PR_FALSE);
575
return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data,
576
key->u.dh.prime.len, PR_FALSE);
578
return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data,
579
key->u.dh.base.len, PR_FALSE);
586
#ifdef NSS_ENABLE_ECC
587
static SFTKAttribute *
588
sftk_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
590
unsigned char hash[SHA1_LENGTH];
591
CK_KEY_TYPE keyType = CKK_EC;
595
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
597
SHA1_HashBuf(hash, key->u.ec.publicValue.data,
598
key->u.ec.publicValue.len);
599
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
602
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
604
case CKA_VERIFY_RECOVER:
606
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
608
/* XXX Why is the last arg PR_FALSE? */
609
return sftk_NewTokenAttributeSigned(type,
610
key->u.ec.ecParams.DEREncoding.data,
611
key->u.ec.ecParams.DEREncoding.len,
614
/* XXX Why is the last arg PR_FALSE? */
615
return sftk_NewTokenAttributeSigned(type,key->u.ec.publicValue.data,
616
key->u.ec.publicValue.len, PR_FALSE);
622
#endif /* NSS_ENABLE_ECC */
625
static SFTKAttribute *
626
sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
628
NSSLOWKEYPublicKey *key;
629
SFTKAttribute *att = NULL;
635
case CKA_ALWAYS_SENSITIVE:
636
case CKA_NEVER_EXTRACTABLE:
637
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
639
case CKA_EXTRACTABLE:
640
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
642
label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
645
return SFTK_CLONE_ATTR(type,sftk_StaticOneAttr);
647
att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
654
key = sftk_GetPublicKey(object);
659
switch (key->keyType) {
660
case NSSLOWKEYRSAKey:
661
return sftk_FindRSAPublicKeyAttribute(key,type);
662
case NSSLOWKEYDSAKey:
663
return sftk_FindDSAPublicKeyAttribute(key,type);
665
return sftk_FindDHPublicKeyAttribute(key,type);
666
#ifdef NSS_ENABLE_ECC
668
return sftk_FindECPublicKeyAttribute(key,type);
669
#endif /* NSS_ENABLE_ECC */
677
static SFTKAttribute *
678
sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
680
NSSLOWKEYPrivateKey *key;
682
unsigned char *keyString;
687
PRUint32 keyTypeStorage;
692
case CKA_ALWAYS_SENSITIVE:
693
case CKA_EXTRACTABLE:
702
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
703
case CKA_NEVER_EXTRACTABLE:
704
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
706
label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
709
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
711
att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
722
key = sftk_GetPrivateKey(object);
728
/* handle legacy databases. In legacy databases key_type was stored
729
* in host order, with any leading zeros stripped off. Only key types
730
* under 0x1f (AES) were stored. We assume that any values which are
731
* either 1 byte long (big endian), or have byte[0] between 0 and
732
* 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other
733
* values are assumed to be from the new database, which is always 4
734
* bytes in network order */
736
keyString = key->u.rsa.coefficient.data;
737
keyTypeLen = key->u.rsa.coefficient.len;
741
* Because of various endian and word lengths The database may have
742
* stored the keyType value in one of the following formats:
745
* Big Endian, pre-3.9, all lengths: 1 (kt)
746
* Little Endian, pre-3.9, 32 bits: 4 (kt) 0 0 0
747
* Little Endian, pre-3.9, 64 bits: 8 (kt) 0 0 0 0 0 0 0
748
* All platforms, 3.9, 32 bits: 4 0 0 0 (kt)
749
* Big Endian, 3.9, 64 bits: 8 0 0 0 (kt) 0 0 0 0
750
* Little Endian, 3.9, 64 bits: 8 0 0 0 0 0 0 0 (kt)
751
* All platforms, >= 3.9.1, all lengths: 4 (a) k1 k2 k3
752
* where (a) is 0 or >= 0x80. currently (a) can only be 0.
755
* this key was written on a 64 bit platform with a using NSS 3.9
756
* or earlier. Reduce the 64 bit possibilities above. We were are
757
* through, we will only have:
759
* Big Endian, pre-3.9, all lengths: 1 (kt)
760
* Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
761
* All platforms, 3.9, all lengths: 4 0 0 0 (kt)
762
* All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3
764
if (keyTypeLen == 8) {
765
keyTypeStorage = *(PRUint32 *) keyString;
766
if (keyTypeStorage == 0) {
767
keyString += sizeof(PRUint32);
774
* All platforms, 3.9, all lengths: 4 0 0 0 (kt)
775
* All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3
777
* NOTE: if kt == 0 or ak1k2k3 == 0, the test fails and
780
* Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
782
if (keyTypeLen == sizeof(keyTypeStorage) &&
783
(((keyString[0] & 0x80) == 0x80) ||
784
!((keyString[1] == 0) && (keyString[2] == 0)
785
&& (keyString[3] == 0))) ) {
786
PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage));
787
keyType = (CK_KEY_TYPE) PR_ntohl(keyTypeStorage);
792
* Big Endian, pre-3.9, all lengths: 1 (kt)
793
* Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0
794
* -- KeyType == 0 all other cases ---: 4 0 0 0 0
796
keyType = (CK_KEY_TYPE) keyString[0] ;
798
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType),PR_TRUE);
800
return sftk_NewTokenAttribute(type,key->u.rsa.privateExponent.data,
801
key->u.rsa.privateExponent.len, PR_FALSE);
803
keyLen=key->u.rsa.privateExponent.len;
804
return sftk_NewTokenAttribute(type, &keyLen, sizeof(CK_ULONG), PR_TRUE);
810
static SFTKAttribute *
811
sftk_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
812
CK_ATTRIBUTE_TYPE type)
814
unsigned char hash[SHA1_LENGTH];
815
CK_KEY_TYPE keyType = CKK_RSA;
819
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
821
SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
822
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
824
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
827
case CKA_SIGN_RECOVER:
829
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
831
return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
832
key->u.rsa.modulus.len, PR_FALSE);
833
case CKA_PUBLIC_EXPONENT:
834
return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
835
key->u.rsa.publicExponent.len, PR_FALSE);
836
case CKA_PRIVATE_EXPONENT:
837
return sftk_NewTokenAttributeSigned(type,
838
key->u.rsa.privateExponent.data,
839
key->u.rsa.privateExponent.len, PR_FALSE);
841
return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime1.data,
842
key->u.rsa.prime1.len, PR_FALSE);
844
return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime2.data,
845
key->u.rsa.prime2.len, PR_FALSE);
847
return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent1.data,
848
key->u.rsa.exponent1.len, PR_FALSE);
850
return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent2.data,
851
key->u.rsa.exponent2.len, PR_FALSE);
852
case CKA_COEFFICIENT:
853
return sftk_NewTokenAttributeSigned(type, key->u.rsa.coefficient.data,
854
key->u.rsa.coefficient.len, PR_FALSE);
861
static SFTKAttribute *
862
sftk_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
863
CK_ATTRIBUTE_TYPE type)
865
unsigned char hash[SHA1_LENGTH];
866
CK_KEY_TYPE keyType = CKK_DSA;
870
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
872
SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
873
key->u.dsa.publicValue.len);
874
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
877
case CKA_SIGN_RECOVER:
879
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
881
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
883
return sftk_NewTokenAttributeSigned(type, key->u.dsa.privateValue.data,
884
key->u.dsa.privateValue.len, PR_FALSE);
886
return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
887
key->u.dsa.params.prime.len, PR_FALSE);
889
return sftk_NewTokenAttributeSigned(type,
890
key->u.dsa.params.subPrime.data,
891
key->u.dsa.params.subPrime.len, PR_FALSE);
893
return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
894
key->u.dsa.params.base.len, PR_FALSE);
895
case CKA_NETSCAPE_DB:
896
return sftk_NewTokenAttributeSigned(type,
897
key->u.dsa.publicValue.data,
898
key->u.dsa.publicValue.len,
906
static SFTKAttribute *
907
sftk_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
909
unsigned char hash[SHA1_LENGTH];
910
CK_KEY_TYPE keyType = CKK_DH;
914
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
916
SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
917
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
919
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
922
case CKA_SIGN_RECOVER:
924
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
926
return sftk_NewTokenAttributeSigned(type,key->u.dh.privateValue.data,
927
key->u.dh.privateValue.len, PR_FALSE);
929
return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data,
930
key->u.dh.prime.len, PR_FALSE);
932
return sftk_NewTokenAttributeSigned(type,key->u.dh.base.data,
933
key->u.dh.base.len, PR_FALSE);
934
case CKA_NETSCAPE_DB:
935
return sftk_NewTokenAttributeSigned(type,
936
key->u.dh.publicValue.data,
937
key->u.dh.publicValue.len,
945
#ifdef NSS_ENABLE_ECC
946
static SFTKAttribute *
947
sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
949
unsigned char hash[SHA1_LENGTH];
950
CK_KEY_TYPE keyType = CKK_EC;
954
return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
956
SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);
957
return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
960
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
962
case CKA_SIGN_RECOVER:
964
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
966
return sftk_NewTokenAttributeSigned(type, key->u.ec.privateValue.data,
967
key->u.ec.privateValue.len, PR_FALSE);
969
/* XXX Why is the last arg PR_FALSE? */
970
return sftk_NewTokenAttributeSigned(type,
971
key->u.ec.ecParams.DEREncoding.data,
972
key->u.ec.ecParams.DEREncoding.len,
974
case CKA_NETSCAPE_DB:
975
return sftk_NewTokenAttributeSigned(type,
976
key->u.ec.publicValue.data,
977
key->u.ec.publicValue.len,
984
#endif /* NSS_ENABLE_ECC */
986
static SFTKAttribute *
987
sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
989
NSSLOWKEYPrivateKey *key;
996
case CKA_ALWAYS_SENSITIVE:
997
case CKA_EXTRACTABLE:
999
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
1000
case CKA_NEVER_EXTRACTABLE:
1001
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
1003
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1005
label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
1007
if (label == NULL) {
1008
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1010
att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
1016
key = sftk_GetPrivateKey(object);
1020
switch (key->keyType) {
1021
case NSSLOWKEYRSAKey:
1022
return sftk_FindRSAPrivateKeyAttribute(key,type);
1023
case NSSLOWKEYDSAKey:
1024
return sftk_FindDSAPrivateKeyAttribute(key,type);
1025
case NSSLOWKEYDHKey:
1026
return sftk_FindDHPrivateKeyAttribute(key,type);
1027
#ifdef NSS_ENABLE_ECC
1028
case NSSLOWKEYECKey:
1029
return sftk_FindECPrivateKeyAttribute(key,type);
1030
#endif /* NSS_ENABLE_ECC */
1038
static SFTKAttribute *
1039
sftk_FindSMIMEAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
1041
certDBEntrySMime *entry;
1044
case CKA_MODIFIABLE:
1045
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
1046
case CKA_NETSCAPE_EMAIL:
1047
return sftk_NewTokenAttribute(type,object->dbKey.data,
1048
object->dbKey.len-1, PR_FALSE);
1049
case CKA_NETSCAPE_SMIME_TIMESTAMP:
1056
entry = sftk_getSMime(object);
1057
if (entry == NULL) {
1061
case CKA_NETSCAPE_SMIME_TIMESTAMP:
1062
return sftk_NewTokenAttribute(type,entry->optionsDate.data,
1063
entry->optionsDate.len, PR_FALSE);
1065
return sftk_NewTokenAttribute(type,entry->subjectName.data,
1066
entry->subjectName.len, PR_FALSE);
1068
return sftk_NewTokenAttribute(type,entry->smimeOptions.data,
1069
entry->smimeOptions.len, PR_FALSE);
1076
static SFTKAttribute *
1077
sftk_FindTrustAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
1079
NSSLOWCERTTrust *trust;
1080
unsigned char hash[SHA1_LENGTH];
1081
unsigned int trustFlags;
1085
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
1086
case CKA_MODIFIABLE:
1087
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
1088
case CKA_CERT_SHA1_HASH:
1089
case CKA_CERT_MD5_HASH:
1090
case CKA_TRUST_CLIENT_AUTH:
1091
case CKA_TRUST_SERVER_AUTH:
1092
case CKA_TRUST_EMAIL_PROTECTION:
1093
case CKA_TRUST_CODE_SIGNING:
1094
case CKA_TRUST_STEP_UP_APPROVED:
1099
trust = sftk_getTrust(object);
1100
if (trust == NULL) {
1104
case CKA_CERT_SHA1_HASH:
1105
SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len);
1106
return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
1107
case CKA_CERT_MD5_HASH:
1108
MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len);
1109
return sftk_NewTokenAttribute(type, hash, MD5_LENGTH, PR_TRUE);
1110
case CKA_TRUST_CLIENT_AUTH:
1111
trustFlags = trust->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
1112
trust->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
1114
case CKA_TRUST_SERVER_AUTH:
1115
trustFlags = trust->trust->sslFlags;
1117
case CKA_TRUST_EMAIL_PROTECTION:
1118
trustFlags = trust->trust->emailFlags;
1120
case CKA_TRUST_CODE_SIGNING:
1121
trustFlags = trust->trust->objectSigningFlags;
1123
if (trustFlags & CERTDB_TRUSTED_CA ) {
1124
return SFTK_CLONE_ATTR(type,sftk_StaticTrustedDelegatorAttr);
1126
if (trustFlags & CERTDB_TRUSTED) {
1127
return SFTK_CLONE_ATTR(type,sftk_StaticTrustedAttr);
1129
if (trustFlags & CERTDB_NOT_TRUSTED) {
1130
return SFTK_CLONE_ATTR(type,sftk_StaticUnTrustedAttr);
1132
if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
1133
return SFTK_CLONE_ATTR(type,sftk_StaticTrustUnknownAttr);
1135
if (trustFlags & CERTDB_VALID_CA) {
1136
return SFTK_CLONE_ATTR(type,sftk_StaticValidDelegatorAttr);
1138
if (trustFlags & CERTDB_VALID_PEER) {
1139
return SFTK_CLONE_ATTR(type,sftk_StaticValidPeerAttr);
1141
return SFTK_CLONE_ATTR(type,sftk_StaticMustVerifyAttr);
1142
case CKA_TRUST_STEP_UP_APPROVED:
1143
if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) {
1144
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
1146
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
1155
cert = sftk_getCertObject(object);
1156
if (cert == NULL) break;
1157
attr = sftk_NewTokenAttribute(type,cert->derIssuer.data,
1158
cert->derIssuer.len, PR_FALSE);
1160
case CKA_SERIAL_NUMBER:
1161
cert = sftk_getCertObject(object);
1162
if (cert == NULL) break;
1163
item = SEC_ASN1EncodeItem(NULL,NULL,cert,sftk_SerialTemplate);
1164
if (item == NULL) break;
1165
attr = sftk_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
1166
SECITEM_FreeItem(item,PR_TRUE);
1169
NSSLOWCERTDestroyCertificate(cert);
1176
static SFTKAttribute *
1177
sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
1179
certDBEntryRevocation *crl;
1183
case CKA_MODIFIABLE:
1184
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
1185
case CKA_NETSCAPE_KRL:
1186
return ((object->obj.handle == SFTK_TOKEN_KRL_HANDLE)
1187
? SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr)
1188
: SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr));
1190
return sftk_NewTokenAttribute(type,object->dbKey.data,
1191
object->dbKey.len, PR_FALSE);
1192
case CKA_NETSCAPE_URL:
1196
PORT_SetError(SEC_ERROR_INVALID_ARGS);
1199
crl = sftk_getCrl(object);
1204
case CKA_NETSCAPE_URL:
1205
if (crl->url == NULL) {
1206
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1208
return sftk_NewTokenAttribute(type, crl->url,
1209
PORT_Strlen(crl->url)+1, PR_TRUE);
1211
return sftk_NewTokenAttribute(type, crl->derCrl.data,
1212
crl->derCrl.len, PR_FALSE);
1219
static SFTKAttribute *
1220
sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
1222
NSSLOWCERTCertificate *cert;
1223
NSSLOWCERTCertDBHandle *certHandle;
1224
NSSLOWKEYPublicKey *pubKey;
1225
unsigned char hash[SHA1_LENGTH];
1230
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
1231
case CKA_MODIFIABLE:
1232
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
1233
case CKA_CERTIFICATE_TYPE:
1234
/* hardcoding X.509 into here */
1235
return SFTK_CLONE_ATTR(type,sftk_StaticX509Attr);
1241
case CKA_SERIAL_NUMBER:
1242
case CKA_NETSCAPE_EMAIL:
1248
certHandle = sftk_getCertDB(object->obj.slot);
1249
if (certHandle == NULL) {
1253
cert = sftk_getCert(object, certHandle);
1254
sftk_freeCertDB(certHandle);
1260
return sftk_NewTokenAttribute(type,cert->derCert.data,
1261
cert->derCert.len,PR_FALSE);
1263
if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
1264
((cert->trust->emailFlags & CERTDB_USER) == 0) &&
1265
((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
1266
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1268
pubKey = nsslowcert_ExtractPublicKey(cert);
1269
if (pubKey == NULL) break;
1270
item = sftk_GetPubItem(pubKey);
1272
nsslowkey_DestroyPublicKey(pubKey);
1275
SHA1_HashBuf(hash,item->data,item->len);
1276
/* item is imbedded in pubKey, just free the key */
1277
nsslowkey_DestroyPublicKey(pubKey);
1278
return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
1280
return cert->nickname
1281
? sftk_NewTokenAttribute(type, cert->nickname,
1282
PORT_Strlen(cert->nickname), PR_FALSE)
1283
: SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1285
return sftk_NewTokenAttribute(type,cert->derSubject.data,
1286
cert->derSubject.len, PR_FALSE);
1288
return sftk_NewTokenAttribute(type,cert->derIssuer.data,
1289
cert->derIssuer.len, PR_FALSE);
1290
case CKA_SERIAL_NUMBER:
1291
return sftk_NewTokenAttribute(type,cert->derSN.data,
1292
cert->derSN.len, PR_FALSE);
1293
case CKA_NETSCAPE_EMAIL:
1294
return (cert->emailAddr && cert->emailAddr[0])
1295
? sftk_NewTokenAttribute(type, cert->emailAddr,
1296
PORT_Strlen(cert->emailAddr), PR_FALSE)
1297
: SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1304
static SFTKAttribute *
1305
sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
1307
/* handle the common ones */
1310
return sftk_NewTokenAttribute(type,&object->obj.objclass,
1311
sizeof(object->obj.objclass),PR_FALSE);
1313
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
1315
if ( (object->obj.objclass == CKO_CERTIFICATE)
1316
|| (object->obj.objclass == CKO_PRIVATE_KEY)
1317
|| (object->obj.objclass == CKO_PUBLIC_KEY)
1318
|| (object->obj.objclass == CKO_SECRET_KEY)) {
1321
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
1325
switch (object->obj.objclass) {
1326
case CKO_CERTIFICATE:
1327
return sftk_FindCertAttribute(object,type);
1328
case CKO_NETSCAPE_CRL:
1329
return sftk_FindCrlAttribute(object,type);
1330
case CKO_NETSCAPE_TRUST:
1331
return sftk_FindTrustAttribute(object,type);
1332
case CKO_NETSCAPE_SMIME:
1333
return sftk_FindSMIMEAttribute(object,type);
1334
case CKO_PUBLIC_KEY:
1335
return sftk_FindPublicKeyAttribute(object,type);
1336
case CKO_PRIVATE_KEY:
1337
return sftk_FindPrivateKeyAttribute(object,type);
1338
case CKO_SECRET_KEY:
1339
return sftk_FindSecretKeyAttribute(object,type);
1348
* look up and attribute structure from a type and Object structure.
1349
* The returned attribute is referenced and needs to be freed when
1350
* it is no longer needed.
1353
sftk_FindAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
1355
SFTKAttribute *attribute;
1356
SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1358
if (sessObject == NULL) {
1359
return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object),type);
1362
PZ_Lock(sessObject->attributeLock);
1363
sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
1364
PZ_Unlock(sessObject->attributeLock);
1370
* Take a buffer and it's length and return it's true size in bits;
1373
sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
1375
unsigned int size = bufLen * 8;
1378
/* Get the real length in bytes */
1379
for (i=0; i < bufLen; i++) {
1380
unsigned char c = *buf++;
1383
for (m=0x80; m > 0 ; m = m >> 1) {
1397
* Constrain a big num attribute. to size and padding
1398
* minLength means length of the object must be greater than equal to minLength
1399
* maxLength means length of the object must be less than equal to maxLength
1400
* minMultiple means that object length mod minMultiple must equal 0.
1401
* all input sizes are in bits.
1402
* if any constraint is '0' that constraint is not checked.
1405
sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
1406
int minLength, int maxLength, int minMultiple)
1408
SFTKAttribute *attribute;
1412
attribute = sftk_FindAttribute(object, type);
1414
return CKR_TEMPLATE_INCOMPLETE;
1416
ptr = (unsigned char *) attribute->attrib.pValue;
1418
sftk_FreeAttribute(attribute);
1419
return CKR_ATTRIBUTE_VALUE_INVALID;
1421
size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen);
1422
sftk_FreeAttribute(attribute);
1424
if ((minLength != 0) && (size < minLength)) {
1425
return CKR_ATTRIBUTE_VALUE_INVALID;
1427
if ((maxLength != 0) && (size > maxLength)) {
1428
return CKR_ATTRIBUTE_VALUE_INVALID;
1430
if ((minMultiple != 0) && ((size % minMultiple) != 0)) {
1431
return CKR_ATTRIBUTE_VALUE_INVALID;
1437
sftk_hasAttributeToken(SFTKTokenObject *object)
1443
* return true if object has attribute
1446
sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
1448
SFTKAttribute *attribute;
1449
SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1451
if (sessObject == NULL) {
1452
return sftk_hasAttributeToken(sftk_narrowToTokenObject(object));
1455
PZ_Lock(sessObject->attributeLock);
1456
sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
1457
PZ_Unlock(sessObject->attributeLock);
1459
return (PRBool)(attribute != NULL);
1463
* add an attribute to an object
1466
sftk_AddAttribute(SFTKObject *object,SFTKAttribute *attribute)
1468
SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1470
if (sessObject == NULL) return;
1471
PZ_Lock(sessObject->attributeLock);
1472
sftkqueue_add(attribute,attribute->handle,
1473
sessObject->head, sessObject->hashSize);
1474
PZ_Unlock(sessObject->attributeLock);
1478
* copy an unsigned attribute into a SECItem. Secitem is allocated in
1479
* the specified arena.
1482
sftk_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
1483
CK_ATTRIBUTE_TYPE type)
1485
SFTKAttribute *attribute;
1489
attribute = sftk_FindAttribute(object, type);
1490
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
1492
(void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen);
1493
if (item->data == NULL) {
1494
sftk_FreeAttribute(attribute);
1495
return CKR_HOST_MEMORY;
1497
PORT_Memcpy(item->data, attribute->attrib.pValue, item->len);
1498
sftk_FreeAttribute(attribute);
1504
* delete an attribute from an object
1507
sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute)
1509
SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1511
if (sessObject == NULL) {
1514
PZ_Lock(sessObject->attributeLock);
1515
if (sftkqueue_is_queued(attribute,attribute->handle,
1516
sessObject->head, sessObject->hashSize)) {
1517
sftkqueue_delete(attribute,attribute->handle,
1518
sessObject->head, sessObject->hashSize);
1520
PZ_Unlock(sessObject->attributeLock);
1524
* this is only valid for CK_BBOOL type attributes. Return the state
1525
* of that attribute.
1528
sftk_isTrue(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
1530
SFTKAttribute *attribute;
1531
PRBool tok = PR_FALSE;
1533
attribute=sftk_FindAttribute(object,type);
1534
if (attribute == NULL) { return PR_FALSE; }
1535
tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
1536
sftk_FreeAttribute(attribute);
1542
* force an attribute to null.
1543
* this is for sensitive keys which are stored in the database, we don't
1544
* want to keep this info around in memory in the clear.
1547
sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
1549
SFTKAttribute *attribute;
1551
attribute=sftk_FindAttribute(object,type);
1552
if (attribute == NULL) return;
1554
if (attribute->attrib.pValue != NULL) {
1555
PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
1556
if (attribute->freeData) {
1557
PORT_Free(attribute->attrib.pValue);
1559
attribute->freeData = PR_FALSE;
1560
attribute->attrib.pValue = NULL;
1561
attribute->attrib.ulValueLen = 0;
1563
sftk_FreeAttribute(attribute);
1567
sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
1568
void *value, unsigned int len)
1570
NSSLOWCERTCertificate *cert;
1571
NSSLOWCERTCertDBHandle *certHandle;
1572
char *nickname = NULL;
1576
/* we can't change the EMAIL values, but let the
1577
* upper layers feel better about the fact we tried to set these */
1578
if (type == CKA_NETSCAPE_EMAIL) {
1582
certHandle = sftk_getCertDB(to->obj.slot);
1583
if (certHandle == NULL) {
1584
crv = CKR_TOKEN_WRITE_PROTECTED;
1588
if ((type != CKA_LABEL) && (type != CKA_ID)) {
1589
crv = CKR_ATTRIBUTE_READ_ONLY;
1593
cert = sftk_getCert(to, certHandle);
1595
crv = CKR_OBJECT_HANDLE_INVALID;
1599
/* if the app is trying to set CKA_ID, it's probably because it just
1600
* imported the key. Look to see if we need to set the CERTDB_USER bits.
1602
if (type == CKA_ID) {
1603
if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
1604
((cert->trust->emailFlags & CERTDB_USER) == 0) &&
1605
((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
1606
SFTKSlot *slot = to->obj.slot;
1607
NSSLOWKEYDBHandle *keyHandle;
1609
keyHandle = sftk_getKeyDB(slot);
1611
if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
1612
NSSLOWCERTCertTrust trust = *cert->trust;
1613
trust.sslFlags |= CERTDB_USER;
1614
trust.emailFlags |= CERTDB_USER;
1615
trust.objectSigningFlags |= CERTDB_USER;
1616
nsslowcert_ChangeCertTrust(certHandle,cert,&trust);
1618
sftk_freeKeyDB(keyHandle);
1625
/* must be CKA_LABEL */
1626
if (value != NULL) {
1627
nickname = PORT_ZAlloc(len+1);
1628
if (nickname == NULL) {
1629
crv = CKR_HOST_MEMORY;
1632
PORT_Memcpy(nickname,value,len);
1635
rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
1636
crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1640
PORT_Free(nickname);
1643
sftk_freeCertDB(certHandle);
1649
sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
1650
void *value, unsigned int len)
1652
NSSLOWKEYPrivateKey *privKey;
1653
NSSLOWKEYDBHandle *keyHandle;
1654
char *nickname = NULL;
1658
/* we can't change the ID and we don't store the subject, but let the
1659
* upper layers feel better about the fact we tried to set these */
1660
if ((type == CKA_ID) || (type == CKA_SUBJECT)) {
1664
keyHandle = sftk_getKeyDB(to->obj.slot);
1665
if (keyHandle == NULL) {
1666
crv = CKR_TOKEN_WRITE_PROTECTED;
1669
if (type != CKA_LABEL) {
1670
crv = CKR_ATTRIBUTE_READ_ONLY;
1674
privKey = sftk_GetPrivateKeyWithDB(to, keyHandle);
1675
if (privKey == NULL) {
1676
crv = CKR_OBJECT_HANDLE_INVALID;
1679
if (value != NULL) {
1680
nickname = PORT_ZAlloc(len+1);
1681
if (nickname == NULL) {
1682
crv = CKR_HOST_MEMORY;
1685
PORT_Memcpy(nickname,value,len);
1688
rv = nsslowkey_UpdateNickname(keyHandle, privKey, &to->dbKey,
1689
nickname, to->obj.slot->password);
1690
crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1693
PORT_Free(nickname);
1696
sftk_freeKeyDB(keyHandle);
1702
sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
1703
void *value, unsigned int len)
1707
NSSLOWCERTCertificate *cert;
1708
NSSLOWCERTCertDBHandle *certHandle;
1709
NSSLOWCERTCertTrust dbTrust;
1713
if (len != sizeof (CK_TRUST)) {
1714
return CKR_ATTRIBUTE_VALUE_INVALID;
1716
trust = *(CK_TRUST *)value;
1717
flags = sftk_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH));
1719
certHandle = sftk_getCertDB(to->obj.slot);
1721
if (certHandle == NULL) {
1722
crv = CKR_TOKEN_WRITE_PROTECTED;
1726
cert = sftk_getCert(to, certHandle);
1728
crv = CKR_OBJECT_HANDLE_INVALID;
1731
dbTrust = *cert->trust;
1734
case CKA_TRUST_EMAIL_PROTECTION:
1735
dbTrust.emailFlags = flags |
1736
(cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
1738
case CKA_TRUST_CODE_SIGNING:
1739
dbTrust.objectSigningFlags = flags |
1740
(cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
1742
case CKA_TRUST_CLIENT_AUTH:
1743
dbTrust.sslFlags = flags | (cert->trust->sslFlags &
1744
(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA));
1746
case CKA_TRUST_SERVER_AUTH:
1747
dbTrust.sslFlags = flags | (cert->trust->sslFlags &
1748
(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));
1751
crv = CKR_ATTRIBUTE_READ_ONLY;
1755
rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
1756
crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
1759
sftk_freeCertDB(certHandle);
1765
sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type,
1766
void *value, unsigned int len)
1768
SFTKAttribute *attribute;
1769
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1770
CK_RV crv = CKR_ATTRIBUTE_READ_ONLY;
1774
return CKR_DEVICE_ERROR;
1777
/* if we are just setting it to the value we already have,
1778
* allow it to happen. Let label setting go through so
1779
* we have the opportunity to repair any database corruption. */
1780
attribute=sftk_FindAttribute(object,type);
1781
PORT_Assert(attribute);
1783
return CKR_ATTRIBUTE_TYPE_INVALID;
1786
if ((type != CKA_LABEL) && (attribute->attrib.ulValueLen == len) &&
1787
PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) {
1788
sftk_FreeAttribute(attribute);
1792
switch (object->objclass) {
1793
case CKO_CERTIFICATE:
1794
/* change NICKNAME, EMAIL, */
1795
crv = sftk_SetCertAttribute(to,type,value,len);
1797
case CKO_NETSCAPE_CRL:
1800
case CKO_NETSCAPE_TRUST:
1801
crv = sftk_SetTrustAttribute(to,type,value,len);
1803
case CKO_PRIVATE_KEY:
1804
case CKO_SECRET_KEY:
1805
crv = sftk_SetPrivateKeyAttribute(to,type,value,len);
1808
sftk_FreeAttribute(attribute);
1813
* force an attribute to a spaecif value.
1816
sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, void *value,
1819
SFTKAttribute *attribute;
1820
void *att_val = NULL;
1821
PRBool freeData = PR_FALSE;
1823
PORT_Assert(object);
1824
PORT_Assert(object->refCount);
1825
PORT_Assert(object->slot);
1827
!object->refCount ||
1829
return CKR_DEVICE_ERROR;
1831
if (sftk_isToken(object->handle)) {
1832
return sftk_forceTokenAttribute(object,type,value,len);
1834
attribute=sftk_FindAttribute(object,type);
1835
if (attribute == NULL) return sftk_AddAttributeType(object,type,value,len);
1839
if (len <= ATTR_SPACE) {
1840
att_val = attribute->space;
1842
att_val = PORT_Alloc(len);
1845
if (att_val == NULL) {
1846
return CKR_HOST_MEMORY;
1848
if (attribute->attrib.pValue == att_val) {
1849
PORT_Memset(attribute->attrib.pValue,0,
1850
attribute->attrib.ulValueLen);
1852
PORT_Memcpy(att_val,value,len);
1854
if (attribute->attrib.pValue != NULL) {
1855
if (attribute->attrib.pValue != att_val) {
1856
PORT_Memset(attribute->attrib.pValue,0,
1857
attribute->attrib.ulValueLen);
1859
if (attribute->freeData) {
1860
PORT_Free(attribute->attrib.pValue);
1862
attribute->freeData = PR_FALSE;
1863
attribute->attrib.pValue = NULL;
1864
attribute->attrib.ulValueLen = 0;
1867
attribute->attrib.pValue = att_val;
1868
attribute->attrib.ulValueLen = len;
1869
attribute->freeData = freeData;
1871
sftk_FreeAttribute(attribute);
1876
* return a null terminated string from attribute 'type'. This string
1877
* is allocated and needs to be freed with PORT_Free() When complete.
1880
sftk_getString(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
1882
SFTKAttribute *attribute;
1885
attribute=sftk_FindAttribute(object,type);
1886
if (attribute == NULL) return NULL;
1888
if (attribute->attrib.pValue != NULL) {
1889
label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1);
1890
if (label == NULL) {
1891
sftk_FreeAttribute(attribute);
1895
PORT_Memcpy(label,attribute->attrib.pValue,
1896
attribute->attrib.ulValueLen);
1897
label[attribute->attrib.ulValueLen] = 0;
1899
sftk_FreeAttribute(attribute);
1904
* decode when a particular attribute may be modified
1905
* SFTK_NEVER: This attribute must be set at object creation time and
1906
* can never be modified.
1907
* SFTK_ONCOPY: This attribute may be modified only when you copy the
1909
* SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
1910
* CK_FALSE to CK_TRUE.
1911
* SFTK_ALWAYS: This attribute can always be modified.
1912
* Some attributes vary their modification type based on the class of the
1916
sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
1918
/* if we don't know about it, user user defined, always allow modify */
1919
SFTKModifyType mtype = SFTK_ALWAYS;
1924
case CKA_CERTIFICATE_TYPE:
1927
case CKA_MODULUS_BITS:
1928
case CKA_PUBLIC_EXPONENT:
1929
case CKA_PRIVATE_EXPONENT:
1935
case CKA_EXPONENT_1:
1936
case CKA_EXPONENT_2:
1937
case CKA_COEFFICIENT:
1939
case CKA_ALWAYS_SENSITIVE:
1940
case CKA_NEVER_EXTRACTABLE:
1941
case CKA_NETSCAPE_DB:
1948
case CKA_MODIFIABLE:
1949
mtype = SFTK_ONCOPY;
1954
case CKA_EXTRACTABLE:
1955
mtype = SFTK_SENSITIVE;
1960
case CKA_APPLICATION:
1962
case CKA_SERIAL_NUMBER:
1963
case CKA_START_DATE:
1970
case CKA_SIGN_RECOVER:
1971
case CKA_VERIFY_RECOVER:
1974
mtype = SFTK_ALWAYS;
1977
/* DEPENDS ON CLASS */
1979
mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER;
1983
mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS;
1991
/* decode if a particular attribute is sensitive (cannot be read
1992
* back to the user of if the object is set to SENSITIVE) */
1994
sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
1998
case CKA_PRIVATE_EXPONENT:
2001
case CKA_EXPONENT_1:
2002
case CKA_EXPONENT_2:
2003
case CKA_COEFFICIENT:
2006
/* DEPENDS ON CLASS */
2008
/* PRIVATE and SECRET KEYS have SENSITIVE values */
2009
return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY));
2018
* copy an attribute into a SECItem. Secitem is allocated in the specified
2022
sftk_Attribute2SecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
2023
CK_ATTRIBUTE_TYPE type)
2026
SFTKAttribute *attribute;
2028
attribute = sftk_FindAttribute(object, type);
2029
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
2030
len = attribute->attrib.ulValueLen;
2033
item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
2035
item->data = (unsigned char *) PORT_Alloc(len);
2037
if (item->data == NULL) {
2038
sftk_FreeAttribute(attribute);
2039
return CKR_HOST_MEMORY;
2042
PORT_Memcpy(item->data,attribute->attrib.pValue, len);
2043
sftk_FreeAttribute(attribute);
2048
sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
2051
SFTKAttribute *attribute;
2053
attribute = sftk_FindAttribute(object, type);
2054
if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
2056
if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) {
2057
return CKR_ATTRIBUTE_VALUE_INVALID;
2060
*longData = *(CK_ULONG *)attribute->attrib.pValue;
2061
sftk_FreeAttribute(attribute);
2066
sftk_DeleteAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
2068
SFTKAttribute *attribute;
2069
attribute = sftk_FindAttribute(object, type);
2070
if (attribute == NULL) return ;
2071
sftk_DeleteAttribute(object,attribute);
2072
sftk_FreeAttribute(attribute);
2076
sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
2079
SFTKAttribute *attribute;
2080
attribute = sftk_NewAttribute(object,type,valPtr,length);
2081
if (attribute == NULL) { return CKR_HOST_MEMORY; }
2082
sftk_AddAttribute(object,attribute);
2087
* ******************** Object Utilities *******************************
2091
sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
2096
item = (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle);
2097
rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ;
2099
SECITEM_FreeItem(item,PR_TRUE);
2101
return rem ? SECSuccess : SECFailure;
2104
/* must be called holding sftk_tokenKeyLock(slot) */
2106
sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
2111
/* don't add a new handle in the middle of closing down a slot */
2112
if (!slot->present) {
2116
item = SECITEM_DupItem(key);
2120
entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item);
2121
if (entry == NULL) {
2122
SECITEM_FreeItem(item,PR_TRUE);
2128
/* must be called holding sftk_tokenKeyLock(slot) */
2130
sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
2132
return (SECItem *)PL_HashTableLookup(slot->tokenHashTable, (void *)handle);
2136
* use the refLock. This operations should be very rare, so the added
2137
* contention on the ref lock should be lower than the overhead of adding
2138
* a new lock. We use separate functions for this just in case I'm wrong.
2141
sftk_tokenKeyLock(SFTKSlot *slot) {
2142
PZ_Lock(slot->objectLock);
2146
sftk_tokenKeyUnlock(SFTKSlot *slot) {
2147
PZ_Unlock(slot->objectLock);
2151
sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
2153
SECItem *item = (SECItem *)entry->value;
2155
SECITEM_FreeItem(item, PR_TRUE);
2156
return HT_ENUMERATE_NEXT;
2160
SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
2162
sftk_tokenKeyLock(slot);
2163
PORT_Assert(!slot->present);
2164
PL_HashTableEnumerateEntries(slot->tokenHashTable, sftk_freeHashItem, NULL);
2165
sftk_tokenKeyUnlock(slot);
2170
/* allocation hooks that allow us to recycle old object structures */
2171
static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 };
2172
static SFTKObjectFreeList tokenObjectList = { NULL, NULL, 0 };
2175
sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace,
2176
SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject)
2181
if (!optimizeSpace) {
2182
PZ_Lock(list->lock);
2183
object = list->head;
2185
list->head = object->next;
2188
PZ_Unlock(list->lock);
2190
object->next = object->prev = NULL;
2191
*hasLocks = PR_TRUE;
2195
size = isSessionObject ? sizeof(SFTKSessionObject)
2196
+ hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject);
2198
object = (SFTKObject*)PORT_ZAlloc(size);
2199
if (isSessionObject) {
2200
((SFTKSessionObject *)object)->hashSize = hashSize;
2202
*hasLocks = PR_FALSE;
2207
sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
2208
PRBool isSessionObject) {
2210
/* the code below is equivalent to :
2211
* optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
2214
PRBool optimizeSpace = isSessionObject &&
2215
((SFTKSessionObject *)object)->optimizeSpace;
2216
if (!optimizeSpace && (list->count < MAX_OBJECT_LIST_SIZE)) {
2217
PZ_Lock(list->lock);
2218
object->next = list->head;
2219
list->head = object;
2221
PZ_Unlock(list->lock);
2224
if (isSessionObject) {
2225
SFTKSessionObject *so = (SFTKSessionObject *)object;
2226
PZ_DestroyLock(so->attributeLock);
2227
so->attributeLock = NULL;
2229
PZ_DestroyLock(object->refLock);
2230
object->refLock = NULL;
2235
sftk_freeObjectData(SFTKObject *object) {
2236
SFTKObject *next = object->next;
2243
sftk_InitFreeList(SFTKObjectFreeList *list)
2245
list->lock = PZ_NewLock(nssILockObject);
2248
void sftk_InitFreeLists(void)
2250
sftk_InitFreeList(&sessionObjectList);
2251
sftk_InitFreeList(&tokenObjectList);
2255
sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList)
2262
PZ_Lock(list->lock);
2263
for (object= list->head; object != NULL;
2264
object = sftk_freeObjectData(object)) {
2265
PZ_DestroyLock(object->refLock);
2266
if (isSessionList) {
2267
PZ_DestroyLock(((SFTKSessionObject *)object)->attributeLock);
2272
PZ_Unlock(list->lock);
2273
PZ_DestroyLock(list->lock);
2278
sftk_CleanupFreeLists(void)
2280
sftk_CleanupFreeList(&sessionObjectList, PR_TRUE);
2281
sftk_CleanupFreeList(&tokenObjectList, PR_FALSE);
2286
* Create a new object
2289
sftk_NewObject(SFTKSlot *slot)
2292
SFTKSessionObject *sessObject;
2293
PRBool hasLocks = PR_FALSE;
2295
unsigned int hashSize = 0;
2297
hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE :
2298
TIME_ATTRIBUTE_HASH_SIZE;
2300
object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace,
2301
&sessionObjectList, hashSize, PR_TRUE);
2302
if (object == NULL) {
2305
sessObject = (SFTKSessionObject *)object;
2306
sessObject->nextAttr = 0;
2308
for (i=0; i < MAX_OBJS_ATTRS; i++) {
2309
sessObject->attrList[i].attrib.pValue = NULL;
2310
sessObject->attrList[i].freeData = PR_FALSE;
2312
sessObject->optimizeSpace = slot->optimizeSpace;
2315
object->next = object->prev = NULL;
2316
object->slot = slot;
2318
object->refCount = 1;
2319
sessObject->sessionList.next = NULL;
2320
sessObject->sessionList.prev = NULL;
2321
sessObject->sessionList.parent = object;
2322
sessObject->session = NULL;
2323
sessObject->wasDerived = PR_FALSE;
2324
if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock);
2325
if (object->refLock == NULL) {
2329
if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute);
2330
if (sessObject->attributeLock == NULL) {
2331
PZ_DestroyLock(object->refLock);
2335
for (i=0; i < sessObject->hashSize; i++) {
2336
sessObject->head[i] = NULL;
2338
object->objectInfo = NULL;
2339
object->infoFree = NULL;
2344
sftk_DestroySessionObjectData(SFTKSessionObject *so)
2348
for (i=0; i < MAX_OBJS_ATTRS; i++) {
2349
unsigned char *value = so->attrList[i].attrib.pValue;
2351
PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen);
2352
if (so->attrList[i].freeData) {
2355
so->attrList[i].attrib.pValue = NULL;
2356
so->attrList[i].freeData = PR_FALSE;
2359
/* PZ_DestroyLock(so->attributeLock);*/
2364
* free all the data associated with an object. Object reference count must
2368
sftk_DestroyObject(SFTKObject *object)
2371
SFTKSessionObject *so = sftk_narrowToSessionObject(object);
2372
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
2374
PORT_Assert(object->refCount == 0);
2376
/* delete the database value */
2378
if (to->dbKey.data) {
2379
PORT_Free(to->dbKey.data);
2380
to->dbKey.data = NULL;
2384
sftk_DestroySessionObjectData(so);
2386
if (object->objectInfo) {
2387
(*object->infoFree)(object->objectInfo);
2388
object->objectInfo = NULL;
2389
object->infoFree = NULL;
2392
sftk_PutObjectToList(object,&sessionObjectList,PR_TRUE);
2394
sftk_PutObjectToList(object,&tokenObjectList,PR_FALSE);
2400
sftk_ReferenceObject(SFTKObject *object)
2402
PZ_Lock(object->refLock);
2404
PZ_Unlock(object->refLock);
2408
sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
2411
PRUint32 index = sftk_hash(handle, slot->tokObjHashSize);
2413
if (sftk_isToken(handle)) {
2414
return sftk_NewTokenObject(slot, NULL, handle);
2417
PZ_Lock(slot->objectLock);
2418
sftkqueue_find2(object, handle, index, slot->tokObjects);
2420
sftk_ReferenceObject(object);
2422
PZ_Unlock(slot->objectLock);
2427
* look up and object structure from a handle. OBJECT_Handles only make
2428
* sense in terms of a given session. make a reference to that object
2429
* structure returned.
2432
sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session)
2434
SFTKSlot *slot = sftk_SlotFromSession(session);
2436
return sftk_ObjectFromHandleOnSlot(handle,slot);
2441
* release a reference to an object handle
2444
sftk_FreeObject(SFTKObject *object)
2446
PRBool destroy = PR_FALSE;
2449
PZ_Lock(object->refLock);
2450
if (object->refCount == 1) destroy = PR_TRUE;
2452
PZ_Unlock(object->refLock);
2455
crv = sftk_DestroyObject(object);
2456
if (crv != CKR_OK) {
2457
return SFTK_DestroyFailure;
2459
return SFTK_Destroyed;
2465
* add an object to a slot and session queue. These two functions
2469
sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object)
2471
PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize);
2472
sftkqueue_init_element(object);
2473
PZ_Lock(slot->objectLock);
2474
sftkqueue_add2(object, object->handle, index, slot->tokObjects);
2475
PZ_Unlock(slot->objectLock);
2479
sftk_AddObject(SFTKSession *session, SFTKObject *object)
2481
SFTKSlot *slot = sftk_SlotFromSession(session);
2482
SFTKSessionObject *so = sftk_narrowToSessionObject(object);
2485
PZ_Lock(session->objectLock);
2486
sftkqueue_add(&so->sessionList,0,session->objects,0);
2487
so->session = session;
2488
PZ_Unlock(session->objectLock);
2490
sftk_AddSlotObject(slot,object);
2491
sftk_ReferenceObject(object);
2495
* add an object to a slot andsession queue
2498
sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
2500
SFTKSlot *slot = sftk_SlotFromSession(session);
2501
SFTKSessionObject *so = sftk_narrowToSessionObject(object);
2502
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
2505
NSSLOWCERTCertificate *cert;
2506
NSSLOWCERTCertTrust tmptrust;
2508
PRUint32 index = sftk_hash(object->handle, slot->tokObjHashSize);
2510
/* Handle Token case */
2511
if (so && so->session) {
2512
SFTKSession *session = so->session;
2513
PZ_Lock(session->objectLock);
2514
sftkqueue_delete(&so->sessionList,0,session->objects,0);
2515
PZ_Unlock(session->objectLock);
2516
PZ_Lock(slot->objectLock);
2517
sftkqueue_delete2(object, object->handle, index, slot->tokObjects);
2518
PZ_Unlock(slot->objectLock);
2519
sftkqueue_clear_deleted_element(object);
2520
sftk_FreeObject(object); /* reduce it's reference count */
2522
NSSLOWKEYDBHandle *keyHandle;
2523
NSSLOWCERTCertDBHandle *certHandle;
2526
/* remove the objects from the real data base */
2527
switch (object->handle & SFTK_TOKEN_TYPE_MASK) {
2528
case SFTK_TOKEN_TYPE_PRIV:
2529
case SFTK_TOKEN_TYPE_KEY:
2530
/* KEYID is the public KEY for DSA and DH, and the MODULUS for
2532
keyHandle = sftk_getKeyDB(slot);
2534
crv = CKR_TOKEN_WRITE_PROTECTED;
2537
rv = nsslowkey_DeleteKey(keyHandle, &to->dbKey);
2538
sftk_freeKeyDB(keyHandle);
2539
if (rv != SECSuccess) {
2540
crv = CKR_DEVICE_ERROR;
2543
case SFTK_TOKEN_TYPE_PUB:
2544
break; /* public keys only exist at the behest of the priv key */
2545
case SFTK_TOKEN_TYPE_CERT:
2546
certHandle = sftk_getCertDB(slot);
2548
crv = CKR_TOKEN_WRITE_PROTECTED;
2551
cert = nsslowcert_FindCertByKey(certHandle,&to->dbKey);
2552
sftk_freeCertDB(certHandle);
2554
crv = CKR_DEVICE_ERROR;
2557
rv = nsslowcert_DeletePermCertificate(cert);
2558
if (rv != SECSuccess) {
2559
crv = CKR_DEVICE_ERROR;
2561
nsslowcert_DestroyCertificate(cert);
2563
case SFTK_TOKEN_TYPE_CRL:
2564
certHandle = sftk_getCertDB(slot);
2566
crv = CKR_TOKEN_WRITE_PROTECTED;
2569
isKrl = (PRBool) (object->handle == SFTK_TOKEN_KRL_HANDLE);
2570
rv = nsslowcert_DeletePermCRL(certHandle, &to->dbKey, isKrl);
2571
sftk_freeCertDB(certHandle);
2572
if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
2574
case SFTK_TOKEN_TYPE_TRUST:
2575
certHandle = sftk_getCertDB(slot);
2577
crv = CKR_TOKEN_WRITE_PROTECTED;
2580
cert = nsslowcert_FindCertByKey(certHandle, &to->dbKey);
2582
sftk_freeCertDB(certHandle);
2583
crv = CKR_DEVICE_ERROR;
2586
tmptrust = *cert->trust;
2587
tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
2588
tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
2589
tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
2590
tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
2591
tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
2592
tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
2593
rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
2594
sftk_freeCertDB(certHandle);
2595
if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
2596
nsslowcert_DestroyCertificate(cert);
2601
sftk_tokenKeyLock(object->slot);
2602
sftk_deleteTokenKeyByHandle(object->slot,object->handle);
2603
sftk_tokenKeyUnlock(object->slot);
2609
* Token objects don't explicitly store their attributes, so we need to know
2610
* what attributes make up a particular token object before we can copy it.
2611
* below are the tables by object type.
2613
static const CK_ATTRIBUTE_TYPE commonAttrs[] = {
2614
CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE
2616
static const CK_ULONG commonAttrsCount =
2617
sizeof(commonAttrs)/sizeof(commonAttrs[0]);
2619
static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = {
2620
CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE
2622
static const CK_ULONG commonKeyAttrsCount =
2623
sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]);
2625
static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = {
2626
CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN,
2627
CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE
2629
static const CK_ULONG secretKeyAttrsCount =
2630
sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]);
2632
static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = {
2633
CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT
2635
static const CK_ULONG commonPubKeyAttrsCount =
2636
sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]);
2638
static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = {
2639
CKA_MODULUS, CKA_PUBLIC_EXPONENT
2641
static const CK_ULONG rsaPubKeyAttrsCount =
2642
sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]);
2644
static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = {
2645
CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
2647
static const CK_ULONG dsaPubKeyAttrsCount =
2648
sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]);
2650
static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = {
2651
CKA_PRIME, CKA_BASE, CKA_VALUE
2653
static const CK_ULONG dhPubKeyAttrsCount =
2654
sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]);
2655
#ifdef NSS_ENABLE_ECC
2656
static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = {
2657
CKA_EC_PARAMS, CKA_EC_POINT
2659
static const CK_ULONG ecPubKeyAttrsCount =
2660
sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]);
2663
static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
2664
CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT,
2665
CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB
2667
static const CK_ULONG commonPrivKeyAttrsCount =
2668
sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]);
2670
static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = {
2671
CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT,
2672
CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT
2674
static const CK_ULONG rsaPrivKeyAttrsCount =
2675
sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]);
2677
static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = {
2678
CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
2680
static const CK_ULONG dsaPrivKeyAttrsCount =
2681
sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]);
2683
static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = {
2684
CKA_PRIME, CKA_BASE, CKA_VALUE
2686
static const CK_ULONG dhPrivKeyAttrsCount =
2687
sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]);
2688
#ifdef NSS_ENABLE_ECC
2689
static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = {
2690
CKA_EC_PARAMS, CKA_VALUE
2692
static const CK_ULONG ecPrivKeyAttrsCount =
2693
sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]);
2696
static const CK_ATTRIBUTE_TYPE certAttrs[] = {
2697
CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER
2699
static const CK_ULONG certAttrsCount =
2700
sizeof(certAttrs)/sizeof(certAttrs[0]);
2702
static const CK_ATTRIBUTE_TYPE trustAttrs[] = {
2703
CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
2704
CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION,
2705
CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED
2707
static const CK_ULONG trustAttrsCount =
2708
sizeof(trustAttrs)/sizeof(trustAttrs[0]);
2710
static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
2711
CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE
2713
static const CK_ULONG smimeAttrsCount =
2714
sizeof(smimeAttrs)/sizeof(smimeAttrs[0]);
2716
static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
2717
CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL
2719
static const CK_ULONG crlAttrsCount =
2720
sizeof(crlAttrs)/sizeof(crlAttrs[0]);
2722
/* copy an object based on it's table */
2724
stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to,
2725
const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount)
2727
SFTKAttribute *attribute;
2728
SFTKAttribute *newAttribute;
2732
for (i=0; i < attrCount; i++) {
2733
if (!sftk_hasAttribute(destObject,attrArray[i])) {
2734
attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]);
2736
continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */
2738
/* we need to copy the attribute since each attribute
2739
* only has one set of link list pointers */
2740
newAttribute = sftk_NewAttribute( destObject,
2741
sftk_attr_expand(&attribute->attrib));
2742
sftk_FreeAttribute(attribute); /* free the old attribute */
2743
if (!newAttribute) {
2744
return CKR_HOST_MEMORY;
2746
sftk_AddAttribute(destObject,newAttribute);
2753
stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to)
2756
CK_KEY_TYPE key_type;
2757
SFTKAttribute *attribute;
2759
/* copy the common attributes for all keys first */
2760
crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
2761
commonKeyAttrsCount);
2762
if (crv != CKR_OK) {
2765
/* copy the common attributes for all private keys next */
2766
crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs,
2767
commonPrivKeyAttrsCount);
2768
if (crv != CKR_OK) {
2771
attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
2772
PORT_Assert(attribute); /* if it wasn't here, ww should have failed
2773
* copying the common attributes */
2775
/* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
2776
* the fact is, the only reason we couldn't get the attribute would
2777
* be a memory error or database error (an error in the 'device').
2778
* if we have a database error code, we could return it here */
2779
crv = CKR_DEVICE_ERROR;
2782
key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
2783
sftk_FreeAttribute(attribute);
2785
/* finally copy the attributes for various private key types */
2788
crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs,
2789
rsaPrivKeyAttrsCount);
2792
crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs,
2793
dsaPrivKeyAttrsCount);
2796
crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs,
2797
dhPrivKeyAttrsCount);
2799
#ifdef NSS_ENABLE_ECC
2801
crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs,
2802
ecPrivKeyAttrsCount);
2806
crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
2807
* of token keys into our database. */
2814
stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to)
2817
CK_KEY_TYPE key_type;
2818
SFTKAttribute *attribute;
2820
/* copy the common attributes for all keys first */
2821
crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
2822
commonKeyAttrsCount);
2823
if (crv != CKR_OK) {
2827
/* copy the common attributes for all public keys next */
2828
crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs,
2829
commonPubKeyAttrsCount);
2830
if (crv != CKR_OK) {
2833
attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
2834
PORT_Assert(attribute); /* if it wasn't here, ww should have failed
2835
* copying the common attributes */
2837
/* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
2838
* the fact is, the only reason we couldn't get the attribute would
2839
* be a memory error or database error (an error in the 'device').
2840
* if we have a database error code, we could return it here */
2841
crv = CKR_DEVICE_ERROR;
2844
key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
2845
sftk_FreeAttribute(attribute);
2847
/* finally copy the attributes for various public key types */
2850
crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs,
2851
rsaPubKeyAttrsCount);
2854
crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs,
2855
dsaPubKeyAttrsCount);
2858
crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs,
2859
dhPubKeyAttrsCount);
2861
#ifdef NSS_ENABLE_ECC
2863
crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs,
2864
ecPubKeyAttrsCount);
2868
crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
2869
* of token keys into our database. */
2875
stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to)
2878
crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
2879
commonKeyAttrsCount);
2880
if (crv != CKR_OK) {
2883
crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs,
2884
secretKeyAttrsCount);
2890
* Copy a token object. We need to explicitly copy the relevant
2891
* attributes since token objects don't store those attributes in
2895
sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject)
2897
SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject);
2900
PORT_Assert(src_to);
2901
if (src_to == NULL) {
2902
return CKR_DEVICE_ERROR; /* internal state inconsistant */
2905
crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs,
2907
if (crv != CKR_OK) {
2910
switch (src_to->obj.objclass) {
2911
case CKO_CERTIFICATE:
2912
crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
2915
case CKO_NETSCAPE_TRUST:
2916
crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
2919
case CKO_NETSCAPE_SMIME:
2920
crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
2923
case CKO_NETSCAPE_CRL:
2924
crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
2927
case CKO_PRIVATE_KEY:
2928
crv = stfk_CopyTokenPrivateKey(destObject,src_to);
2930
case CKO_PUBLIC_KEY:
2931
crv = stfk_CopyTokenPublicKey(destObject,src_to);
2933
case CKO_SECRET_KEY:
2934
crv = stfk_CopyTokenSecretKey(destObject,src_to);
2937
crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
2938
* of token keys into our database. */
2945
* copy the attributes from one object to another. Don't overwrite existing
2946
* attributes. NOTE: This is a pretty expensive operation since it
2947
* grabs the attribute locks for the src object for a *long* time.
2950
sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject)
2952
SFTKAttribute *attribute;
2953
SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
2956
if (src_so == NULL) {
2957
return sftk_CopyTokenObject(destObject,srcObject);
2960
PZ_Lock(src_so->attributeLock);
2961
for(i=0; i < src_so->hashSize; i++) {
2962
attribute = src_so->head[i];
2965
if (!sftk_hasAttribute(destObject,attribute->handle)) {
2966
/* we need to copy the attribute since each attribute
2967
* only has one set of link list pointers */
2968
SFTKAttribute *newAttribute = sftk_NewAttribute(
2969
destObject,sftk_attr_expand(&attribute->attrib));
2970
if (newAttribute == NULL) {
2971
PZ_Unlock(src_so->attributeLock);
2972
return CKR_HOST_MEMORY;
2974
sftk_AddAttribute(destObject,newAttribute);
2976
attribute=attribute->next;
2978
} while (attribute != NULL);
2980
PZ_Unlock(src_so->attributeLock);
2986
* ******************** Search Utilities *******************************
2989
/* add an object to a search list */
2991
AddToList(SFTKObjectListElement **list,SFTKObject *object)
2993
SFTKObjectListElement *newElem =
2994
(SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement));
2996
if (newElem == NULL) return CKR_HOST_MEMORY;
2998
newElem->next = *list;
2999
newElem->object = object;
3000
sftk_ReferenceObject(object);
3007
/* return true if the object matches the template */
3009
sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count)
3013
for (i=0; i < count; i++) {
3014
SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type);
3015
if (attribute == NULL) {
3018
if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
3019
if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
3020
theTemplate[i].ulValueLen) == 0) {
3021
sftk_FreeAttribute(attribute);
3025
sftk_FreeAttribute(attribute);
3031
/* search through all the objects in the queue and return the template matches
3032
* in the object list.
3035
sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head,
3036
unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate,
3037
int count, PRBool isLoggedIn)
3043
for(i=0; i < size; i++) {
3044
/* We need to hold the lock to copy a consistant version of
3045
* the linked list. */
3047
for (object = head[i]; object != NULL; object= object->next) {
3048
if (sftk_objectMatch(object,theTemplate,count)) {
3049
/* don't return objects that aren't yet visible */
3050
if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue;
3051
sftk_addHandle(search,object->handle);
3060
* free a single list element. Return the Next object in the list.
3062
SFTKObjectListElement *
3063
sftk_FreeObjectListElement(SFTKObjectListElement *objectList)
3065
SFTKObjectListElement *ol = objectList->next;
3067
sftk_FreeObject(objectList->object);
3068
PORT_Free(objectList);
3072
/* free an entire object list */
3074
sftk_FreeObjectList(SFTKObjectListElement *objectList)
3076
SFTKObjectListElement *ol;
3078
for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {}
3082
* free a search structure
3085
sftk_FreeSearch(SFTKSearchResults *search)
3087
if (search->handles) {
3088
PORT_Free(search->handles);
3094
* ******************** Session Utilities *******************************
3097
/* update the sessions state based in it's flags and wether or not it's
3100
sftk_update_state(SFTKSlot *slot,SFTKSession *session)
3102
if (slot->isLoggedIn) {
3103
if (slot->ssoLoggedIn) {
3104
session->info.state = CKS_RW_SO_FUNCTIONS;
3105
} else if (session->info.flags & CKF_RW_SESSION) {
3106
session->info.state = CKS_RW_USER_FUNCTIONS;
3108
session->info.state = CKS_RO_USER_FUNCTIONS;
3111
if (session->info.flags & CKF_RW_SESSION) {
3112
session->info.state = CKS_RW_PUBLIC_SESSION;
3114
session->info.state = CKS_RO_PUBLIC_SESSION;
3119
/* update the state of all the sessions on a slot */
3121
sftk_update_all_states(SFTKSlot *slot)
3124
SFTKSession *session;
3126
for (i=0; i < slot->sessHashSize; i++) {
3127
PZLock *lock = SFTK_SESSION_LOCK(slot,i);
3129
for (session = slot->head[i]; session; session = session->next) {
3130
sftk_update_state(slot,session);
3137
* context are cipher and digest contexts that are associated with a session
3140
sftk_FreeContext(SFTKSessionContext *context)
3142
if (context->cipherInfo) {
3143
(*context->destroy)(context->cipherInfo,PR_TRUE);
3145
if (context->hashInfo) {
3146
(*context->hashdestroy)(context->hashInfo,PR_TRUE);
3149
sftk_FreeObject(context->key);
3150
context->key = NULL;
3156
* create a new nession. NOTE: The session handle is not set, and the
3157
* session is not added to the slot's session queue.
3160
sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
3163
SFTKSession *session;
3164
SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
3166
if (slot == NULL) return NULL;
3168
session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession));
3169
if (session == NULL) return NULL;
3171
session->next = session->prev = NULL;
3172
session->refCount = 1;
3173
session->enc_context = NULL;
3174
session->hash_context = NULL;
3175
session->sign_context = NULL;
3176
session->search = NULL;
3177
session->objectIDCount = 1;
3178
session->objectLock = PZ_NewLock(nssILockObject);
3179
if (session->objectLock == NULL) {
3183
session->objects[0] = NULL;
3185
session->slot = slot;
3186
session->notify = notify;
3187
session->appData = pApplication;
3188
session->info.flags = flags;
3189
session->info.slotID = slotID;
3190
session->info.ulDeviceError = 0;
3191
sftk_update_state(slot,session);
3196
/* free all the data associated with a session. */
3198
sftk_DestroySession(SFTKSession *session)
3200
SFTKObjectList *op,*next;
3201
PORT_Assert(session->refCount == 0);
3203
/* clean out the attributes */
3204
/* since no one is referencing us, it's safe to walk the chain
3206
for (op = session->objects[0]; op != NULL; op = next) {
3209
op->next = op->prev = NULL;
3210
sftk_DeleteObject(session,op->parent);
3212
PZ_DestroyLock(session->objectLock);
3213
if (session->enc_context) {
3214
sftk_FreeContext(session->enc_context);
3216
if (session->hash_context) {
3217
sftk_FreeContext(session->hash_context);
3219
if (session->sign_context) {
3220
sftk_FreeContext(session->sign_context);
3222
if (session->search) {
3223
sftk_FreeSearch(session->search);
3230
* look up a session structure from a session handle
3231
* generate a reference to it.
3234
sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
3236
SFTKSlot *slot = sftk_SlotFromSessionHandle(handle);
3237
SFTKSession *session;
3240
if (!slot) return NULL;
3241
lock = SFTK_SESSION_LOCK(slot,handle);
3244
sftkqueue_find(session,handle,slot->head,slot->sessHashSize);
3245
if (session) session->refCount++;
3252
* release a reference to a session handle
3255
sftk_FreeSession(SFTKSession *session)
3257
PRBool destroy = PR_FALSE;
3258
SFTKSlot *slot = sftk_SlotFromSession(session);
3259
PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle);
3262
if (session->refCount == 1) destroy = PR_TRUE;
3263
session->refCount--;
3266
if (destroy) sftk_DestroySession(session);
3269
* handle Token Object stuff
3272
sftk_XORHash(unsigned char *key, unsigned char *dbkey, int len)
3276
PORT_Memset(key, 0, 4);
3278
for (i=0; i < len-4; i += 4) {
3280
key[1] ^= dbkey[i+1];
3281
key[2] ^= dbkey[i+2];
3282
key[3] ^= dbkey[i+3];
3286
/* Make a token handle for an object and record it so we can find it again */
3288
sftk_mkHandle(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
3290
unsigned char hashBuf[4];
3291
CK_OBJECT_HANDLE handle;
3295
/* there is only one KRL, use a fixed handle for it */
3296
if (handle != SFTK_TOKEN_KRL_HANDLE) {
3297
sftk_XORHash(hashBuf,dbKey->data,dbKey->len);
3298
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
3299
(hashBuf[2] << 8) | hashBuf[3];
3300
handle = SFTK_TOKEN_MAGIC | class |
3301
(handle & ~(SFTK_TOKEN_TYPE_MASK|SFTK_TOKEN_MASK));
3302
/* we have a CRL who's handle has randomly matched the reserved KRL
3303
* handle, increment it */
3304
if (handle == SFTK_TOKEN_KRL_HANDLE) {
3309
sftk_tokenKeyLock(slot);
3310
while ((key = sftk_lookupTokenKeyByHandle(slot,handle)) != NULL) {
3311
if (SECITEM_ItemsAreEqual(key,dbKey)) {
3312
sftk_tokenKeyUnlock(slot);
3317
sftk_addTokenKeyByHandle(slot,handle,dbKey);
3318
sftk_tokenKeyUnlock(slot);
3323
sftk_poisonHandle(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
3325
unsigned char hashBuf[4];
3326
CK_OBJECT_HANDLE handle;
3330
/* there is only one KRL, use a fixed handle for it */
3331
if (handle != SFTK_TOKEN_KRL_HANDLE) {
3332
sftk_XORHash(hashBuf,dbKey->data,dbKey->len);
3333
handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
3334
(hashBuf[2] << 8) | hashBuf[3];
3335
handle = SFTK_TOKEN_MAGIC | class |
3336
(handle & ~(SFTK_TOKEN_TYPE_MASK|SFTK_TOKEN_MASK));
3337
/* we have a CRL who's handle has randomly matched the reserved KRL
3338
* handle, increment it */
3339
if (handle == SFTK_TOKEN_KRL_HANDLE) {
3343
sftk_tokenKeyLock(slot);
3344
while ((key = sftk_lookupTokenKeyByHandle(slot,handle)) != NULL) {
3345
if (SECITEM_ItemsAreEqual(key,dbKey)) {
3346
key->data[0] ^= 0x80;
3347
sftk_tokenKeyUnlock(slot);
3352
sftk_tokenKeyUnlock(slot);
3357
sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
3359
if (search->handles == NULL) {
3362
if (search->size >= search->array_size) {
3363
search->array_size += NSC_SEARCH_BLOCK_SIZE;
3364
search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
3365
sizeof(CK_OBJECT_HANDLE)* search->array_size);
3366
if (search->handles == NULL) {
3370
search->handles[search->size] = handle;
3374
static const CK_OBJECT_HANDLE sftk_classArray[] = {
3375
0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
3376
CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME,
3379
#define handleToClass(handle) \
3380
sftk_classArray[((handle & SFTK_TOKEN_TYPE_MASK))>>28]
3383
sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
3385
SFTKObject *object = NULL;
3386
SFTKTokenObject *tokObject = NULL;
3387
PRBool hasLocks = PR_FALSE;
3390
object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0,
3392
if (object == NULL) {
3395
tokObject = (SFTKTokenObject *) object;
3397
object->objclass = handleToClass(handle);
3398
object->handle = handle;
3399
object->slot = slot;
3400
object->objectInfo = NULL;
3401
object->infoFree = NULL;
3402
if (dbKey == NULL) {
3403
sftk_tokenKeyLock(slot);
3404
dbKey = sftk_lookupTokenKeyByHandle(slot,handle);
3405
if (dbKey == NULL) {
3406
sftk_tokenKeyUnlock(slot);
3409
rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
3410
sftk_tokenKeyUnlock(slot);
3412
rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
3414
if (rv != SECSuccess) {
3418
object->refLock = PZ_NewLock(nssILockRefLock);
3420
if (object->refLock == NULL) {
3423
object->refCount = 1;
3428
(void) sftk_DestroyObject(object);
3435
sftk_tokenMatch(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
3436
CK_ATTRIBUTE_PTR theTemplate,int count)
3441
object = sftk_NewTokenObject(slot,dbKey,SFTK_TOKEN_MASK|class);
3442
if (object == NULL) {
3446
ret = sftk_objectMatch(object,theTemplate,count);
3447
sftk_FreeObject(object);
3452
sftk_convertSessionToToken(SFTKObject *obj)
3455
SFTKSessionObject *so = (SFTKSessionObject *)obj;
3456
SFTKTokenObject *to = sftk_narrowToTokenObject(obj);
3459
sftk_DestroySessionObjectData(so);
3460
PZ_DestroyLock(so->attributeLock);
3464
sftk_tokenKeyLock(so->obj.slot);
3465
key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle);
3467
sftk_tokenKeyUnlock(so->obj.slot);
3470
rv = SECITEM_CopyItem(NULL,&to->dbKey,key);
3471
sftk_tokenKeyUnlock(so->obj.slot);
3472
if (rv == SECFailure) {
3481
sftk_narrowToSessionObject(SFTKObject *obj)
3483
return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL;
3487
sftk_narrowToTokenObject(SFTKObject *obj)
3489
return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL;