summaryrefslogtreecommitdiff
path: root/security/nss/lib/softoken/pkcs11u.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/softoken/pkcs11u.c')
-rw-r--r--security/nss/lib/softoken/pkcs11u.c1697
1 files changed, 1469 insertions, 228 deletions
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index 0aa42823a..1c8cd821a 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -35,18 +35,10 @@
*/
#include "pkcs11.h"
#include "pkcs11i.h"
-#include "key.h"
-#include "keylow.h"
-#include "certdb.h"
-
-
-/* declare the internal pkcs11 slot structures:
- * There are threee:
- * slot 0 is the generic crypto service token.
- * slot 1 is the Database service token.
- * slot 2 is the FIPS token (both generic and database).
- */
-static PK11Slot pk11_slot[3];
+#include "pcertt.h"
+#include "lowkeyi.h"
+#include "pcert.h"
+#include "secasn1.h"
/*
* ******************** Attribute Utilities *******************************
@@ -62,27 +54,36 @@ pk11_NewAttribute(PK11Object *object,
{
PK11Attribute *attribute;
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
int index;
+
+ if (so == NULL) {
+ /* allocate new attribute in a buffer */
+ PORT_Assert(0);
+ }
/*
- * NO_ARENA attempts to keep down contention on Malloc and Arena locks
+ * PKCS11_STATIC_ATTRIBUTES attempts to keep down contention on Malloc and Arena locks
* by limiting the number of these calls on high traversed paths. this
* is done for attributes by 'allocating' them from a pool already allocated
* by the parent object.
*/
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- index = object->nextAttr++;
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11_USE_THREADS(PZ_Lock(so->attributeLock);)
+ index = so->nextAttr++;
+ PK11_USE_THREADS(PZ_Unlock(so->attributeLock);)
PORT_Assert(index < MAX_OBJS_ATTRS);
if (index >= MAX_OBJS_ATTRS) return NULL;
- attribute = &object->attrList[index];
+ attribute = &so->attrList[index];
attribute->attrib.type = type;
+ attribute->freeAttr = PR_FALSE;
+ attribute->freeData = PR_FALSE;
if (value) {
if (len <= ATTR_SPACE) {
attribute->attrib.pValue = attribute->space;
} else {
attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
}
if (attribute->attrib.pValue == NULL) {
return NULL;
@@ -94,23 +95,27 @@ pk11_NewAttribute(PK11Object *object,
attribute->attrib.ulValueLen = 0;
}
#else
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
+ attribute->freeAttr = PR_TRUE;
#else
attribute = (PK11Attribute*)PORT_ArenaAlloc(object->arena,sizeof(PK11Attribute));
-#endif /* REF_COUNT_ATTRIBUTE */
+ attribute->freeAttr = PR_FALSE;
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
if (attribute == NULL) return NULL;
+ attribute->freeData = PR_FALSE;
if (value) {
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
#else
attribute->attrib.pValue = PORT_ArenaAlloc(object->arena,len);
-#endif /* REF_COUNT_ATTRIBUTE */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
if (attribute->attrib.pValue == NULL) {
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
PORT_Free(attribute);
-#endif /* REF_COUNT_ATTRIBUTE */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
return NULL;
}
PORT_Memcpy(attribute->attrib.pValue,value,len);
@@ -119,11 +124,11 @@ pk11_NewAttribute(PK11Object *object,
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
-#endif /* NO_ARENA */
+#endif /* PKCS11_STATIC_ATTRIBUTES */
attribute->attrib.type = type;
attribute->handle = type;
attribute->next = attribute->prev = NULL;
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
attribute->refCount = 1;
#ifdef PKCS11_USE_THREADS
attribute->refLock = PZ_NewLock(nssILockRefLock);
@@ -135,31 +140,893 @@ pk11_NewAttribute(PK11Object *object,
#else
attribute->refLock = NULL;
#endif
-#endif /* REF_COUNT_ATTRIBUTE */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
+ return attribute;
+}
+
+static PK11Attribute *
+pk11_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
+ CK_ULONG len, PRBool copy)
+{
+ PK11Attribute *attribute;
+
+ attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
+
+ if (attribute == NULL) return NULL;
+ attribute->attrib.type = type;
+ attribute->handle = type;
+ attribute->next = attribute->prev = NULL;
+ attribute->freeAttr = PR_TRUE;
+ attribute->freeData = PR_FALSE;
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ attribute->refCount = 1;
+#ifdef PKCS11_USE_THREADS
+ attribute->refLock = PZ_NewLock(nssILockRefLock);
+ if (attribute->refLock == NULL) {
+ PORT_Free(attribute);
+ return NULL;
+ }
+#else
+ attribute->refLock = NULL;
+#endif
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
+ attribute->attrib.type = type;
+ if (!copy) {
+ attribute->attrib.pValue = value;
+ attribute->attrib.ulValueLen = len;
+ return attribute;
+ }
+
+ if (value) {
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ if (len <= ATTR_SPACE) {
+ attribute->attrib.pValue = attribute->space;
+ } else {
+ attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
+ }
+#else
+ attribute->attrib.pValue = PORT_Alloc(len);
+ attribute->freeData = PR_TRUE;
+#endif
+ if (attribute->attrib.pValue == NULL) {
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ if (attribute->refLock) {
+ PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);)
+ }
+#endif
+ PORT_Free(attribute);
+ return NULL;
+ }
+ PORT_Memcpy(attribute->attrib.pValue,value,len);
+ attribute->attrib.ulValueLen = len;
+ } else {
+ attribute->attrib.pValue = NULL;
+ attribute->attrib.ulValueLen = 0;
+ }
return attribute;
}
+static PK11Attribute *
+pk11_NewTokenAttributeSigned(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value,
+ CK_ULONG len, PRBool copy)
+{
+ unsigned char * dval = (unsigned char *)value;
+ if (*dval == 0) {
+ dval++;
+ len--;
+ }
+ return pk11_NewTokenAttribute(type,dval,len,copy);
+}
+
/*
* Free up all the memory associated with an attribute. Reference count
* must be zero to call this.
*/
-#ifdef REF_COUNT_ATTRIBUTE
static void
pk11_DestroyAttribute(PK11Attribute *attribute)
{
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
PORT_Assert(attribute->refCount == 0);
PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);)
- if (attribute->attrib.pValue) {
- /* clear out the data in the attribute value... it may have been
- * sensitive data */
- PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
- PORT_Free(attribute->attrib.pValue);
+#endif
+ if (attribute->freeData) {
+ if (attribute->attrib.pValue) {
+ /* clear out the data in the attribute value... it may have been
+ * sensitive data */
+ PORT_Memset(attribute->attrib.pValue, 0,
+ attribute->attrib.ulValueLen);
+ }
+ PORT_Free(attribute->attrib.pValue);
}
PORT_Free(attribute);
}
+
+/*
+ * release a reference to an attribute structure
+ */
+void
+pk11_FreeAttribute(PK11Attribute *attribute)
+{
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ PRBool destroy = PR_FALSE;
#endif
+
+ if (attribute->freeAttr) {
+ pk11_DestroyAttribute(attribute);
+ return;
+ }
+
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ PK11_USE_THREADS(PZ_Lock(attribute->refLock);)
+ if (attribute->refCount == 1) destroy = PR_TRUE;
+ attribute->refCount--;
+ PK11_USE_THREADS(PZ_Unlock(attribute->refLock);)
+
+ if (destroy) pk11_DestroyAttribute(attribute);
+#endif
+}
+
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+#define PK11_DEF_ATTRIBUTE(value,len) \
+ { NULL, NULL, PR_FALSE, PR_FALSE, 1, NULL, 0, { 0, value, len } }
+
+#else
+#define PK11_DEF_ATTRIBUTE(value,len) \
+ { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } }
+#endif
+
+CK_BBOOL pk11_staticTrueValue = CK_TRUE;
+CK_BBOOL pk11_staticFalseValue = CK_FALSE;
+static const PK11Attribute pk11_StaticTrueAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrueValue,sizeof(pk11_staticTrueValue));
+static const PK11Attribute pk11_StaticFalseAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticFalseValue,sizeof(pk11_staticFalseValue));
+static const PK11Attribute pk11_StaticNullAttr = PK11_DEF_ATTRIBUTE(NULL,0);
+
+CK_CERTIFICATE_TYPE pk11_staticX509Value = CKC_X_509;
+static const PK11Attribute pk11_StaticX509Attr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticX509Value, sizeof(pk11_staticX509Value));
+CK_TRUST pk11_staticTrustedValue = CKT_NETSCAPE_TRUSTED;
+CK_TRUST pk11_staticTrustedDelegatorValue = CKT_NETSCAPE_TRUSTED_DELEGATOR;
+CK_TRUST pk11_staticUnTrustedValue = CKT_NETSCAPE_UNTRUSTED;
+CK_TRUST pk11_staticTrustUnknownValue = CKT_NETSCAPE_TRUST_UNKNOWN;
+CK_TRUST pk11_staticMustVerifyValue = CKT_NETSCAPE_MUST_VERIFY;
+static const PK11Attribute pk11_StaticTrustedAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrustedValue,
+ sizeof(pk11_staticTrustedValue));
+static const PK11Attribute pk11_StaticTrustedDelegatorAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrustedDelegatorValue,
+ sizeof(pk11_staticTrustedDelegatorValue));
+static const PK11Attribute pk11_StaticUnTrustedAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticUnTrustedValue,
+ sizeof(pk11_staticUnTrustedValue));
+static const PK11Attribute pk11_StaticTrustUnknownAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticTrustUnknownValue,
+ sizeof(pk11_staticTrustUnknownValue));
+static const PK11Attribute pk11_StaticMustVerifyAttr =
+ PK11_DEF_ATTRIBUTE(&pk11_staticMustVerifyValue,
+ sizeof(pk11_staticMustVerifyValue));
+
+static void pk11_FreeItem(SECItem *item)
+{
+ SECITEM_FreeItem(item, PR_TRUE);
+}
+
+static certDBEntrySMime *
+pk11_getSMime(PK11TokenObject *object)
+{
+ certDBEntrySMime *entry;
+
+ if (object->obj.objclass != CKO_NETSCAPE_SMIME) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (certDBEntrySMime *)object->obj.objectInfo;
+ }
+
+ entry = nsslowcert_ReadDBSMimeEntry(object->obj.slot->certDB,
+ (char *)object->dbKey.data);
+ object->obj.objectInfo = (void *)entry;
+ object->obj.infoFree = (PK11Free) nsslowcert_DestroyDBEntry;
+ return entry;
+}
+
+static SECItem *
+pk11_getCrl(PK11TokenObject *object)
+{
+ SECItem *crl;
+ PRBool isKrl;
+
+ if (object->obj.objclass != CKO_NETSCAPE_CRL) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (SECItem *)object->obj.objectInfo;
+ }
+
+ isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE;
+ crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey,
+ NULL,isKrl);
+ object->obj.objectInfo = (void *)crl;
+ object->obj.infoFree = (PK11Free) pk11_FreeItem;
+ return crl;
+}
+
+static char *
+pk11_getUrl(PK11TokenObject *object)
+{
+ SECItem *crl;
+ PRBool isKrl;
+ char *url = NULL;
+
+ if (object->obj.objclass != CKO_NETSCAPE_CRL) {
+ return NULL;
+ }
+
+ isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE;
+ crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey,
+ &url,isKrl);
+ if (object->obj.objectInfo == NULL) {
+ object->obj.objectInfo = (void *)crl;
+ object->obj.infoFree = (PK11Free) pk11_FreeItem;
+ } else {
+ if (crl) SECITEM_FreeItem(crl,PR_TRUE);
+ }
+ return url;
+}
+
+static NSSLOWCERTCertificate *
+pk11_getCert(PK11TokenObject *object)
+{
+ NSSLOWCERTCertificate *cert;
+
+ if ((object->obj.objclass != CKO_CERTIFICATE) &&
+ (object->obj.objclass != CKO_NETSCAPE_TRUST)) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (NSSLOWCERTCertificate *)object->obj.objectInfo;
+ }
+ cert = nsslowcert_FindCertByKey(object->obj.slot->certDB,&object->dbKey);
+ object->obj.objectInfo = (void *)cert;
+ object->obj.infoFree = (PK11Free) nsslowcert_DestroyCertificate ;
+ return cert;
+}
+
+static NSSLOWKEYPublicKey *
+pk11_GetPublicKey(PK11TokenObject *object)
+{
+ NSSLOWKEYPublicKey *pubKey;
+ NSSLOWKEYPrivateKey *privKey;
+
+ if (object->obj.objclass != CKO_PUBLIC_KEY) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (NSSLOWKEYPublicKey *)object->obj.objectInfo;
+ }
+ privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB,
+ &object->dbKey, object->obj.slot->password);
+ pubKey = nsslowkey_ConvertToPublicKey(privKey);
+ nsslowkey_DestroyPrivateKey(privKey);
+ object->obj.objectInfo = (void *) pubKey;
+ object->obj.infoFree = (PK11Free) nsslowkey_DestroyPublicKey ;
+ return pubKey;
+}
+
+static NSSLOWKEYPrivateKey *
+pk11_GetPrivateKey(PK11TokenObject *object)
+{
+ NSSLOWKEYPrivateKey *privKey;
+
+ if ((object->obj.objclass != CKO_PRIVATE_KEY) &&
+ (object->obj.objclass != CKO_SECRET_KEY)) {
+ return NULL;
+ }
+ if (object->obj.objectInfo) {
+ return (NSSLOWKEYPrivateKey *)object->obj.objectInfo;
+ }
+ privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB,
+ &object->dbKey, object->obj.slot->password);
+ object->obj.objectInfo = (void *) privKey;
+ object->obj.infoFree = (PK11Free) nsslowkey_DestroyPrivateKey ;
+ return privKey;
+}
+
+/* pk11_GetPubItem returns data associated with the public key.
+ * one only needs to free the public key. This comment is here
+ * because this sematic would be non-obvious otherwise. All callers
+ * should include this comment.
+ */
+static SECItem *
+pk11_GetPubItem(NSSLOWKEYPublicKey *pubKey) {
+ SECItem *pubItem = NULL;
+ /* get value to compare from the cert's public key */
+ switch ( pubKey->keyType ) {
+ case NSSLOWKEYRSAKey:
+ pubItem = &pubKey->u.rsa.modulus;
+ break;
+ case NSSLOWKEYDSAKey:
+ pubItem = &pubKey->u.dsa.publicValue;
+ break;
+ case NSSLOWKEYDHKey:
+ pubItem = &pubKey->u.dh.publicValue;
+ break;
+ default:
+ break;
+ }
+ return pubItem;
+}
+
+static const SEC_ASN1Template pk11_SerialTemplate[] = {
+ { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
+ { 0 }
+};
+
+static PK11Attribute *
+pk11_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_RSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ default:
+ case CKA_MODULUS:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
+ key->u.rsa.modulus.len, PR_FALSE);
+ case CKA_PUBLIC_EXPONENT:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len, PR_FALSE);
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ case CKA_ENCRYPT:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VERIFY:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_VALUE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len, PR_FALSE);
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
+ key->u.dsa.params.prime.len, PR_FALSE);
+ case CKA_SUBPRIME:
+ return pk11_NewTokenAttributeSigned(type,
+ key->u.dsa.params.subPrime.data,
+ key->u.dsa.params.subPrime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
+ key->u.dsa.params.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DH;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_ENCRYPT:
+ case CKA_VERIFY:
+ case CKA_VERIFY_RECOVER:
+ case CKA_WRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VALUE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.publicValue.data,
+ key->u.dh.publicValue.len, PR_FALSE);
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data,
+ key->u.dh.prime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data,
+ key->u.dh.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWKEYPublicKey *key;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_NEVER_EXTRACTABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_MODIFIABLE:
+ case CKA_EXTRACTABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ default:
+ break;
+ }
+
+ key = pk11_GetPublicKey(object);
+ if (key == NULL) {
+ return NULL;
+ }
+ switch (key->keyType) {
+ case NSSLOWKEYRSAKey:
+ return pk11_FindRSAPublicKeyAttribute(key,type);
+ case NSSLOWKEYDSAKey:
+ return pk11_FindDSAPublicKeyAttribute(key,type);
+ case NSSLOWKEYDHKey:
+ return pk11_FindDHPublicKeyAttribute(key,type);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWKEYPrivateKey *key;
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_DERIVE:
+ case CKA_ENCRYPT:
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_VERIFY:
+ case CKA_WRAP:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_NEVER_EXTRACTABLE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VALUE:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ default:
+ break;
+ }
+
+ key = pk11_GetPrivateKey(object);
+ if (key == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,key->u.rsa.coefficient.data,
+ key->u.rsa.coefficient.len, PR_FALSE);
+ case CKA_VALUE:
+ return pk11_NewTokenAttribute(type,key->u.rsa.privateExponent.data,
+ key->u.rsa.privateExponent.len, PR_FALSE);
+ }
+
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
+ CK_ATTRIBUTE_TYPE type)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_RSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_MODULUS:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data,
+ key->u.rsa.modulus.len, PR_FALSE);
+ case CKA_PUBLIC_EXPONENT:
+ return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len, PR_FALSE);
+ case CKA_PRIVATE_EXPONENT:
+ case CKA_PRIME_1:
+ case CKA_PRIME_2:
+ case CKA_EXPONENT_1:
+ case CKA_EXPONENT_2:
+ case CKA_COEFFICIENT:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key,
+ CK_ATTRIBUTE_TYPE type)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DSA;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
+ key->u.dsa.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ case CKA_DECRYPT:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_SIGN:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_VALUE:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data,
+ key->u.dsa.params.prime.len, PR_FALSE);
+ case CKA_SUBPRIME:
+ return pk11_NewTokenAttributeSigned(type,
+ key->u.dsa.params.subPrime.data,
+ key->u.dsa.params.subPrime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data,
+ key->u.dsa.params.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
+{
+ unsigned char hash[SHA1_LENGTH];
+ CK_KEY_TYPE keyType = CKK_DH;
+
+ switch (type) {
+ case CKA_KEY_TYPE:
+ return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE);
+ case CKA_ID:
+ SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_DERIVE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_DECRYPT:
+ case CKA_SIGN:
+ case CKA_SIGN_RECOVER:
+ case CKA_UNWRAP:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_VALUE:
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ case CKA_PRIME:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data,
+ key->u.dh.prime.len, PR_FALSE);
+ case CKA_BASE:
+ return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data,
+ key->u.dh.base.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWKEYPrivateKey *key;
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_SENSITIVE:
+ case CKA_ALWAYS_SENSITIVE:
+ case CKA_EXTRACTABLE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_NEVER_EXTRACTABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ default:
+ break;
+ }
+ key = pk11_GetPrivateKey(object);
+ if (key == NULL) {
+ return NULL;
+ }
+ switch (key->keyType) {
+ case NSSLOWKEYRSAKey:
+ return pk11_FindRSAPrivateKeyAttribute(key,type);
+ case NSSLOWKEYDSAKey:
+ return pk11_FindDSAPrivateKeyAttribute(key,type);
+ case NSSLOWKEYDHKey:
+ return pk11_FindDHPrivateKeyAttribute(key,type);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindSMIMEAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ certDBEntrySMime *entry;
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_NETSCAPE_EMAIL:
+ return pk11_NewTokenAttribute(type,object->dbKey.data,
+ object->dbKey.len, PR_FALSE);
+ default:
+ break;
+ }
+ entry = pk11_getSMime(object);
+ if (entry == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_NETSCAPE_SMIME_TIMESTAMP:
+ return pk11_NewTokenAttribute(type,entry->optionsDate.data,
+ entry->optionsDate.len, PR_FALSE);
+ case CKA_SUBJECT:
+ return pk11_NewTokenAttribute(type,entry->subjectName.data,
+ entry->subjectName.len, PR_FALSE);
+ case CKA_VALUE:
+ return pk11_NewTokenAttribute(type,entry->smimeOptions.data,
+ entry->smimeOptions.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindTrustAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWCERTCertificate *cert;
+ unsigned char hash[SHA1_LENGTH];
+ SECItem *item;
+ PK11Attribute *attr;
+ unsigned int trustFlags;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ default:
+ break;
+ }
+ cert = pk11_getCert(object);
+ if (cert == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_CERT_SHA1_HASH:
+ SHA1_HashBuf(hash,cert->derCert.data,cert->derCert.len);
+ return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE);
+ case CKA_CERT_MD5_HASH:
+ MD5_HashBuf(hash,cert->derCert.data,cert->derCert.len);
+ return pk11_NewTokenAttribute(type,hash,MD5_LENGTH, PR_TRUE);
+ case CKA_ISSUER:
+ return pk11_NewTokenAttribute(type,cert->derIssuer.data,
+ cert->derIssuer.len, PR_FALSE);
+ case CKA_SERIAL_NUMBER:
+ item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate);
+ if (item == NULL) break;
+ attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
+ SECITEM_FreeItem(item,PR_TRUE);
+ return attr;
+ case CKA_TRUST_CLIENT_AUTH:
+ trustFlags = cert->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
+ cert->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
+ goto trust;
+ case CKA_TRUST_SERVER_AUTH:
+ trustFlags = cert->trust->sslFlags;
+ goto trust;
+ case CKA_TRUST_EMAIL_PROTECTION:
+ trustFlags = cert->trust->emailFlags;
+ goto trust;
+ case CKA_TRUST_CODE_SIGNING:
+ trustFlags = cert->trust->objectSigningFlags;
+trust:
+ if (trustFlags & CERTDB_TRUSTED_CA ) {
+ return (PK11Attribute *)&pk11_StaticTrustedDelegatorAttr;
+ }
+ if (trustFlags & CERTDB_TRUSTED) {
+ return (PK11Attribute *)&pk11_StaticTrustedAttr;
+ }
+ if (trustFlags & CERTDB_NOT_TRUSTED) {
+ return (PK11Attribute *)&pk11_StaticUnTrustedAttr;
+ }
+ if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
+ return (PK11Attribute *)&pk11_StaticTrustUnknownAttr;
+ }
+ return (PK11Attribute *)&pk11_StaticMustVerifyAttr;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindCrlAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ SECItem *crl;
+ char *url;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_NETSCAPE_KRL:
+ return (PK11Attribute *) ((object->obj.handle == PK11_TOKEN_KRL_HANDLE)
+ ? &pk11_StaticTrueAttr : &pk11_StaticFalseAttr);
+ case CKA_NETSCAPE_URL:
+ url = pk11_getUrl(object);
+ if (url == NULL) {
+ return (PK11Attribute *) &pk11_StaticNullAttr;
+ }
+ return pk11_NewTokenAttribute(type, url, PORT_Strlen(url)+1, PR_TRUE);
+ case CKA_VALUE:
+ crl = pk11_getCrl(object);
+ if (crl == NULL) break;
+ return pk11_NewTokenAttribute(type, crl->data, crl->len, PR_FALSE);
+ case CKA_SUBJECT:
+ return pk11_NewTokenAttribute(type,object->dbKey.data,
+ object->dbKey.len, PR_FALSE);
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static PK11Attribute *
+pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
+{
+ NSSLOWCERTCertificate *cert;
+ NSSLOWKEYPublicKey *pubKey;
+ unsigned char hash[SHA1_LENGTH];
+ SECItem *item;
+ PK11Attribute *attr;
+
+ switch (type) {
+ case CKA_PRIVATE:
+ return (PK11Attribute *) &pk11_StaticFalseAttr;
+ case CKA_MODIFIABLE:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_CERTIFICATE_TYPE:
+ /* hardcoding X.509 into here */
+ return (PK11Attribute *)&pk11_StaticX509Attr;
+ default:
+ break;
+ }
+ cert = pk11_getCert(object);
+ if (cert == NULL) {
+ return NULL;
+ }
+ switch (type) {
+ case CKA_VALUE:
+ return pk11_NewTokenAttribute(type,cert->derCert.data,
+ cert->derCert.len,PR_FALSE);
+ case CKA_ID:
+ pubKey = nsslowcert_ExtractPublicKey(cert);
+ if (pubKey == NULL) break;
+ item = pk11_GetPubItem(pubKey);
+ if (item == NULL) {
+ nsslowkey_DestroyPublicKey(pubKey);
+ break;
+ }
+ SHA1_HashBuf(hash,item->data,item->len);
+ /* item is imbedded in pubKey, just free the key */
+ nsslowkey_DestroyPublicKey(pubKey);
+ return pk11_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE);
+ case CKA_LABEL:
+ return cert->nickname ? pk11_NewTokenAttribute(type, cert->nickname,
+ PORT_Strlen(cert->nickname)+1, PR_FALSE) :
+ (PK11Attribute *) &pk11_StaticNullAttr;
+ case CKA_SUBJECT:
+ return pk11_NewTokenAttribute(type,cert->derSubject.data,
+ cert->derSubject.len, PR_FALSE);
+ case CKA_ISSUER:
+ return pk11_NewTokenAttribute(type,cert->derIssuer.data,
+ cert->derIssuer.len, PR_FALSE);
+ case CKA_SERIAL_NUMBER:
+ item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate);
+ if (item == NULL) break;
+ attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE);
+ SECITEM_FreeItem(item,PR_TRUE);
+ return attr;
+ default:
+ break;
+ }
+ return NULL;
+}
-
+static PK11Attribute *
+pk11_FindTokenAttribute(PK11TokenObject *object,CK_ATTRIBUTE_TYPE type)
+{
+ /* handle the common ones */
+ switch (type) {
+ case CKA_CLASS:
+ return pk11_NewTokenAttribute(type,&object->obj.objclass,
+ sizeof(object->obj.objclass),PR_FALSE);
+ case CKA_TOKEN:
+ return (PK11Attribute *) &pk11_StaticTrueAttr;
+ case CKA_LABEL:
+ return (object->obj.objclass != CKO_CERTIFICATE) ?
+ (PK11Attribute *) &pk11_StaticNullAttr :
+ pk11_FindCertAttribute(object,type);
+ default:
+ break;
+ }
+ switch (object->obj.objclass) {
+ case CKO_CERTIFICATE:
+ return pk11_FindCertAttribute(object,type);
+ case CKO_NETSCAPE_CRL:
+ return pk11_FindCrlAttribute(object,type);
+ case CKO_NETSCAPE_TRUST:
+ return pk11_FindTrustAttribute(object,type);
+ case CKO_NETSCAPE_SMIME:
+ return pk11_FindSMIMEAttribute(object,type);
+ case CKO_PUBLIC_KEY:
+ return pk11_FindPublicKeyAttribute(object,type);
+ case CKO_PRIVATE_KEY:
+ return pk11_FindPrivateKeyAttribute(object,type);
+ case CKO_SECRET_KEY:
+ return pk11_FindSecretKeyAttribute(object,type);
+ default:
+ break;
+ }
+ PORT_Assert(0);
+ return NULL;
+}
+
/*
* look up and attribute structure from a type and Object structure.
* The returned attribute is referenced and needs to be freed when
@@ -169,10 +1036,15 @@ PK11Attribute *
pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
{
PK11Attribute *attribute;
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ if (sessObject == NULL) {
+ return pk11_FindTokenAttribute(pk11_narrowToTokenObject(object),type);
+ }
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);
-#ifdef REF_COUNT_ATTRIBUTE
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
+ pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE);
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
if (attribute) {
/* atomic increment would be nice here */
PK11_USE_THREADS(PZ_Lock(attribute->refLock);)
@@ -180,31 +1052,19 @@ pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
PK11_USE_THREADS(PZ_Unlock(attribute->refLock);)
}
#endif
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
return(attribute);
}
-/*
- * release a reference to an attribute structure
- */
-void
-pk11_FreeAttribute(PK11Attribute *attribute)
-{
-#ifdef REF_COUNT_ATTRIBUTE
- PRBool destroy = PR_FALSE;
-
- PK11_USE_THREADS(PZ_Lock(attribute->refLock);)
- if (attribute->refCount == 1) destroy = PR_TRUE;
- attribute->refCount--;
- PK11_USE_THREADS(PZ_Unlock(attribute->refLock);)
- if (destroy) pk11_DestroyAttribute(attribute);
-#endif
+PRBool
+pk11_hasAttributeToken(PK11TokenObject *object)
+{
+ return PR_FALSE;
}
-
/*
* return true if object has attribute
*/
@@ -212,10 +1072,15 @@ PRBool
pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
{
PK11Attribute *attribute;
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ if (sessObject == NULL) {
+ return pk11_hasAttributeToken(pk11_narrowToTokenObject(object));
+ }
+
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
+ pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE);
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
return (PRBool)(attribute != NULL);
}
@@ -223,12 +1088,16 @@ pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
/*
* add an attribute to an object
*/
-static
-void pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute)
+static void
+pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute)
{
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
- pk11queue_add(attribute,attribute->handle,object->head,ATTRIBUTE_HASH_SIZE);
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ if (sessObject == NULL) return;
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
+ pk11queue_add(attribute,attribute->handle,
+ sessObject->head,ATTRIBUTE_HASH_SIZE);
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
}
/*
@@ -277,13 +1146,18 @@ pk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object,
static void
pk11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute)
{
- PK11_USE_THREADS(PZ_Lock(object->attributeLock);)
+ PK11SessionObject *sessObject = pk11_narrowToSessionObject(object);
+
+ if (sessObject == NULL) {
+ return ;
+ }
+ PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);)
if (pk11queue_is_queued(attribute,attribute->handle,
- object->head,ATTRIBUTE_HASH_SIZE)) {
+ sessObject->head,ATTRIBUTE_HASH_SIZE)) {
pk11queue_delete(attribute,attribute->handle,
- object->head,ATTRIBUTE_HASH_SIZE);
+ sessObject->head,ATTRIBUTE_HASH_SIZE);
}
- PK11_USE_THREADS(PZ_Unlock(object->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);)
pk11_FreeAttribute(attribute);
}
@@ -320,20 +1194,106 @@ pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
if (attribute->attrib.pValue != NULL) {
PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
-#ifdef REF_COUNT_ATTRIBUTE
- PORT_Free(attribute->attrib.pValue);
-#endif /* REF_COUNT_ATTRIBUTE */
-#ifdef NO_ARENA
- if (attribute->attrib.pValue != attribute->space) {
+ if (attribute->freeData) {
PORT_Free(attribute->attrib.pValue);
}
-#endif /* NO_ARENA */
+ attribute->freeData = PR_FALSE;
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
pk11_FreeAttribute(attribute);
}
+static CK_RV
+pk11_SetTrustAttribute(PK11TokenObject *to, CK_ATTRIBUTE_TYPE type,
+ void *value, unsigned int len)
+{
+ unsigned int flags;
+ CK_TRUST trust;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertTrust dbTrust;
+ SECStatus rv;
+
+ if (to->obj.slot->certDB == NULL) {
+ return CKR_TOKEN_WRITE_PROTECTED;
+ }
+ if (len != sizeof (CK_TRUST)) {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ trust = *(CK_TRUST *)value;
+ flags = pk11_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH));
+
+ cert = pk11_getCert(to);
+ if (cert == NULL) {
+ return CKR_OBJECT_HANDLE_INVALID;
+ }
+ dbTrust = *cert->trust;
+
+ switch (type) {
+ case CKA_TRUST_EMAIL_PROTECTION:
+ dbTrust.emailFlags = flags |
+ (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
+ break;
+ case CKA_TRUST_CODE_SIGNING:
+ dbTrust.objectSigningFlags = flags |
+ (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
+ break;
+ case CKA_TRUST_CLIENT_AUTH:
+ dbTrust.sslFlags = flags | (cert->trust->sslFlags &
+ CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA);
+ break;
+ case CKA_TRUST_SERVER_AUTH:
+ dbTrust.sslFlags = flags | (cert->trust->sslFlags &
+ CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA);
+ break;
+ default:
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+
+ rv = nsslowcert_ChangeCertTrust(to->obj.slot->certDB,cert,&dbTrust);
+ if (rv != SECSuccess) {
+ return CKR_DEVICE_ERROR;
+ }
+ return CKR_OK;
+}
+
+static CK_RV
+pk11_forceTokenAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type,
+ void *value, unsigned int len)
+{
+ PK11Attribute *attribute;
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
+ CK_RV crv = CKR_ATTRIBUTE_READ_ONLY;
+
+ PORT_Assert(to);
+ if (to == NULL) {
+ return CKR_DEVICE_ERROR;
+ }
+
+ /* if we are just setting it to the value we already have,
+ * allow it to happen. */
+ attribute=pk11_FindAttribute(object,type);
+ if ((attribute->attrib.ulValueLen == len) &&
+ PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) {
+ pk11_FreeAttribute(attribute);
+ return CKR_OK;
+ }
+
+ switch (object->objclass) {
+ case CKO_CERTIFICATE:
+ /* change NICKNAME, EMAIL, */
+ break;
+ case CKO_NETSCAPE_CRL:
+ /* change URL */
+ break;
+ case CKO_NETSCAPE_TRUST:
+ crv = pk11_SetTrustAttribute(to,type,value,len);
+ break;
+ }
+ pk11_FreeAttribute(attribute);
+ return crv;
+}
+
/*
* force an attribute to a spaecif value.
*/
@@ -343,25 +1303,31 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value,
{
PK11Attribute *attribute;
void *att_val = NULL;
+ PRBool freeData = PR_FALSE;
+ if (pk11_isToken(object->handle)) {
+ return pk11_forceTokenAttribute(object,type,value,len);
+ }
attribute=pk11_FindAttribute(object,type);
if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len);
if (value) {
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
if (len <= ATTR_SPACE) {
att_val = attribute->space;
} else {
att_val = PORT_Alloc(len);
+ freeData = PR_TRUE;
}
#else
-#ifdef REF_COUNT_ATTRIBUTE
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
att_val = PORT_Alloc(len);
+ freeData = PR_TRUE;
#else
att_val = PORT_ArenaAlloc(object->arena,len);
-#endif /* REF_COUNT_ATTRIBUTE */
-#endif /* NO_ARENA */
+#endif /* PKCS11_REF_COUNT_ATTRIBUTES */
+#endif /* PKCS11_STATIC_ATTRIBUTES */
if (att_val == NULL) {
return CKR_HOST_MEMORY;
}
@@ -376,21 +1342,19 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value,
PORT_Memset(attribute->attrib.pValue,0,
attribute->attrib.ulValueLen);
}
-#ifdef REF_COUNT_ATTRIBUTE
- PORT_Free(attribute->attrib.pValue);
-#endif /* REF_COUNT_ATTRIBUTE */
-#ifdef NO_ARENA
- if (attribute->attrib.pValue != attribute->space) {
+ if (attribute->freeData) {
PORT_Free(attribute->attrib.pValue);
}
-#endif /* NO_ARENA */
+ attribute->freeData = PR_FALSE;
attribute->attrib.pValue = NULL;
attribute->attrib.ulValueLen = 0;
}
if (att_val) {
attribute->attrib.pValue = att_val;
attribute->attrib.ulValueLen = len;
+ attribute->freeData = freeData;
}
+ pk11_FreeAttribute(attribute);
return CKR_OK;
}
@@ -591,6 +1555,62 @@ pk11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
* ******************** Object Utilities *******************************
*/
+static SECStatus
+pk11_deleteTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle)
+{
+ SECItem *item;
+ PRBool rem;
+
+ item = (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable,
+ (void *)handle);
+ if (item) {
+ SECITEM_FreeItem(item,PR_TRUE);
+ }
+ rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ;
+ return rem ? SECSuccess : SECFailure;
+}
+
+static SECStatus
+pk11_addTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
+{
+ PLHashEntry *entry;
+ SECItem *item;
+
+ item = SECITEM_DupItem(key);
+ if (item == NULL) {
+ return SECFailure;
+ }
+ entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item);
+ if (entry == NULL) {
+ SECITEM_FreeItem(item,PR_TRUE);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static SECItem *
+pk11_lookupTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle)
+{
+ return (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable,
+ (void *)handle);
+}
+
+/*
+ * use the refLock. This operations should be very rare, so the added
+ * contention on the ref lock should be lower than the overhead of adding
+ * a new lock. We use separate functions for this just in case I'm wrong.
+ */
+static void
+pk11_tokenKeyLock(PK11Slot *slot) {
+ PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
+}
+
+static void
+pk11_tokenKeyUnlock(PK11Slot *slot) {
+ PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
+}
+
+
/* allocation hooks that allow us to recycle old object structures */
#ifdef MAX_OBJECT_LIST_SIZE
static PK11Object * objectFreeList = NULL;
@@ -620,26 +1640,26 @@ pk11_GetObjectFromList(PRBool *hasLocks) {
}
#endif
- object = (PK11Object*)PORT_ZAlloc(sizeof(PK11Object));
+ object = (PK11Object*)PORT_ZAlloc(sizeof(PK11SessionObject));
*hasLocks = PR_FALSE;
return object;
}
static void
-pk11_PutObjectToList(PK11Object *object) {
+pk11_PutObjectToList(PK11SessionObject *object) {
#ifdef MAX_OBJECT_LIST_SIZE
if (object_count < MAX_OBJECT_LIST_SIZE) {
PK11_USE_THREADS(PZ_Lock(objectLock));
- object->next = objectFreeList;
- objectFreeList = object;
+ object->obj.next = objectFreeList;
+ objectFreeList = &object->obj;
object_count++;
PK11_USE_THREADS(PZ_Unlock(objectLock));
return;
}
#endif
PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);)
- PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
- object->attributeLock = object->refLock = NULL;
+ PK11_USE_THREADS(PZ_DestroyLock(object->obj.refLock);)
+ object->attributeLock = object->obj.refLock = NULL;
PORT_Free(object);
}
@@ -651,58 +1671,63 @@ PK11Object *
pk11_NewObject(PK11Slot *slot)
{
PK11Object *object;
+ PK11SessionObject *sessObject;
PRBool hasLocks = PR_FALSE;
int i;
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
object = pk11_GetObjectFromList(&hasLocks);
if (object == NULL) {
return NULL;
}
- object->nextAttr = 0;
+ sessObject = (PK11SessionObject *)object;
+ sessObject->nextAttr = 0;
+
+ for (i=0; i < MAX_OBJS_ATTRS; i++) {
+ sessObject->attrList[i].attrib.pValue = NULL;
+ sessObject->attrList[i].freeData = PR_FALSE;
+ }
#else
+ PRArenaPool *arena;
+
arena = PORT_NewArena(2048);
if (arena == NULL) return NULL;
- object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11Object));
+ object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11SessionObject));
if (object == NULL) {
PORT_FreeArena(arena,PR_FALSE);
return NULL;
}
object->arena = arena;
- for (i=0; i < MAX_OBJS_ATTRS; i++) {
- object->attrList[i].attrib.pValue = NULL;
- }
+ sessObject = (PK11SessionObject *)object;
#endif
object->handle = 0;
object->next = object->prev = NULL;
- object->sessionList.next = NULL;
- object->sessionList.prev = NULL;
- object->sessionList.parent = object;
- object->inDB = PR_FALSE;
- object->label = NULL;
- object->refCount = 1;
- object->session = NULL;
object->slot = slot;
object->objclass = 0xffff;
- object->wasDerived = PR_FALSE;
+ object->refCount = 1;
+ sessObject->sessionList.next = NULL;
+ sessObject->sessionList.prev = NULL;
+ sessObject->sessionList.parent = object;
+ sessObject->session = NULL;
+ sessObject->wasDerived = PR_FALSE;
#ifdef PKCS11_USE_THREADS
if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock);
if (object->refLock == NULL) {
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
PORT_Free(object);
#else
PORT_FreeArena(arena,PR_FALSE);
#endif
return NULL;
}
- if (!hasLocks) object->attributeLock = PZ_NewLock(nssILockAttribute);
- if (object->attributeLock == NULL) {
+ if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute);
+ if (sessObject->attributeLock == NULL) {
PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
-#ifdef NO_ARENA
+#ifdef PKCS11_STATIC_ATTRIBUTES
PORT_Free(object);
#else
PORT_FreeArena(arena,PR_FALSE);
@@ -710,17 +1735,55 @@ pk11_NewObject(PK11Slot *slot)
return NULL;
}
#else
- object->attributeLock = NULL;
+ sessObject->attributeLock = NULL;
object->refLock = NULL;
#endif
for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
- object->head[i] = NULL;
+ sessObject->head[i] = NULL;
}
object->objectInfo = NULL;
object->infoFree = NULL;
return object;
}
+static CK_RV
+pk11_DestroySessionObjectData(PK11SessionObject *so)
+{
+ int i;
+
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ for (i=0; i < MAX_OBJS_ATTRS; i++) {
+ unsigned char *value = so->attrList[i].attrib.pValue;
+ if (value) {
+ PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen);
+ if (so->attrList[i].freeData) {
+ PORT_Free(value);
+ }
+ so->attrList[i].attrib.pValue = NULL;
+ so->attrList[i].freeData = PR_FALSE;
+ }
+ }
+#endif
+
+#ifdef PKCS11_REF_COUNT_ATTRIBUTES
+ /* clean out the attributes */
+ /* since no one is referencing us, it's safe to walk the chain
+ * without a lock */
+ for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
+ PK11Attribute *ap,*next;
+ for (ap = so->head[i]; ap != NULL; ap = next) {
+ next = ap->next;
+ /* paranoia */
+ ap->next = ap->prev = NULL;
+ pk11_FreeAttribute(ap);
+ }
+ so->head[i] = NULL;
+ }
+#endif
+/* PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock));*/
+ return CKR_OK;
+}
+
/*
* free all the data associated with an object. Object reference count must
* be 'zero'.
@@ -728,86 +1791,33 @@ pk11_NewObject(PK11Slot *slot)
static CK_RV
pk11_DestroyObject(PK11Object *object)
{
-#if defined(REF_COUNT_ATTRIBUTE) || defined(NO_ARENA)
- int i;
-#endif
- SECItem pubKey;
CK_RV crv = CKR_OK;
- SECStatus rv;
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
PORT_Assert(object->refCount == 0);
/* delete the database value */
- if (object->inDB) {
- if (pk11_isToken(object->handle)) {
- /* remove the objects from the real data base */
- switch (object->handle & PK11_TOKEN_TYPE_MASK) {
- case PK11_TOKEN_TYPE_PRIV:
- /* KEYID is the public KEY for DSA and DH, and the MODULUS for
- * RSA */
- crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
- if (crv != CKR_OK) break;
- rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &pubKey);
- if (rv != SECSuccess && pubKey.data[0] == 0) {
- /* Because of legacy code issues, sometimes the public key
- * has a '0' prepended to it, forcing it to be unsigned.
- * The database may not store that '0', so remove it and
- * try again.
- */
- SECItem tmpPubKey;
- tmpPubKey.data = pubKey.data + 1;
- tmpPubKey.len = pubKey.len - 1;
- rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &tmpPubKey);
- }
- if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;
- break;
- case PK11_TOKEN_TYPE_CERT:
- rv = SEC_DeletePermCertificate((CERTCertificate *)object->objectInfo);
- if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
- break;
- }
+ if (to) {
+ if (to->dbKey.data) {
+ PORT_Free(to->dbKey.data);
+ to->dbKey.data = NULL;
}
}
- if (object->label) PORT_Free(object->label);
-
- object->inDB = PR_FALSE;
- object->label = NULL;
-
-#ifdef NO_ARENA
- for (i=0; i < MAX_OBJS_ATTRS; i++) {
- unsigned char *value = object->attrList[i].attrib.pValue;
- if (value) {
- PORT_Memset(value,0,object->attrList[i].attrib.ulValueLen);
- if (value != object->attrList[i].space) {
- PORT_Free(value);
- }
- object->attrList[i].attrib.pValue = NULL;
- }
+ if (so) {
+ pk11_DestroySessionObjectData(so);
}
-#endif
-
-#ifdef REF_COUNT_ATTRIBUTE
- /* clean out the attributes */
- /* since no one is referencing us, it's safe to walk the chain
- * without a lock */
- for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
- PK11Attribute *ap,*next;
- for (ap = object->head[i]; ap != NULL; ap = next) {
- next = ap->next;
- /* paranoia */
- ap->next = ap->prev = NULL;
- pk11_FreeAttribute(ap);
- }
- object->head[i] = NULL;
- }
-#endif
if (object->objectInfo) {
(*object->infoFree)(object->objectInfo);
}
-#ifdef NO_ARENA
- pk11_PutObjectToList(object);
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ if (so) {
+ pk11_PutObjectToList(so);
+ } else {
+ PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
+ PORT_Free(to);;
+ }
#else
- PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);)
PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
arena = object->arena;
PORT_FreeArena(arena,PR_FALSE);
@@ -830,6 +1840,10 @@ pk11_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, PK11Slot *slot)
PZLock *lock;
PK11Object *object;
+ if (pk11_isToken(handle)) {
+ return pk11_NewTokenObject(slot, NULL, handle);
+ }
+
head = slot->tokObjects;
lock = slot->objectLock;
@@ -888,7 +1902,8 @@ void
pk11_AddSlotObject(PK11Slot *slot, PK11Object *object)
{
PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- pk11queue_add(object,object->handle,slot->tokObjects,TOKEN_OBJECT_HASH_SIZE);
+ pk11queue_add(object,object->handle,slot->tokObjects,
+ TOKEN_OBJECT_HASH_SIZE);
PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
}
@@ -896,35 +1911,98 @@ void
pk11_AddObject(PK11Session *session, PK11Object *object)
{
PK11Slot *slot = pk11_SlotFromSession(session);
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
- if (!pk11_isToken(object->handle)) {
+ if (so) {
PK11_USE_THREADS(PZ_Lock(session->objectLock);)
- pk11queue_add(&object->sessionList,0,session->objects,0);
- object->session = session;
+ pk11queue_add(&so->sessionList,0,session->objects,0);
+ so->session = session;
PK11_USE_THREADS(PZ_Unlock(session->objectLock);)
}
pk11_AddSlotObject(slot,object);
+ pk11_ReferenceObject(object);
}
/*
* add an object to a slot andsession queue
*/
-void
+CK_RV
pk11_DeleteObject(PK11Session *session, PK11Object *object)
{
PK11Slot *slot = pk11_SlotFromSession(session);
+ PK11SessionObject *so = pk11_narrowToSessionObject(object);
+ PK11TokenObject *to = pk11_narrowToTokenObject(object);
+ CK_RV crv = CKR_OK;
+ SECStatus rv;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertTrust tmptrust;
+ PRBool isKrl;
- if (object->session) {
- PK11Session *session = object->session;
+ /* Handle Token case */
+ if (so && so->session) {
+ PK11Session *session = so->session;
PK11_USE_THREADS(PZ_Lock(session->objectLock);)
- pk11queue_delete(&object->sessionList,0,session->objects,0);
+ pk11queue_delete(&so->sessionList,0,session->objects,0);
PK11_USE_THREADS(PZ_Unlock(session->objectLock);)
- }
- PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
- pk11queue_delete(object,object->handle,slot->tokObjects,
+ PK11_USE_THREADS(PZ_Lock(slot->objectLock);)
+ pk11queue_delete(object,object->handle,slot->tokObjects,
TOKEN_OBJECT_HASH_SIZE);
- PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
- pk11_FreeObject(object);
+ PK11_USE_THREADS(PZ_Unlock(slot->objectLock);)
+ pk11_FreeObject(object); /* reduce it's reference count */
+ } else {
+ PORT_Assert(to);
+ /* remove the objects from the real data base */
+ switch (object->handle & PK11_TOKEN_TYPE_MASK) {
+ case PK11_TOKEN_TYPE_PRIV:
+ case PK11_TOKEN_TYPE_KEY:
+ /* KEYID is the public KEY for DSA and DH, and the MODULUS for
+ * RSA */
+ PORT_Assert(slot->keyDB);
+ rv = nsslowkey_DeleteKey(slot->keyDB, &to->dbKey);
+ if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;
+ break;
+ case PK11_TOKEN_TYPE_PUB:
+ break; /* public keys only exist at the behest of the priv key */
+ case PK11_TOKEN_TYPE_CERT:
+ cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey);
+ if (cert == NULL) {
+ crv = CKR_DEVICE_ERROR;
+ break;
+ }
+ rv = nsslowcert_DeletePermCertificate(cert);
+ if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
+ nsslowcert_DestroyCertificate(cert);
+ break;
+ case PK11_TOKEN_TYPE_CRL:
+ isKrl = (PRBool) (object->handle == PK11_TOKEN_KRL_HANDLE);
+ rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,isKrl);
+ if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
+ break;
+ case PK11_TOKEN_TYPE_TRUST:
+ cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey);
+ if (cert == NULL) {
+ crv = CKR_DEVICE_ERROR;
+ break;
+ }
+ tmptrust = *cert->trust;
+ tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS;
+ tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS;
+ tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS;
+ tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
+ tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
+ tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
+ rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&tmptrust);
+ if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
+ nsslowcert_DestroyCertificate(cert);
+ break;
+ default:
+ break;
+ }
+ pk11_tokenKeyLock(object->slot);
+ pk11_deleteTokenKeyByHandle(object->slot,object->handle);
+ pk11_tokenKeyUnlock(object->slot);
+ }
+ return crv;
}
/*
@@ -936,11 +2014,16 @@ CK_RV
pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
{
PK11Attribute *attribute;
+ PK11SessionObject *src_so = pk11_narrowToSessionObject(srcObject);
int i;
- PK11_USE_THREADS(PZ_Lock(srcObject->attributeLock);)
+ if (src_so == NULL) {
+ return CKR_DEVICE_ERROR; /* can't copy token objects yet */
+ }
+
+ PK11_USE_THREADS(PZ_Lock(src_so->attributeLock);)
for(i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
- attribute = srcObject->head[i];
+ attribute = src_so->head[i];
do {
if (attribute) {
if (!pk11_hasAttribute(destObject,attribute->handle)) {
@@ -949,7 +2032,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
PK11Attribute *newAttribute = pk11_NewAttribute(
destObject,pk11_attr_expand(&attribute->attrib));
if (newAttribute == NULL) {
- PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);)
return CKR_HOST_MEMORY;
}
pk11_AddAttribute(destObject,newAttribute);
@@ -958,7 +2041,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
}
} while (attribute != NULL);
}
- PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);)
+ PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);)
return CKR_OK;
}
@@ -1012,7 +2095,7 @@ pk11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count)
* in the object list.
*/
CK_RV
-pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
+pk11_searchObjectList(PK11SearchResults *search,PK11Object **head,
PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, int count, PRBool isLoggedIn)
{
int i;
@@ -1027,10 +2110,7 @@ pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
if (pk11_objectMatch(object,theTemplate,count)) {
/* don't return objects that aren't yet visible */
if ((!isLoggedIn) && pk11_isTrue(object,CKA_PRIVATE)) continue;
- crv = AddToList(objectList,object);
- if (crv != CKR_OK) {
- break;
- }
+ pk11_addHandle(search,object->handle);
}
}
PK11_USE_THREADS(PZ_Unlock(lock);)
@@ -1126,37 +2206,11 @@ pk11_FreeContext(PK11SessionContext *context)
if (context->hashInfo) {
(*context->hashdestroy)(context->hashInfo,PR_TRUE);
}
- PORT_Free(context);
-}
-
-/* look up a slot structure from the ID (used to be a macro when we only
- * had two slots) */
-PK11Slot *
-pk11_SlotFromID(CK_SLOT_ID slotID)
-{
- switch (slotID) {
- case NETSCAPE_SLOT_ID:
- return &pk11_slot[0];
- case PRIVATE_KEY_SLOT_ID:
- return &pk11_slot[1];
- case FIPS_SLOT_ID:
- return &pk11_slot[2];
- default:
- break; /* fall through to NULL */
+ if (context->key) {
+ pk11_FreeObject(context->key);
+ context->key = NULL;
}
- return NULL;
-}
-
-PK11Slot *
-pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
-{
- if (handle & PK11_PRIVATE_KEY_FLAG) {
- return &pk11_slot[1];
- }
- if (handle & PK11_FIPS_FLAG) {
- return &pk11_slot[2];
- }
- return &pk11_slot[0];
+ PORT_Free(context);
}
/*
@@ -1278,3 +2332,190 @@ pk11_FreeSession(PK11Session *session)
if (destroy) pk11_DestroySession(session);
}
+/*
+ * handle Token Object stuff
+ */
+
+/* Make a token handle for an object and record it so we can find it again */
+CK_OBJECT_HANDLE
+pk11_mkHandle(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class)
+{
+ unsigned char hashBuf[SHA1_LENGTH];
+ CK_OBJECT_HANDLE handle;
+ SECItem *key;
+
+ handle = class;
+ /* there is only one KRL, use a fixed handle for it */
+ if (handle != PK11_TOKEN_KRL_HANDLE) {
+ SHA1_HashBuf(hashBuf,dbKey->data,dbKey->len);
+ handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) |
+ (hashBuf[2] << 8) | hashBuf[3];
+ handle = PK11_TOKEN_MAGIC | class |
+ (handle & ~(PK11_TOKEN_TYPE_MASK|PK11_TOKEN_MASK));
+ /* we have a CRL who's handle has randomly matched the reserved KRL
+ * handle, increment it */
+ if (handle == PK11_TOKEN_KRL_HANDLE) {
+ handle++;
+ }
+ }
+
+ pk11_tokenKeyLock(slot);
+ while ((key = pk11_lookupTokenKeyByHandle(slot,handle)) != NULL) {
+ if (SECITEM_ItemsAreEqual(key,dbKey)) {
+ pk11_tokenKeyUnlock(slot);
+ return handle;
+ }
+ handle++;
+ }
+ pk11_addTokenKeyByHandle(slot,handle,dbKey);
+ pk11_tokenKeyUnlock(slot);
+ return handle;
+}
+
+void
+pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle)
+{
+ if (search->handles == NULL) {
+ return;
+ }
+ if (search->size >= search->array_size) {
+ search->array_size += NSC_SEARCH_BLOCK_SIZE;
+ search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
+ sizeof(CK_OBJECT_HANDLE)* search->array_size);
+ if (search->handles == NULL) {
+ return;
+ }
+ }
+ search->handles[search->size] = handle;
+ search->size++;
+}
+
+static const CK_OBJECT_HANDLE pk11_classArray[] = {
+ 0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
+ CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME,
+ CKO_CERTIFICATE };
+
+#define handleToClass(handle) \
+ pk11_classArray[((handle & PK11_TOKEN_TYPE_MASK))>>28]
+
+PK11Object *
+pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
+{
+ PK11Object *object = NULL;
+ PK11TokenObject *tokObject = NULL;
+ SECStatus rv;
+
+#ifdef PKCS11_STATIC_ATTRIBUTES
+ object = (PK11Object *) PORT_ZAlloc(sizeof(PK11TokenObject));
+ if (object == NULL) {
+ return NULL;
+ }
+#else
+ PRArenaPool *arena;
+
+ arena = PORT_NewArena(2048);
+ if (arena == NULL) return NULL;
+
+ object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11TokenObject));
+ if (object == NULL) {
+ PORT_FreeArena(arena,PR_FALSE);
+ return NULL;
+ }
+ object->arena = arena;
+#endif
+ tokObject = (PK11TokenObject *) object;
+
+ object->objclass = handleToClass(handle);
+ object->handle = handle;
+ object->refCount = 1;
+ object->slot = slot;
+ object->objectInfo = NULL;
+ object->infoFree = NULL;
+ if (dbKey == NULL) {
+ pk11_tokenKeyLock(slot);
+ dbKey = pk11_lookupTokenKeyByHandle(slot,handle);
+ if (dbKey == NULL) {
+ pk11_tokenKeyUnlock(slot);
+ goto loser;
+ }
+ rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
+ pk11_tokenKeyUnlock(slot);
+ } else {
+ rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey);
+ }
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+#ifdef PKCS11_USE_THREADS
+ object->refLock = PZ_NewLock(nssILockRefLock);
+ if (object->refLock == NULL) {
+ goto loser;
+ }
+#endif
+
+ return object;
+loser:
+ if (object) {
+ pk11_FreeObject(object);
+ }
+ return NULL;
+
+}
+
+PRBool
+pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class,
+ CK_ATTRIBUTE_PTR theTemplate,int count)
+{
+ PK11Object *object;
+ PRBool ret;
+
+ object = pk11_NewTokenObject(slot,dbKey,PK11_TOKEN_MASK|class);
+ if (object == NULL) {
+ return PR_FALSE;
+ }
+
+ ret = pk11_objectMatch(object,theTemplate,count);
+ pk11_FreeObject(object);
+ return ret;
+}
+
+PK11TokenObject *
+pk11_convertSessionToToken(PK11SessionObject *so)
+{
+ SECItem *key;
+ PK11TokenObject *to = pk11_narrowToTokenObject(&so->obj);
+ SECStatus rv;
+
+ pk11_DestroySessionObjectData(so);
+ PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock));
+ if (to == NULL) {
+ return NULL;
+ }
+ pk11_tokenKeyLock(so->obj.slot);
+ key = pk11_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle);
+ if (key == NULL) {
+ pk11_tokenKeyUnlock(so->obj.slot);
+ return NULL;
+ }
+ rv = SECITEM_CopyItem(NULL,&to->dbKey,key);
+ pk11_tokenKeyUnlock(so->obj.slot);
+ if (rv == SECFailure) {
+ return NULL;
+ }
+
+ return to;
+
+}
+
+PK11SessionObject *
+pk11_narrowToSessionObject(PK11Object *obj)
+{
+ return !pk11_isToken(obj->handle) ? (PK11SessionObject *)obj : NULL;
+}
+
+PK11TokenObject *
+pk11_narrowToTokenObject(PK11Object *obj)
+{
+ return pk11_isToken(obj->handle) ? (PK11TokenObject *)obj : NULL;
+}
+