Patches to reduce the cost of getting attributes on certs or finding certs in lists.

This commit is contained in:
relyea%netscape.com 2002-06-20 18:46:47 +00:00
Родитель 7961794510
Коммит eb95452896
5 изменённых файлов: 244 добавлений и 123 удалений

Просмотреть файл

@ -34,7 +34,7 @@
/*
* Certificate handling code
*
* $Id: lowcert.c,v 1.6 2002/02/21 22:41:37 ian.mcgreer%sun.com Exp $
* $Id: lowcert.c,v 1.7 2002/06/20 18:46:46 relyea%netscape.com Exp $
*/
#include "seccomon.h"
@ -170,20 +170,142 @@ nsslowcert_GetDefaultCertDB(void)
return(default_pcert_db_handle);
}
/*
* simple cert decoder to avoid the cost of asn1 engine
*/
static unsigned char *
nsslowcert_dataStart(unsigned char *buf, int length,
int *data_length, PRBool includeTag) {
unsigned char tag;
int used_length= 0;
tag = buf[used_length++];
/* blow out when we come to the end */
if (tag == 0) {
return NULL;
}
*data_length = buf[used_length++];
if (*data_length&0x80) {
int len_count = *data_length & 0x7f;
*data_length = 0;
while (len_count-- > 0) {
*data_length = (*data_length << 8) | buf[used_length++];
}
}
if (*data_length > (length-used_length) ) {
*data_length = length-used_length;
return NULL;
}
if (includeTag) *data_length += used_length;
return (buf + (includeTag ? 0 : used_length));
}
static int
nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
SECItem *notBefore, SECItem *notAfter)
{
notBefore->data = nsslowcert_dataStart(buf,buf_length,
&notBefore->len,PR_FALSE);
if (notBefore->data == NULL) return SECFailure;
buf_length -= (notBefore->data-buf) + notBefore->len;
buf = notBefore->data + notBefore->len;
notAfter->data = nsslowcert_dataStart(buf,buf_length,
&notAfter->len,PR_FALSE);
if (notAfter->data == NULL) return SECFailure;
return SECSuccess;
}
static int
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
SECItem *valid, SECItem *subjkey)
{
unsigned char *buf;
int buf_length;
unsigned char *dummy;
int dummylen;
/* get past the signature wrap */
buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE);
if (buf == NULL) return SECFailure;
/* get into the raw cert data */
buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE);
if (buf == NULL) return SECFailure;
/* skip past any optional version number */
if ((buf[0] & 0xa0) == 0xa0) {
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy-buf) + dummylen;
buf = dummy + dummylen;
}
/* serial number */
if (derSN) {
derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE);
}
serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE);
if (serial->data == NULL) return SECFailure;
buf_length -= (serial->data-buf) + serial->len;
buf = serial->data + serial->len;
/* skip the OID */
dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE);
if (dummy == NULL) return SECFailure;
buf_length -= (dummy-buf) + dummylen;
buf = dummy + dummylen;
/* issuer */
issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE);
if (issuer->data == NULL) return SECFailure;
buf_length -= (issuer->data-buf) + issuer->len;
buf = issuer->data + issuer->len;
/* only wanted issuer/SN */
if (valid == NULL) {
return SECSuccess;
}
/* validity */
valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE);
if (valid->data == NULL) return SECFailure;
buf_length -= (valid->data-buf) + valid->len;
buf = valid->data + valid->len;
/*subject */
subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE);
if (subject->data == NULL) return SECFailure;
buf_length -= (subject->data-buf) + subject->len;
buf = subject->data + subject->len;
/* subject key info */
subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE);
if (subjkey->data == NULL) return SECFailure;
buf_length -= (subjkey->data-buf) + subjkey->len;
buf = subjkey->data + subjkey->len;
return SECSuccess;
}
SECStatus
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
{
int rv;
NSSLOWCERTValidity validity;
rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
&validity.notBefore,&validity.notAfter);
if (rv != SECSuccess) {
return rv;
}
/* convert DER not-before time */
rv = DER_UTCTimeToTime(notBefore, &c->validity.notBefore);
rv = DER_UTCTimeToTime(notBefore, &validity.notBefore);
if (rv) {
return(SECFailure);
}
/* convert DER not-after time */
rv = DER_UTCTimeToTime(notAfter, &c->validity.notAfter);
rv = DER_UTCTimeToTime(notAfter, &validity.notAfter);
if (rv) {
return(SECFailure);
}
@ -251,6 +373,33 @@ nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
#define SOFT_DEFAULT_CHUNKSIZE 2048
static SECStatus
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
SECItem *key)
{
key->len = sn->len + issuer->len;
key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len);
if ( !key->data ) {
goto loser;
}
/* copy the serialNumber */
PORT_Memcpy(key->data, sn->data, sn->len);
/* copy the issuer */
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
return(SECSuccess);
loser:
return(SECFailure);
}
/*
* take a DER certificate and decode it into a certificate structure
*/
@ -295,15 +444,21 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER,
}
/* decode the certificate info */
rv = SEC_ASN1DecodeItem(arena, cert, nsslowcert_SignedCertificateTemplate,
&cert->derCert);
rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
&cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
&cert->validity, &cert->derSubjKeyInfo);
/*rv = SEC_ASN1DecodeItem(arena, cert, nsslowcert_SignedCertificateTemplate,
&cert->derCert); */
/* cert->subjectKeyID; x509v3 subject key identifier */
cert->dbEntry = NULL;
cert ->trust = NULL;
/* generate and save the database key for the cert */
rv = nsslowcert_KeyFromDERCert(arena, &cert->derCert, &cert->certKey);
/*rv = nsslowcert_KeyFromDERCert(arena, &cert->derCert, &cert->certKey); */
rv = nsslowcert_KeyFromIssuerAndSN(arena, &cert->derIssuer,
&cert->serialNumber, &cert->certKey);
if ( rv ) {
goto loser;
}
@ -372,31 +527,6 @@ nsslowcert_FixupEmailAddr(char *emailAddr)
return(retaddr);
}
static SECStatus
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
SECItem *key)
{
key->len = sn->len + issuer->len;
key->data = (unsigned char*)PORT_ArenaAlloc(arena, key->len);
if ( !key->data ) {
goto loser;
}
/* copy the serialNumber */
PORT_Memcpy(key->data, sn->data, sn->len);
/* copy the issuer */
PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
return(SECSuccess);
loser:
return(SECFailure);
}
/*
* Generate a database key, based on serial number and issuer, from a
@ -406,21 +536,12 @@ SECStatus
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
{
int rv;
NSSLOWCERTSignedData sd;
NSSLOWCERTCertKey certkey;
PORT_Memset(&sd, 0, sizeof(NSSLOWCERTSignedData));
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
&certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
rv = SEC_ASN1DecodeItem(arena, &sd, nsslowcert_SignedDataTemplate, derCert);
if ( rv ) {
goto loser;
}
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
rv = SEC_ASN1DecodeItem(arena, &certkey,
nsslowcert_CertKeyTemplate, &sd.data);
PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
if ( rv ) {
goto loser;
@ -435,7 +556,7 @@ loser:
NSSLOWKEYPublicKey *
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
{
NSSLOWCERTSubjectPublicKeyInfo *spki = &cert->subjectPublicKeyInfo;
NSSLOWCERTSubjectPublicKeyInfo *spki = cert->subjectPublicKeyInfo;
NSSLOWKEYPublicKey *pubk;
SECItem os;
SECStatus rv;
@ -455,6 +576,23 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
pubk->arena = arena;
/* we haven't bothered decoding the spki struct yet, do it now */
if (spki == NULL) {
spki = (NSSLOWCERTSubjectPublicKeyInfo *) PORT_ArenaZAlloc(cert->arena,
sizeof(NSSLOWCERTSubjectPublicKeyInfo));
if (spki == NULL) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
rv = SEC_ASN1DecodeItem(cert->arena, spki,
nsslowcert_SubjectPublicKeyInfoTemplate, &cert->derSubjKeyInfo);
if (rv != SECSuccess) {
PORT_FreeArena (arena, PR_FALSE);
return NULL;
}
cert->subjectPublicKeyInfo = spki;
}
/* Convert bit string length from bits to bytes */
os = spki->subjectPublicKey;
DER_ConvertBitString (&os);

Просмотреть файл

@ -34,7 +34,7 @@
/*
* Permanent Certificate database handling code
*
* $Id: pcertdb.c,v 1.21 2002/06/13 23:25:37 relyea%netscape.com Exp $
* $Id: pcertdb.c,v 1.22 2002/06/20 18:46:46 relyea%netscape.com Exp $
*/
#include "prtime.h"
@ -373,14 +373,19 @@ ReadDBEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCommon *entry,
/* format body of entry for return to caller */
dbentry->len = data.size - SEC_DB_ENTRY_HEADER_LEN;
if ( dbentry->len ) {
dbentry->data = (unsigned char *)PORT_ArenaAlloc(arena, dbentry->len);
if ( dbentry->data == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
if (arena) {
dbentry->data = (unsigned char *)
PORT_ArenaAlloc(arena, dbentry->len);
if ( dbentry->data == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
PORT_Memcpy(dbentry->data, &buf[SEC_DB_ENTRY_HEADER_LEN],
PORT_Memcpy(dbentry->data, &buf[SEC_DB_ENTRY_HEADER_LEN],
dbentry->len);
} else {
dbentry->data = &buf[SEC_DB_ENTRY_HEADER_LEN];
}
} else {
dbentry->data = NULL;
}
@ -497,8 +502,15 @@ loser:
static SECStatus
EncodeDBCertKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey)
{
dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN;
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
unsigned int len = certKey->len + SEC_DB_KEY_HEADER_LEN;
if (arena) {
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
} else {
if (dbkey->len < len) {
dbkey->data = (unsigned char *)PORT_Alloc(dbkey->len);
}
}
dbkey->len = len;
if ( dbkey->data == NULL ) {
goto loser;
}
@ -837,15 +849,12 @@ static SECStatus
DeleteDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
{
SECItem dbkey;
PRArenaPool *arena = NULL;
SECStatus rv;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if ( arena == NULL ) {
goto loser;
}
rv = EncodeDBCertKey(certKey, arena, &dbkey);
dbkey.data= NULL;
dbkey.len = 0;
rv = EncodeDBCertKey(certKey, NULL, &dbkey);
if ( rv != SECSuccess ) {
goto loser;
}
@ -855,14 +864,15 @@ DeleteDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
goto loser;
}
PORT_FreeArena(arena, PR_FALSE);
if (dbkey.data) {
PORT_Free(dbkey.data);
}
return(SECSuccess);
loser:
if ( arena ) {
PORT_FreeArena(arena, PR_FALSE);
if (dbkey.data) {
PORT_Free(dbkey.data);
}
return(SECFailure);
}
@ -873,11 +883,14 @@ static certDBEntryCert *
ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
{
PRArenaPool *arena = NULL;
PRArenaPool *tmparena = NULL;
certDBEntryCert *entry;
SECItem dbkey;
SECItem dbentry;
SECStatus rv;
unsigned char buf[512];
dbkey.data = buf;
dbkey.len = sizeof(buf);
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if ( arena == NULL ) {
@ -885,12 +898,6 @@ ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
goto loser;
}
tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if ( tmparena == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
entry = (certDBEntryCert *)PORT_ArenaAlloc(arena, sizeof(certDBEntryCert));
if ( entry == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
@ -899,12 +906,12 @@ ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
entry->common.arena = arena;
entry->common.type = certDBEntryTypeCert;
rv = EncodeDBCertKey(certKey, tmparena, &dbkey);
rv = EncodeDBCertKey(certKey, NULL, &dbkey);
if ( rv != SECSuccess ) {
goto loser;
}
rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, tmparena);
rv = ReadDBEntry(handle, &entry->common, &dbkey, &dbentry, NULL);
if ( rv == SECFailure ) {
goto loser;
}
@ -914,12 +921,14 @@ ReadDBCertEntry(NSSLOWCERTCertDBHandle *handle, SECItem *certKey)
goto loser;
}
PORT_FreeArena(tmparena, PR_FALSE);
if (dbkey.data && dbkey.data != buf) {
PORT_Free(dbkey.data);
}
return(entry);
loser:
if ( tmparena ) {
PORT_FreeArena(tmparena, PR_FALSE);
if (dbkey.data && dbkey.data != buf) {
PORT_Free(dbkey.data);
}
if ( arena ) {
PORT_FreeArena(arena, PR_FALSE);
@ -4160,27 +4169,12 @@ loser:
static NSSLOWCERTCertificate *
FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb)
{
SECItem keyitem;
DBT key;
SECStatus rv;
NSSLOWCERTCertificate *cert = NULL;
PRArenaPool *arena = NULL;
certDBEntryCert *entry;
PRBool locked = PR_FALSE;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if ( arena == NULL ) {
goto loser;
}
rv = EncodeDBCertKey(certKey, arena, &keyitem);
if ( rv != SECSuccess ) {
goto loser;
}
key.data = keyitem.data;
key.size = keyitem.len;
if ( lockdb ) {
locked = PR_TRUE;
nsslowcert_LockDB(handle);
@ -4206,10 +4200,6 @@ loser:
if ( locked ) {
nsslowcert_UnlockDB(handle);
}
if ( arena ) {
PORT_FreeArena(arena, PR_FALSE);
}
return(cert);
}
@ -4220,27 +4210,12 @@ loser:
static NSSLOWCERTTrust *
FindTrustByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey, PRBool lockdb)
{
SECItem keyitem;
DBT key;
SECStatus rv;
NSSLOWCERTTrust *trust = NULL;
PRArenaPool *arena = NULL;
certDBEntryCert *entry;
PRBool locked = PR_FALSE;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if ( arena == NULL ) {
goto loser;
}
rv = EncodeDBCertKey(certKey, arena, &keyitem);
if ( rv != SECSuccess ) {
goto loser;
}
key.data = keyitem.data;
key.size = keyitem.len;
if ( lockdb ) {
locked = PR_TRUE;
nsslowcert_LockDB(handle);
@ -4270,10 +4245,6 @@ loser:
if ( locked ) {
nsslowcert_UnlockDB(handle);
}
if ( arena ) {
PORT_FreeArena(arena, PR_FALSE);
}
return(trust);
}

Просмотреть файл

@ -33,7 +33,7 @@
/*
* certt.h - public data structures for the certificate library
*
* $Id: pcertt.h,v 1.4 2002/05/16 20:39:03 relyea%netscape.com Exp $
* $Id: pcertt.h,v 1.5 2002/06/20 18:46:46 relyea%netscape.com Exp $
*/
#ifndef _PCERTT_H_
#define _PCERTT_H_
@ -133,11 +133,13 @@ struct NSSLOWCERTCertificateStr {
SECItem derCert; /* original DER for the cert */
SECItem derIssuer; /* DER for issuer name */
SECItem derSN;
SECItem serialNumber;
SECItem derSubject; /* DER for subject name */
NSSLOWCERTSubjectPublicKeyInfo subjectPublicKeyInfo;
SECItem derSubjKeyInfo;
NSSLOWCERTSubjectPublicKeyInfo *subjectPublicKeyInfo;
SECItem certKey; /* database key for this cert */
NSSLOWCERTValidity validity;
SECItem validity;
certDBEntryCert *dbEntry; /* database entry struct */
SECItem subjectKeyID; /* x509v3 subject key identifier */
char *nickname;

Просмотреть файл

@ -3764,6 +3764,11 @@ pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn,
if (keyHandle->version != 3) {
return;
}
/* don't do the traversal if it can't possibly be the correct id */
/* all soft token id's are SHA1_HASH_LEN's */
if (key_id->len != SHA1_LENGTH) {
return;
}
}
keyData.slot = slot;
keyData.searchHandles = search;

Просмотреть файл

@ -284,6 +284,9 @@ static const PK11Attribute pk11_StaticTrueAttr =
static const PK11Attribute pk11_StaticFalseAttr =
PK11_DEF_ATTRIBUTE(&pk11_staticFalseValue,sizeof(pk11_staticFalseValue));
static const PK11Attribute pk11_StaticNullAttr = PK11_DEF_ATTRIBUTE(NULL,0);
char pk11_StaticOneValue = 1;
static const PK11Attribute pk11_StaticOneAttr =
PK11_DEF_ATTRIBUTE(&pk11_StaticOneValue,sizeof(pk11_StaticOneValue));
CK_CERTIFICATE_TYPE pk11_staticX509Value = CKC_X_509;
static const PK11Attribute pk11_StaticX509Attr =
@ -622,7 +625,7 @@ pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB,
&object->dbKey, object->obj.slot->password);
if (label == NULL) {
return (PK11Attribute *)&pk11_StaticNullAttr;
return (PK11Attribute *)&pk11_StaticOneAttr;
}
att = pk11_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE);
PORT_Free(label);
@ -1048,6 +1051,11 @@ pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
return pk11_NewTokenAttribute(type,cert->derCert.data,
cert->derCert.len,PR_FALSE);
case CKA_ID:
if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
((cert->trust->emailFlags & CERTDB_USER) == 0) &&
((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
return (PK11Attribute *)&pk11_StaticNullAttr;
}
pubKey = nsslowcert_ExtractPublicKey(cert);
if (pubKey == NULL) break;
item = pk11_GetPubItem(pubKey);
@ -1070,11 +1078,8 @@ pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type)
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;
return pk11_NewTokenAttribute(type,cert->derSN.data,
cert->derSN.len, PR_FALSE);
case CKA_NETSCAPE_EMAIL:
return cert->emailAddr ? pk11_NewTokenAttribute(type, cert->emailAddr,
PORT_Strlen(cert->emailAddr), PR_FALSE) :