From b0bdf359ef8931a793a8486cd8332dd7fffdffd4 Mon Sep 17 00:00:00 2001 From: "relyea%netscape.com" Date: Tue, 2 Jul 2002 15:11:29 +0000 Subject: 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. --- security/nss/lib/certdb/alg1485.c | 114 ++++++++++++++++++------------- security/nss/lib/dev/devtoken.c | 34 ++++------ security/nss/lib/pk11wrap/pk11cert.c | 70 +++++++------------ security/nss/lib/softoken/pcertdb.c | 21 ++++-- security/nss/lib/softoken/pkcs11.c | 14 ++-- security/nss/lib/softoken/pkcs11i.h | 7 ++ security/nss/lib/softoken/pkcs11u.c | 126 +++++++++++++++++++++-------------- 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; } -- cgit v1.2.1