Implement the CRL cache . Bug 149854

This commit is contained in:
jpierre%netscape.com 2002-08-30 22:57:03 +00:00
parent c8c32a582e
commit 29333f104f
10 changed files with 1119 additions and 64 deletions

View File

@ -34,7 +34,7 @@
/*
* cert.h - public data structures and prototypes for the certificate library
*
* $Id: cert.h,v 1.20 2002/08/07 03:42:45 jpierre%netscape.com Exp $
* $Id: cert.h,v 1.21 2002/08/30 22:56:51 jpierre%netscape.com Exp $
*/
#ifndef _CERT_H_
@ -408,6 +408,7 @@ CERT_DecodeDERCrlEx(PRArenaPool *narena, SECItem *derSignedCrl, int type,
#define CRL_DECODE_DONT_COPY_DER 0x00000001
#define CRL_DECODE_SKIP_ENTRIES 0x00000002
#define CRL_DECODE_KEEP_BAD_CRL 0x00000004
/* complete the decoding of a partially decoded CRL, ie. decode the
entries. Note that entries is an optional field in a CRL, so the
@ -1429,6 +1430,14 @@ CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert,
*/
extern SECStatus CERT_GetCertType(CERTCertificate *cert);
SECStatus InitCRLCache(void);
SECStatus ShutdownCRLCache(void);
SECStatus CERT_CheckCRL(CERTCertificate* cert, CERTCertificate* issuer,
SECItem* dp, int64 t, void* wincx);
SEC_END_PROTOS
#endif /* _CERT_H_ */

View File

@ -31,20 +31,147 @@
* GPL.
*/
/*
* certt.h - public data structures for the certificate library
* certi.h - private data structures for the certificate library
*
* $Id: certi.h,v 1.1 2002/08/07 03:42:46 jpierre%netscape.com Exp $
* $Id: certi.h,v 1.2 2002/08/30 22:56:52 jpierre%netscape.com Exp $
*/
#ifndef _CERTI_H_
#define _CERTI_H_
#include "certt.h"
#include "nssrwlkt.h"
typedef struct OpaqueCRLFieldsStr OpaqueCRLFields;
#define USE_RWLOCK 1
/* all definitions in this file are subject to change */
typedef struct OpaqueCRLFieldsStr OpaqueCRLFields;
typedef struct CRLEntryCacheStr CRLEntryCache;
typedef struct CRLDPCacheStr CRLDPCache;
typedef struct CRLIssuerCacheStr CRLIssuerCache;
typedef struct CRLCacheStr CRLCache;
struct OpaqueCRLFieldsStr {
/* these fields are subject to change */
PRBool partial;
PRBool bad;
PRBool badDER;
PRBool badExtensions;
PRBool deleted;
PRBool heapDER;
};
typedef struct PreAllocatorStr PreAllocator;
struct PreAllocatorStr
{
PRSize len;
void* data;
PRSize used;
PRArenaPool* arena;
PRSize extra;
};
/* CRL entry cache.
This is the same as an entry plus the next/prev pointers for the hash table
*/
struct CRLEntryCacheStr {
CERTCrlEntry entry;
CRLEntryCache *prev, *next;
};
#define CRL_CACHE_INVALID_CRLS 0x0001 /* this state will be set
if we have CRL objects with an invalid DER or signature. Can be
cleared if the invalid objects are deleted from the token */
#define CRL_CACHE_LAST_FETCH_FAILED 0x0002 /* this state will be set
if the last CRL fetch encountered an error. Can be cleared if a
new fetch succeeds */
/* CRL distribution point cache object
This is a cache of CRL entries for a given distribution point of an issuer
It is built from a collection of one full and 0 or more delta CRLs.
*/
struct CRLDPCacheStr {
#ifdef USE_RWLOCK
NSSRWLock* lock;
#else
PRLock* lock;
#endif
CERTCertificate* issuer; /* DER of cert issuer */
SECItem* distributionPoint; /* DER of distribution point. This may be
NULL when distribution points aren't
in use (ie. the CA has a single CRL) */
/* hash table of entries. We use a PLHashTable and pre-allocate the
required amount of memory in one shot, so that our allocator can
simply pass offsets into it when hashing.
This won't work anymore when we support delta CRLs and iCRLs, because
the size of the hash table will vary over time. At that point, the best
solution will be to allocate large CRLEntry structures by modifying
the DER decoding template. The extra space would be for next/prev
pointers. This would allow entries from different CRLs to be mixed in
the same hash table.
*/
PLHashTable* entries;
PreAllocator* prebuffer; /* big pre-allocated buffer mentioned above */
/* array of CRLs matching this distribution point */
PRUint32 ncrls; /* total number of CRLs in crls */
CERTSignedCrl** crls; /* array of all matching DER CRLs
from all tokens */
/* XCRL With iCRLs and multiple DPs, the CRL can be shared accross several
issuers. In the future, we'll need to globally recycle the CRL in a
separate list in order to avoid extra lookups, decodes, and copies */
/* pointers to good decoded CRLs used to build the cache */
CERTSignedCrl* full; /* full CRL used for the cache */
#if 0
/* for future use */
PRInt32 numdeltas; /* number of delta CRLs used for the cache */
CERTSignedCrl** deltas; /* delta CRLs used for the cache */
#endif
/* invalidity bitflag */
PRUint16 invalid; /* this state will be set if either
CRL_CACHE_INVALID_CRLS or CRL_CACHE_LAST_FETCH_FAILED is set.
In those cases, all certs are considered revoked as a
security precaution. The invalid state can only be cleared
during an update if all error states are cleared */
};
/* CRL issuer cache object
This object tracks all the distribution point caches for a given issuer.
XCRL once we support multiple issuing distribution points, this object
will be a hash table. For now, it just holds the single CRL distribution
point cache structure.
*/
struct CRLIssuerCacheStr {
PRUint32 refcount;
CERTCertificate* issuer;
CRLDPCache dp;
CRLDPCache* dpp;
#if 0
/* XCRL for future use.
We don't need to lock at the moment because we only have one DP,
which gets created at the same time as this object */
NSSRWLock* lock;
CRLDPCache** dps;
PLHashTable* distributionpoints;
#endif
};
/* CRL revocation cache object
This object tracks all the issuer caches
*/
struct CRLCacheStr {
PRLock* lock;
/* hash table of issuer to CRLIssuerCacheStr,
indexed by issuer DER subject */
PLHashTable* issuers;
};
#endif /* _CERTI_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -113,7 +113,7 @@ CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
if ( !pubKey ) {
return(SECFailure);
}
/* check the signature */
sig = sd->signature;
DER_ConvertBitString(&sig);
@ -267,37 +267,7 @@ SECStatus
SEC_CheckCRL(CERTCertDBHandle *handle,CERTCertificate *cert,
CERTCertificate *caCert, int64 t, void * wincx)
{
CERTSignedCrl *crl = NULL;
SECStatus rv = SECSuccess;
CERTCrlEntry **crlEntry;
/* first look up the CRL */
crl = SEC_FindCrlByName(handle,&caCert->derSubject, SEC_CRL_TYPE);
if (crl == NULL) {
/* XXX for now no CRL is ok */
goto done;
}
/* now verify the CRL signature */
rv = CERT_VerifySignedData(&crl->signatureWrap, caCert, t, wincx);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
rv = SECWouldBlock; /* Soft error, ask the user */
goto done;
}
/* now make sure the key is not on the revocation list */
for (crlEntry = crl->crl.entries; crlEntry && *crlEntry; crlEntry++) {
if (SECITEM_CompareItem(&(*crlEntry)->serialNumber,&cert->serialNumber) == SECEqual) {
PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
rv = SECFailure; /* cert is revoked */
goto done;
}
}
done:
if (crl) SEC_DestroyCrl(crl);
return rv;
return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
}
/*

View File

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.25 $ $Date: 2002/08/27 23:37:55 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: ckhelper.c,v $ $Revision: 1.26 $ $Date: 2002/08/30 22:56:57 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSCKEPV_H
@ -611,6 +611,8 @@ nssCryptokiCRL_GetAttributes
nssSession *sessionOpt,
NSSArena *arenaOpt,
NSSItem *encodingOpt,
NSSItem *subjectOpt,
CK_ULONG* crl_class,
NSSUTF8 **urlOpt,
PRBool *isKRLOpt
)
@ -619,11 +621,14 @@ nssCryptokiCRL_GetAttributes
NSSSlot *slot;
nssSession *session;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE crl_template[5];
CK_ATTRIBUTE crl_template[7];
CK_ULONG crl_size;
PRUint32 i;
NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
if (crl_class) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
}
if (encodingOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
}
@ -633,6 +638,9 @@ nssCryptokiCRL_GetAttributes
if (isKRLOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NETSCAPE_KRL);
}
if (subjectOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
}
NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
@ -655,6 +663,9 @@ nssCryptokiCRL_GetAttributes
}
i=0;
if (crl_class) {
NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class); i++;
}
if (encodingOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt); i++;
}
@ -664,6 +675,9 @@ nssCryptokiCRL_GetAttributes
if (isKRLOpt) {
NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt); i++;
}
if (subjectOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt); i++;
}
return PR_SUCCESS;
}

View File

@ -41,7 +41,7 @@
#define CKHELPER_H
#ifdef DEBUG
static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.16 $ $Date: 2002/04/18 17:29:53 $ $Name: $";
static const char CKHELPER_CVS_ID[] = "@(#) $RCSfile: ckhelper.h,v $ $Revision: 1.17 $ $Date: 2002/08/30 22:56:58 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSCKT_H
@ -118,6 +118,11 @@ NSS_EXTERN_DATA const NSSItem g_ck_class_privkey;
} \
}
#define NSS_CK_ATTRIBUTE_TO_ULONG(attrib, ulongvar) \
if ((attrib)->ulValueLen > 0) { \
ulongvar = *((CK_ULONG*)(attrib)->pValue); \
}
/* NSS_CK_ATTRIBUTE_TO_UTF8(attrib, str)
*
* Convert a CK_ATTRIBUTE to a string.

View File

@ -41,7 +41,7 @@
*/
#ifdef DEBUG
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.30 $ $Date: 2002/08/27 23:37:56 $ $Name: $";
static const char DEV_CVS_ID[] = "@(#) $RCSfile: dev.h,v $ $Revision: 1.31 $ $Date: 2002/08/30 22:56:58 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSCKT_H
@ -755,6 +755,8 @@ nssCryptokiCRL_GetAttributes
nssSession *sessionOpt,
NSSArena *arenaOpt,
NSSItem *encodingOpt,
NSSItem * subjectOpt,
CK_ULONG * crl_class,
NSSUTF8 **urlOpt,
PRBool *isKRLOpt
);

View File

@ -32,7 +32,7 @@
* may use your version of this file under either the MPL or the
* GPL.
*
# $Id: nssinit.c,v 1.54 2002/07/18 23:08:55 jpierre%netscape.com Exp $
# $Id: nssinit.c,v 1.55 2002/08/30 22:56:59 jpierre%netscape.com Exp $
*/
#include <ctype.h>
@ -411,6 +411,10 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix,
return SECSuccess;
}
if (SECSuccess != InitCRLCache()) {
return SECFailure;
}
flags = nss_makeFlags(readOnly,noCertDB,noModDB,forceOpen,
pk11_password_required, optimizeSpace);
if (flags == NULL) return rv;
@ -536,6 +540,7 @@ NSS_Shutdown(void)
{
SECStatus rv;
ShutdownCRLCache();
SECOID_Shutdown();
STAN_Shutdown();
rv = SECMOD_Shutdown();

View File

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.40 $ $Date: 2002/08/29 22:11:06 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: certificate.c,v $ $Revision: 1.41 $ $Date: 2002/08/30 22:57:03 $ $Name: $";
#endif /* DEBUG */
#ifndef NSSPKI_H
@ -1098,6 +1098,8 @@ nssCRL_Create
NULL, /* XXX sessionOpt */
arena,
&rvCRL->encoding,
NULL, /* subject */
NULL, /* class */
&rvCRL->url,
&rvCRL->isKRL);
if (status != PR_SUCCESS) {

View File

@ -32,7 +32,7 @@
*/
#ifdef DEBUG
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.13 $ $Date: 2002/08/02 17:43:36 $ $Name: $";
static const char CVS_ID[] = "@(#) $RCSfile: pkibase.c,v $ $Revision: 1.14 $ $Date: 2002/08/30 22:57:03 $ $Name: $";
#endif /* DEBUG */
#ifndef DEV_H
@ -1157,6 +1157,8 @@ crl_getUIDFromInstance(nssCryptokiObject *instance, NSSItem *uid,
NULL, /* XXX sessionOpt */
arena, /* arena */
&uid[0], /* encoding */
NULL, /* subject */
NULL, /* class */
NULL, /* url */
NULL); /* isKRL */
}