summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2002-07-02 15:11:29 +0000
committerrelyea%netscape.com <devnull@localhost>2002-07-02 15:11:29 +0000
commitb0bdf359ef8931a793a8486cd8332dd7fffdffd4 (patch)
tree8e881f2af5b36261de3db87fef239fb02422ad45
parentc8440750a740cd2af2a96ad7de0fea5c0dcc6194 (diff)
downloadnss-hg-b0bdf359ef8931a793a8486cd8332dd7fffdffd4.tar.gz
More performance improvements in listing certs:
1) reduce more short term memory allocate/frees. 2) remove sha1 hash calculations from critical paths. 3) when listing user certs, skip decoding of non-user certs.
-rw-r--r--security/nss/lib/certdb/alg1485.c114
-rw-r--r--security/nss/lib/dev/devtoken.c34
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c70
-rw-r--r--security/nss/lib/softoken/pcertdb.c21
-rw-r--r--security/nss/lib/softoken/pkcs11.c14
-rw-r--r--security/nss/lib/softoken/pkcs11i.h7
-rw-r--r--security/nss/lib/softoken/pkcs11u.c126
7 files changed, 213 insertions, 173 deletions
diff --git a/security/nss/lib/certdb/alg1485.c b/security/nss/lib/certdb/alg1485.c
index aa3ea1b3b..ca18e845e 100644
--- a/security/nss/lib/certdb/alg1485.c
+++ b/security/nss/lib/certdb/alg1485.c
@@ -520,29 +520,43 @@ CERT_AsciiToName(char *string)
/************************************************************************/
+typedef struct stringBufStr {
+ char *buffer;
+ unsigned offset;
+ unsigned size;
+} stringBuf;
+
+#define DEFAULT_BUFFER_SIZE 200
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
static SECStatus
-AppendStr(char **bufp, unsigned *buflenp, char *str)
+AppendStr(stringBuf *bufp, char *str)
{
char *buf;
unsigned bufLen, bufSize, len;
+ int size = 0;
/* Figure out how much to grow buf by (add in the '\0') */
- buf = *bufp;
- bufLen = *buflenp;
+ buf = bufp->buffer;
+ bufLen = bufp->offset;
len = PORT_Strlen(str);
bufSize = bufLen + len;
- if (buf) {
- buf = (char*) PORT_Realloc(buf, bufSize);
- } else {
+ if (!buf) {
bufSize++;
- buf = (char*) PORT_Alloc(bufSize);
+ size = MAX(DEFAULT_BUFFER_SIZE,bufSize*2);
+ buf = (char *) PORT_Alloc(size);
+ bufp->size = size;
+ } else if (bufp->size < bufSize) {
+ size = bufSize*2;
+ buf =(char *) PORT_Realloc(buf,size);
+ bufp->size = size;
}
if (!buf) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
- *bufp = buf;
- *buflenp = bufSize;
+ bufp->buffer = buf;
+ bufp->offset = bufSize;
/* Concatenate str onto buf */
buf = buf + bufLen;
@@ -603,7 +617,7 @@ CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen)
}
static SECStatus
-AppendAVA(char **bufp, unsigned *buflenp, CERTAVA *ava)
+AppendAVA(stringBuf *bufp, CERTAVA *ava)
{
char *tagName;
char tmpBuf[384];
@@ -663,7 +677,7 @@ AppendAVA(char **bufp, unsigned *buflenp, CERTAVA *ava)
PORT_SetError(SEC_ERROR_INVALID_AVA);
return SECFailure;
#else
- rv = AppendStr(bufp, buflenp, "ERR=Unknown AVA");
+ rv = AppendStr(bufp, "ERR=Unknown AVA");
return rv;
#endif
}
@@ -689,7 +703,7 @@ AppendAVA(char **bufp, unsigned *buflenp, CERTAVA *ava)
SECITEM_FreeItem(avaValue, PR_TRUE);
if (rv) return SECFailure;
- rv = AppendStr(bufp, buflenp, tmpBuf);
+ rv = AppendStr(bufp, tmpBuf);
return rv;
}
@@ -705,6 +719,7 @@ CERT_NameToAscii(CERTName *name)
PRBool first = PR_TRUE;
char *buf = NULL;
unsigned buflen = 0;
+ stringBuf strBuf = { NULL, 0, 0 };
rdns = name->rdns;
if (rdns == NULL) {
@@ -724,20 +739,22 @@ CERT_NameToAscii(CERTName *name)
while ((ava = *avas++) != NULL) {
/* Put in comma separator */
if (!first) {
- rv = AppendStr(&buf, &buflen, ", ");
+ rv = AppendStr(&strBuf, ", ");
if (rv) goto loser;
} else {
first = PR_FALSE;
}
/* Add in tag type plus value into buf */
- rv = AppendAVA(&buf, &buflen, ava);
+ rv = AppendAVA(&strBuf, ava);
if (rv) goto loser;
}
}
- return buf;
+ return strBuf.buffer;
loser:
- PORT_Free(buf);
+ if (strBuf.buffer) {
+ PORT_Free(strBuf.buffer);
+ }
return NULL;
}
@@ -776,7 +793,7 @@ loser:
}
static char *
-CERT_GetNameElement(CERTName *name, int wantedTag)
+CERT_GetNameElement(PRArenaPool *arena, CERTName *name, int wantedTag)
{
CERTRDN** rdns;
CERTRDN *rdn;
@@ -796,7 +813,11 @@ CERT_GetNameElement(CERTName *name, int wantedTag)
if(!decodeItem) {
return NULL;
}
- buf = (char *)PORT_ZAlloc(decodeItem->len + 1);
+ if (arena) {
+ buf = (char *)PORT_ArenaZAlloc(arena,decodeItem->len + 1);
+ } else {
+ buf = (char *)PORT_ZAlloc(decodeItem->len + 1);
+ }
if ( buf ) {
PORT_Memcpy(buf, decodeItem->data, decodeItem->len);
buf[decodeItem->len] = 0;
@@ -825,13 +846,16 @@ CERT_GetCertificateEmailAddress(CERTCertificate *cert)
subAltName.data = NULL;
- rawEmailAddr = CERT_GetNameElement(&(cert->subject), SEC_OID_PKCS9_EMAIL_ADDRESS);
+ rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject),
+ SEC_OID_PKCS9_EMAIL_ADDRESS);
if ( rawEmailAddr == NULL ) {
- rawEmailAddr = CERT_GetNameElement(&(cert->subject), SEC_OID_RFC1274_MAIL);
+ rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject),
+ SEC_OID_RFC1274_MAIL);
}
if ( rawEmailAddr == NULL) {
- rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, &subAltName);
+ rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
+ &subAltName);
if (rv != SECSuccess) {
goto finish;
}
@@ -846,14 +870,16 @@ CERT_GetCertificateEmailAddress(CERTCertificate *cert)
if (nameList != NULL) {
do {
if (current->type == certDirectoryName) {
- rawEmailAddr = CERT_GetNameElement(&(current->name.directoryName),
- SEC_OID_PKCS9_EMAIL_ADDRESS);
+ rawEmailAddr = CERT_GetNameElement(cert->arena,
+ &(current->name.directoryName),
+ SEC_OID_PKCS9_EMAIL_ADDRESS);
if ( rawEmailAddr == NULL ) {
- rawEmailAddr = CERT_GetNameElement(&(current->name.directoryName),
- SEC_OID_RFC1274_MAIL);
+ rawEmailAddr = CERT_GetNameElement(cert->arena,
+ &(current->name.directoryName), SEC_OID_RFC1274_MAIL);
}
} else if (current->type == certRFC822Name) {
- rawEmailAddr = (char*)PORT_ZAlloc(current->name.other.len + 1);
+ rawEmailAddr = (char*)PORT_ArenaZAlloc(cert->arena,
+ current->name.other.len + 1);
if (!rawEmailAddr) {
goto finish;
}
@@ -869,18 +895,12 @@ CERT_GetCertificateEmailAddress(CERTCertificate *cert)
}
}
if (rawEmailAddr) {
- emailAddr = (char*)PORT_ArenaZAlloc(cert->arena, PORT_Strlen(rawEmailAddr) + 1);
- for (i = 0; i <= PORT_Strlen(rawEmailAddr); i++) {
- emailAddr[i] = tolower(rawEmailAddr[i]);
+ for (i = 0; i <= (int) PORT_Strlen(rawEmailAddr); i++) {
+ rawEmailAddr[i] = tolower(rawEmailAddr[i]);
}
- } else {
- emailAddr = NULL;
- }
+ }
finish:
- if ( rawEmailAddr ) {
- PORT_Free(rawEmailAddr);
- }
/* Don't free nameList, it's part of the arena. */
@@ -892,7 +912,7 @@ finish:
SECITEM_FreeItem(&subAltName, PR_FALSE);
}
- return(emailAddr);
+ return(rawEmailAddr);
}
char *
@@ -902,9 +922,9 @@ CERT_GetCertEmailAddress(CERTName *name)
char *emailAddr;
- rawEmailAddr = CERT_GetNameElement(name, SEC_OID_PKCS9_EMAIL_ADDRESS);
+ rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_PKCS9_EMAIL_ADDRESS);
if ( rawEmailAddr == NULL ) {
- rawEmailAddr = CERT_GetNameElement(name, SEC_OID_RFC1274_MAIL);
+ rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_MAIL);
}
emailAddr = CERT_FixupEmailAddr(rawEmailAddr);
if ( rawEmailAddr ) {
@@ -916,54 +936,54 @@ CERT_GetCertEmailAddress(CERTName *name)
char *
CERT_GetCommonName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_COMMON_NAME));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COMMON_NAME));
}
char *
CERT_GetCountryName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_COUNTRY_NAME));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COUNTRY_NAME));
}
char *
CERT_GetLocalityName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_LOCALITY));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_LOCALITY));
}
char *
CERT_GetStateName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_STATE_OR_PROVINCE));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_STATE_OR_PROVINCE));
}
char *
CERT_GetOrgName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_ORGANIZATION_NAME));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATION_NAME));
}
char *
CERT_GetDomainComponentName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_DC));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DC));
}
char *
CERT_GetOrgUnitName(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME));
}
char *
CERT_GetDnQualifier(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_AVA_DN_QUALIFIER));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DN_QUALIFIER));
}
char *
CERT_GetCertUid(CERTName *name)
{
- return(CERT_GetNameElement(name, SEC_OID_RFC1274_UID));
+ return(CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_UID));
}
diff --git a/security/nss/lib/dev/devtoken.c b/security/nss/lib/dev/devtoken.c
index 562e0331c..7c155f9bf 100644
--- a/security/nss/lib/dev/devtoken.c
+++ b/security/nss/lib/dev/devtoken.c
@@ -393,24 +393,25 @@ find_objects
CK_RV ckrv;
CK_ULONG count;
CK_OBJECT_HANDLE *objectHandles;
+ CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE];
PRUint32 arraySize, numHandles;
void *epv = nssToken_GetCryptokiEPV(tok);
nssCryptokiObject **objects;
NSSArena *arena;
nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
+
/* the arena is only for the array of object handles */
- arena = nssArena_Create();
- if (!arena) {
- if (statusOpt) *statusOpt = PR_FAILURE;
- return (nssCryptokiObject **)NULL;
- }
if (maximumOpt > 0) {
arraySize = maximumOpt;
} else {
arraySize = OBJECT_STACK_SIZE;
}
numHandles = 0;
- objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
+ if (arraySize <= OBJECT_STACK_SIZE) {
+ objectHandles = staticObjects;
+ } else {
+ objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize);
+ }
if (!objectHandles) {
goto loser;
}
@@ -462,11 +463,15 @@ find_objects
} else {
objects = NULL;
}
- nssArena_Destroy(arena);
+ if (objectHandles && objectHandles != staticObjects) {
+ nss_ZFreeIf(objectHandles);
+ }
if (statusOpt) *statusOpt = PR_SUCCESS;
return objects;
loser:
- nssArena_Destroy(arena);
+ if (objectHandles && objectHandles != staticObjects) {
+ nss_ZFreeIf(objectHandles);
+ }
if (statusOpt) *statusOpt = PR_FAILURE;
return (nssCryptokiObject **)NULL;
}
@@ -1213,8 +1218,6 @@ nssToken_FindTrustForCertificate
nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
nssCryptokiObject *object, **objects;
- sha1_result.data = sha1; sha1_result.size = sizeof sha1;
- sha1_hash(certEncoding, &sha1_result);
NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
if (searchType == nssTokenSearchType_SessionOnly) {
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
@@ -1222,19 +1225,8 @@ nssToken_FindTrustForCertificate
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
}
NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, tobjc);
- NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result);
-#ifdef NSS_3_4_CODE
- if (!PK11_HasRootCerts(token->pk11slot)) {
-#endif
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER, certIssuer);
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial);
-#ifdef NSS_3_4_CODE
- }
- /*
- * we need to arrange for the built-in token to lose the bottom 2
- * attributes so that old built-in tokens will continue to work.
- */
-#endif
NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
object = NULL;
objects = find_objects_by_template(token, session,
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c
index 973f95f1e..a40384df8 100644
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -287,6 +287,14 @@ PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
return CK_INVALID_HANDLE;
}
+ if ((theTemplate[0].ulValueLen == 0) || (theTemplate[0].ulValueLen == -1)) {
+ PORT_FreeArena(arena,PR_FALSE);
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ return CK_INVALID_HANDLE;
+ }
+
+
+
/*
* issue the find
*/
@@ -3225,24 +3233,20 @@ struct listCertsStr {
};
static PRBool
-isOnList(CERTCertList *certList,CERTCertificate *cert)
+isOnList(CERTCertList *certList,NSSCertificate *c)
{
CERTCertListNode *cln;
for (cln = CERT_LIST_HEAD(certList); !CERT_LIST_END(cln,certList);
cln = CERT_LIST_NEXT(cln)) {
- if (cln->cert == cert) {
+ if (cln->cert->nssCertificate == c) {
return PR_TRUE;
}
}
return PR_FALSE;
}
static SECStatus
-#ifdef NSS_CLASSIC
-pk11ListCertCallback(CERTCertificate *cert, SECItem *derCert, void *arg)
-#else
-pk11ListCertCallback(CERTCertificate *cert, void *arg)
-#endif
+pk11ListCertCallback(NSSCertificate *c, void *arg)
{
struct listCertsStr *listCertP = (struct listCertsStr *)arg;
CERTCertificate *newCert = NULL;
@@ -3260,53 +3264,37 @@ pk11ListCertCallback(CERTCertificate *cert, void *arg)
if ((type == PK11CertListCA) || (type == PK11CertListRootUnique)) {
isCA = PR_TRUE;
}
- /* at this point the nickname is correct for the cert. save it for later */
- if (!isUnique && cert->nickname) {
- nickname = PORT_ArenaStrdup(listCertP->certList->arena,cert->nickname);
- }
-#ifdef NSS_CLASSIC
- if (derCert == NULL) {
- newCert=CERT_DupCertificate(cert);
- } else {
- newCert=CERT_FindCertByDERCert(CERT_GetDefaultCertDB(),&cert->derCert);
- }
-#else
- newCert=CERT_DupCertificate(cert);
-#endif
-
- if (newCert == NULL) return SECSuccess;
- trust = newCert->trust;
/* if we want user certs and we don't have one skip this cert */
if ((type == PK11CertListUser) &&
- ((trust == NULL) ||
- ( ((trust->sslFlags & CERTDB_USER) == 0) &&
- ((trust->emailFlags & CERTDB_USER) == 0) )) ) {
- CERT_DestroyCertificate(newCert);
+ !NSSCertificate_IsPrivateKeyAvailable(c, NULL,NULL)) {
return SECSuccess;
}
/* if we want root certs, skip the user certs */
if ((type == PK11CertListRootUnique) &&
- ((trust) && (((trust->sslFlags & CERTDB_USER ) ||
- (trust->emailFlags & CERTDB_USER))) ) ) {
- CERT_DestroyCertificate(newCert);
+ NSSCertificate_IsPrivateKeyAvailable(c, NULL,NULL)) {
return SECSuccess;
}
-
/* if we want Unique certs and we already have it on our list, skip it */
- if ( isUnique && isOnList(certList,newCert) ) {
- CERT_DestroyCertificate(newCert);
+ if ( isUnique && isOnList(certList,c) ) {
return SECSuccess;
}
+
+ newCert = STAN_GetCERTCertificate(c);
+ if (!newCert) {
+ return SECSuccess;
+ }
/* if we want CA certs and it ain't one, skip it */
if( isCA && (!CERT_IsCACert(newCert, &certType)) ) {
- CERT_DestroyCertificate(newCert);
return SECSuccess;
}
+ CERT_DupCertificate(newCert);
+
+ nickname = STAN_GetCERTCertificateName(c);
/* put slot certs at the end */
if (newCert->slot && !PK11_IsInternal(newCert->slot)) {
@@ -3339,25 +3327,15 @@ PK11_ListCerts(PK11CertListType type, void *pwarg)
#else
NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain();
CERTCertList *certList = NULL;
- struct nss3_cert_cbstr pk11cb;
struct listCertsStr listCerts;
certList = CERT_NewCertList();
listCerts.type = type;
listCerts.certList = certList;
- pk11cb.callback = pk11ListCertCallback;
- pk11cb.arg = &listCerts;
/* authenticate to the slots */
(void) pk11_TraverseAllSlots( NULL, NULL, pwarg);
-#ifdef notdef
- if (type == PK11CertListUser) {
- NSSTrustDomain_TraverseUserCertificates(defaultTD, convert_cert &pk11cb);
- } else {
- NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
- }
-#else
- NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb);
-#endif
+ NSSTrustDomain_TraverseCertificates(defaultTD, pk11ListCertCallback,
+ &listCerts);
return certList;
#endif
}
diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c
index b72582cf4..99c3789ba 100644
--- a/security/nss/lib/softoken/pcertdb.c
+++ b/security/nss/lib/softoken/pcertdb.c
@@ -4054,8 +4054,12 @@ DecodeTrustEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry, SECI
trust->dbEntry = entry;
trust->dbKey.data = pkcs11_copyStaticData(dbKey->data,dbKey->len,
trust->dbKeySpace, sizeof(trust->dbKeySpace));
+ if (!trust->dbKey.data) {
+ PORT_Free(trust);
+ return NULL;
+ }
trust->dbKey.len = dbKey->len;
- SECITEM_CopyItem(NULL, &trust->dbKey , dbKey);
+
trust->trust = &entry->trust;
trust->derCert = &entry->derCert;
@@ -4526,9 +4530,11 @@ nsslowcert_FindTrustByIssuerAndSN(NSSLOWCERTCertDBHandle *handle,
SECItem *sn = &issuerAndSN->serialNumber;
SECItem *issuer = &issuerAndSN->derIssuer;
NSSLOWCERTTrust *trust;
+ unsigned char keyBuf[512];
int data_left = sn->len-1;
int data_len = sn->len;
int index = 0;
+ int len;
/* automatically detect DER encoded serial numbers and remove the der
* encoding since the database expects unencoded data.
@@ -4563,8 +4569,13 @@ nsslowcert_FindTrustByIssuerAndSN(NSSLOWCERTCertDBHandle *handle,
}
certKey.type = 0;
- certKey.data = (unsigned char*)PORT_Alloc(sn->len + issuer->len);
certKey.len = data_len + issuer->len;
+ len = sn->len + issuer->len;
+ if (len > sizeof (keyBuf)) {
+ certKey.data = (unsigned char*)PORT_Alloc(len);
+ } else {
+ certKey.data = keyBuf;
+ }
if ( certKey.data == NULL ) {
return(0);
@@ -4579,12 +4590,12 @@ nsslowcert_FindTrustByIssuerAndSN(NSSLOWCERTCertDBHandle *handle,
trust = nsslowcert_FindTrustByKey(handle, &certKey);
if (trust) {
- PORT_Free(certKey.data);
+ pkcs11_freeStaticData(certKey.data, keyBuf);
return (trust);
}
if (index == 0) {
- PORT_Free(certKey.data);
+ pkcs11_freeStaticData(certKey.data, keyBuf);
return NULL;
}
@@ -4598,7 +4609,7 @@ nsslowcert_FindTrustByIssuerAndSN(NSSLOWCERTCertDBHandle *handle,
trust = nsslowcert_FindTrustByKey(handle, &certKey);
- PORT_Free(certKey.data);
+ pkcs11_freeStaticData(certKey.data, keyBuf);
return(trust);
}
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index 7b750a8da..1642b46a5 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -3410,6 +3410,7 @@ CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession,
PK11Object *object;
PK11Attribute *attribute;
PRBool sensitive;
+ CK_RV crv;
int i;
/*
@@ -3433,17 +3434,20 @@ CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession,
return CKR_USER_NOT_LOGGED_IN;
}
+ crv = CKR_OK;
sensitive = pk11_isTrue(object,CKA_SENSITIVE);
for (i=0; i < (int) ulCount; i++) {
/* Make sure that this attribute is retrievable */
if (sensitive && pk11_isSensitive(pTemplate[i].type,object->objclass)) {
- pk11_FreeObject(object);
- return CKR_ATTRIBUTE_SENSITIVE;
+ crv = CKR_ATTRIBUTE_SENSITIVE;
+ pTemplate[i].ulValueLen = -1;
+ continue;
}
attribute = pk11_FindAttribute(object,pTemplate[i].type);
if (attribute == NULL) {
- pk11_FreeObject(object);
- return CKR_ATTRIBUTE_TYPE_INVALID;
+ crv = CKR_ATTRIBUTE_TYPE_INVALID;
+ pTemplate[i].ulValueLen = -1;
+ continue;
}
if (pTemplate[i].pValue != NULL) {
PORT_Memcpy(pTemplate[i].pValue,attribute->attrib.pValue,
@@ -3454,7 +3458,7 @@ CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession,
}
pk11_FreeObject(object);
- return CKR_OK;
+ return crv;
}
/* NSC_SetAttributeValue modifies the value of one or more object attributes */
diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h
index 2634bac01..ef783b918 100644
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -143,6 +143,7 @@
/* define typedefs, double as forward declarations as well */
typedef struct PK11AttributeStr PK11Attribute;
typedef struct PK11ObjectListStr PK11ObjectList;
+typedef struct PK11ObjectFreeListStr PK11ObjectFreeList;
typedef struct PK11ObjectListElementStr PK11ObjectListElement;
typedef struct PK11ObjectStr PK11Object;
typedef struct PK11SessionObjectStr PK11SessionObject;
@@ -218,6 +219,12 @@ struct PK11ObjectListStr {
PK11Object *parent;
};
+struct PK11ObjectFreeListStr {
+ PK11Object *head;
+ PZLock *lock;
+ int count;
+};
+
/*
* PKCS 11 crypto object structure
*/
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index 260352c41..6be47eb7d 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -1027,7 +1027,6 @@ pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
NSSLOWKEYPublicKey *pubKey;
unsigned char hash[SHA1_LENGTH];
SECItem *item;
- PK11Attribute *attr;
switch (type) {
case CKA_PRIVATE:
@@ -1054,7 +1053,7 @@ pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
((cert->trust->emailFlags & CERTDB_USER) == 0) &&
((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
- return NULL;
+ return (PK11Attribute *) &pk11_StaticNullAttr;
}
pubKey = nsslowcert_ExtractPublicKey(cert);
if (pubKey == NULL) break;
@@ -1792,54 +1791,70 @@ pk11_tokenKeyUnlock(PK11Slot *slot) {
/* allocation hooks that allow us to recycle old object structures */
-static PK11Object * objectFreeList = NULL;
-static PZLock *objectLock = NULL;
-static int object_count = 0;
+static PK11ObjectFreeList sessionObjectList = { NULL, NULL, 0 };
+static PK11ObjectFreeList tokenObjectList = { NULL, NULL, 0 };
PK11Object *
pk11_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace,
- unsigned int hashSize) {
+ PK11ObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject)
+{
PK11Object *object;
+ int size = 0;
if (!optimizeSpace) {
- if (objectLock == NULL) {
- objectLock = PZ_NewLock(nssILockObject);
+ if (list->lock == NULL) {
+ list->lock = PZ_NewLock(nssILockObject);
}
- PK11_USE_THREADS(PZ_Lock(objectLock));
- object = objectFreeList;
+ PK11_USE_THREADS(PZ_Lock(list->lock));
+ object = list->head;
if (object) {
- objectFreeList = object->next;
- object_count--;
+ list->head = object->next;
+ list->count--;
}
- PK11_USE_THREADS(PZ_Unlock(objectLock));
+ PK11_USE_THREADS(PZ_Unlock(list->lock));
if (object) {
object->next = object->prev = NULL;
*hasLocks = PR_TRUE;
return object;
}
}
+ size = isSessionObject ? sizeof(PK11SessionObject)
+ + hashSize *sizeof(PK11Attribute *) : sizeof(PK11TokenObject);
- object = (PK11Object*)PORT_ZAlloc(sizeof(PK11SessionObject) +
- hashSize * sizeof(PK11Attribute *));
- ((PK11SessionObject *)object)->hashSize = hashSize;
+ object = (PK11Object*)PORT_ZAlloc(size);
+ if (isSessionObject) {
+ ((PK11SessionObject *)object)->hashSize = hashSize;
+ }
*hasLocks = PR_FALSE;
return object;
}
static void
-pk11_PutObjectToList(PK11SessionObject *object) {
- if (!object->optimizeSpace && (object_count < MAX_OBJECT_LIST_SIZE)) {
- PK11_USE_THREADS(PZ_Lock(objectLock));
- object->obj.next = objectFreeList;
- objectFreeList = &object->obj;
- object_count++;
- PK11_USE_THREADS(PZ_Unlock(objectLock));
+pk11_PutObjectToList(PK11Object *object, PK11ObjectFreeList *list,
+ PRBool isSessionObject) {
+
+ /* the code below is equivalent to :
+ * optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
+ * just faster.
+ */
+ PRBool optimizeSpace = isSessionObject &&
+ ((PK11SessionObject *)object)->optimizeSpace;
+ if (!optimizeSpace && (list->count < MAX_OBJECT_LIST_SIZE)) {
+ PK11_USE_THREADS(PZ_Lock(list->lock));
+ object->next = list->head;
+ list->head = object;
+ list->count++;
+ PK11_USE_THREADS(PZ_Unlock(list->lock));
return;
}
- PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);)
- PK11_USE_THREADS(PZ_DestroyLock(object->obj.refLock);)
- object->attributeLock = object->obj.refLock = NULL;
+ if (isSessionObject) {
+ PK11SessionObject *so = (PK11SessionObject *)object;
+ PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock);)
+ so->attributeLock = NULL;
+ }
+ PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
+ object->refLock = NULL;
PORT_Free(object);
}
@@ -1851,27 +1866,36 @@ pk11_freeObjectData(PK11Object *object) {
return next;
}
-void
-pk11_CleanupFreeLists()
+static void
+pk11_CleanupFreeList(PK11ObjectFreeList *list, PRBool isSessionList)
{
PK11Object *object;
- if (!objectLock) {
+ if (!list->lock) {
return;
}
- PK11_USE_THREADS(PZ_Lock(objectLock));
- for (object= objectFreeList; object != NULL;
+ PK11_USE_THREADS(PZ_Lock(list->lock));
+ for (object= list->head; object != NULL;
object = pk11_freeObjectData(object)) {
#ifdef PKCS11_USE_THREADS
PZ_DestroyLock(object->refLock);
- PZ_DestroyLock(((PK11SessionObject *)object)->attributeLock);
+ if (isSessionList) {
+ PZ_DestroyLock(((PK11SessionObject *)object)->attributeLock);
+ }
#endif
}
- object_count = 0;
- objectFreeList = NULL;
- PK11_USE_THREADS(PZ_Unlock(objectLock));
- PZ_DestroyLock(objectLock);
- objectLock = NULL;
+ list->count = 0;
+ list->head = NULL;
+ PK11_USE_THREADS(PZ_Unlock(list->lock));
+ PK11_USE_THREADS(PZ_DestroyLock(list->lock));
+ list->lock = NULL;
+}
+
+void
+pk11_CleanupFreeLists(void)
+{
+ pk11_CleanupFreeList(&sessionObjectList, PR_TRUE);
+ pk11_CleanupFreeList(&tokenObjectList, PR_FALSE);
}
@@ -1884,14 +1908,15 @@ pk11_NewObject(PK11Slot *slot)
PK11Object *object;
PK11SessionObject *sessObject;
PRBool hasLocks = PR_FALSE;
- int i;
+ unsigned int i;
unsigned int hashSize = 0;
hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE :
TIME_ATTRIBUTE_HASH_SIZE;
#ifdef PKCS11_STATIC_ATTRIBUTES
- object = pk11_GetObjectFromList(&hasLocks, slot->optimizeSpace, hashSize);
+ object = pk11_GetObjectFromList(&hasLocks, slot->optimizeSpace,
+ &sessionObjectList, hashSize, PR_TRUE);
if (object == NULL) {
return NULL;
}
@@ -2026,15 +2051,14 @@ pk11_DestroyObject(PK11Object *object)
}
if (object->objectInfo) {
(*object->infoFree)(object->objectInfo);
+ object->objectInfo = NULL;
+ object->infoFree = NULL;
}
#ifdef PKCS11_STATIC_ATTRIBUTES
if (so) {
- pk11_PutObjectToList(so);
+ pk11_PutObjectToList(object,&sessionObjectList,PR_TRUE);
} else {
- if (object->refLock) {
- PK11_USE_THREADS(PZ_DestroyLock(object->refLock);)
- }
- PORT_Free(to);
+ pk11_PutObjectToList(object,&tokenObjectList,PR_FALSE);
}
#else
if (object->refLock) {
@@ -2235,7 +2259,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
{
PK11Attribute *attribute;
PK11SessionObject *src_so = pk11_narrowToSessionObject(srcObject);
- int i;
+ unsigned int i;
if (src_so == NULL) {
return CKR_DEVICE_ERROR; /* can't copy token objects yet */
@@ -2319,7 +2343,7 @@ pk11_searchObjectList(PK11SearchResults *search,PK11Object **head,
unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate,
int count, PRBool isLoggedIn)
{
- int i;
+ unsigned int i;
PK11Object *object;
CK_RV crv = CKR_OK;
@@ -2403,7 +2427,7 @@ pk11_update_state(PK11Slot *slot,PK11Session *session)
void
pk11_update_all_states(PK11Slot *slot)
{
- int i;
+ unsigned int i;
PK11Session *session;
for (i=0; i < slot->sessHashSize; i++) {
@@ -2631,10 +2655,12 @@ pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
{
PK11Object *object = NULL;
PK11TokenObject *tokObject = NULL;
+ PRBool hasLocks = PR_FALSE;
SECStatus rv;
#ifdef PKCS11_STATIC_ATTRIBUTES
- object = (PK11Object *) PORT_ZAlloc(sizeof(PK11TokenObject));
+ object = pk11_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0,
+ PR_FALSE);
if (object == NULL) {
return NULL;
}
@@ -2674,7 +2700,9 @@ pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
goto loser;
}
#ifdef PKCS11_USE_THREADS
- object->refLock = PZ_NewLock(nssILockRefLock);
+ if (!hasLocks) {
+ object->refLock = PZ_NewLock(nssILockRefLock);
+ }
if (object->refLock == NULL) {
goto loser;
}