Fix for 243585 - add the ability to use CRL objects from RAM . r=nelson, neil.williams

This commit is contained in:
julien.pierre.bugs%sun.com 2005-02-15 06:26:43 +00:00
Родитель 1d28e9d8ef
Коммит 1b8fc2a9d7
7 изменённых файлов: 1719 добавлений и 499 удалений

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

@ -37,7 +37,7 @@
/* /*
* cert.h - public data structures and prototypes for the certificate library * cert.h - public data structures and prototypes for the certificate library
* *
* $Id: cert.h,v 1.48 2004/11/09 06:13:32 wchang0222%aol.com Exp $ * $Id: cert.h,v 1.49 2005/02/15 06:26:42 julien.pierre.bugs%sun.com Exp $
*/ */
#ifndef _CERT_H_ #ifndef _CERT_H_
@ -428,6 +428,7 @@ CERT_DecodeDERCrlWithFlags(PRArenaPool *narena, SECItem *derSignedCrl,
#define CRL_DECODE_DONT_COPY_DER 0x00000001 #define CRL_DECODE_DONT_COPY_DER 0x00000001
#define CRL_DECODE_SKIP_ENTRIES 0x00000002 #define CRL_DECODE_SKIP_ENTRIES 0x00000002
#define CRL_DECODE_KEEP_BAD_CRL 0x00000004 #define CRL_DECODE_KEEP_BAD_CRL 0x00000004
#define CRL_DECODE_ADOPT_HEAP_DER 0x00000008
/* complete the decoding of a partially decoded CRL, ie. decode the /* complete the decoding of a partially decoded CRL, ie. decode the
entries. Note that entries is an optional field in a CRL, so the entries. Note that entries is an optional field in a CRL, so the
@ -452,6 +453,18 @@ extern void CERT_DestroyCrl (CERTSignedCrl *crl);
the issuer (CA). */ the issuer (CA). */
void CERT_CRLCacheRefreshIssuer(CERTCertDBHandle* dbhandle, SECItem* crlKey); void CERT_CRLCacheRefreshIssuer(CERTCertDBHandle* dbhandle, SECItem* crlKey);
/* add the specified RAM CRL object to the cache.
Once a CRL is added to the cache, the application must hold on to the
memory, because the cache will reference it directly. It can only
free it after it calls CERT_UncacheCRL .
*/
SECStatus CERT_CacheCRL(CERTCertDBHandle* dbhandle, SECItem* newcrl);
/* remove a previously added CRL object from the CRL cache. It is OK
for the application to free the memory after a successful removal
*/
SECStatus CERT_UncacheCRL(CERTCertDBHandle* dbhandle, SECItem* oldcrl);
/* /*
** Decode a certificate and put it into the temporary certificate database ** Decode a certificate and put it into the temporary certificate database
*/ */

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

@ -36,7 +36,7 @@
/* /*
* certi.h - private data structures for the certificate library * certi.h - private data structures for the certificate library
* *
* $Id: certi.h,v 1.11 2004/04/25 15:03:03 gerv%gerv.net Exp $ * $Id: certi.h,v 1.12 2005/02/15 06:26:42 julien.pierre.bugs%sun.com Exp $
*/ */
#ifndef _CERTI_H_ #ifndef _CERTI_H_
#define _CERTI_H_ #define _CERTI_H_
@ -44,7 +44,11 @@
#include "certt.h" #include "certt.h"
#include "nssrwlkt.h" #include "nssrwlkt.h"
#define USE_RWLOCK 1 /*
#define GLOBAL_RWLOCK 1
*/
#define DPC_RWLOCK 1
/* all definitions in this file are subject to change */ /* all definitions in this file are subject to change */
@ -53,16 +57,15 @@ typedef struct CRLEntryCacheStr CRLEntryCache;
typedef struct CRLDPCacheStr CRLDPCache; typedef struct CRLDPCacheStr CRLDPCache;
typedef struct CRLIssuerCacheStr CRLIssuerCache; typedef struct CRLIssuerCacheStr CRLIssuerCache;
typedef struct CRLCacheStr CRLCache; typedef struct CRLCacheStr CRLCache;
typedef struct CachedCrlStr CachedCrl;
struct OpaqueCRLFieldsStr { struct OpaqueCRLFieldsStr {
PRBool partial; PRBool partial;
PRBool decodingError;
PRBool badEntries; PRBool badEntries;
PRBool bad;
PRBool badDER; PRBool badDER;
PRBool badExtensions; PRBool badExtensions;
PRBool deleted;
PRBool heapDER; PRBool heapDER;
PRBool unverified;
}; };
typedef struct PreAllocatorStr PreAllocator; typedef struct PreAllocatorStr PreAllocator;
@ -95,23 +98,14 @@ struct CRLEntryCacheStr {
#define CRL_CACHE_OUT_OF_MEMORY 0x0004 /* this state will be set #define CRL_CACHE_OUT_OF_MEMORY 0x0004 /* this state will be set
if we don't have enough memory to build the hash table of entries */ if we don't have enough memory to build the hash table of entries */
/* CRL distribution point cache object typedef enum {
This is a cache of CRL entries for a given distribution point of an issuer CRL_OriginToken = 0, /* CRL came from PKCS#11 token */
It is built from a collection of one full and 0 or more delta CRLs. CRL_OriginExplicit = 1, /* CRL was explicitly added to the cache, from RAM */
*/ } CRLOrigin;
struct CRLDPCacheStr {
#ifdef USE_RWLOCK
NSSRWLock* lock;
#else
PRLock* lock;
#endif
CERTCertificate* issuer; /* cert issuer */
SECItem* subject; /* DER of issuer subject */
SECItem* distributionPoint; /* DER of distribution point. This may be
NULL when distribution points aren't
in use (ie. the CA has a single CRL) */
struct CachedCrlStr {
CERTSignedCrl* crl;
CRLOrigin origin;
/* hash table of entries. We use a PLHashTable and pre-allocate the /* hash table of entries. We use a PLHashTable and pre-allocate the
required amount of memory in one shot, so that our allocator can required amount of memory in one shot, so that our allocator can
simply pass offsets into it when hashing. simply pass offsets into it when hashing.
@ -125,30 +119,110 @@ struct CRLDPCacheStr {
*/ */
PLHashTable* entries; PLHashTable* entries;
PreAllocator* prebuffer; /* big pre-allocated buffer mentioned above */ PreAllocator* prebuffer; /* big pre-allocated buffer mentioned above */
PRBool sigChecked; /* this CRL signature has already been checked */
PRBool sigValid; /* signature verification status .
Only meaningful if checked is PR_TRUE . */
};
/* array of CRLs matching this distribution point */ /* constructor */
SECStatus CachedCrl_Create(CachedCrl** returned, CERTSignedCrl* crl,
CRLOrigin origin);
/* destructor */
SECStatus CachedCrl_Destroy(CachedCrl* crl);
/* create hash table of CRL entries */
SECStatus CachedCrl_Populate(CachedCrl* crlobject);
/* empty the cache content */
SECStatus CachedCrl_Depopulate(CachedCrl* crl);
/* are these CRLs the same, as far as the cache is concerned ?
Or are they the same token object, but with different DER ? */
static SECStatus CachedCrl_Compare(CachedCrl* a, CachedCrl* b, PRBool* isDupe,
PRBool* isUpdated);
/* 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 DPC_RWLOCK
NSSRWLock* lock;
#else
PRLock* lock;
#endif
CERTCertificate* issuer; /* cert issuer
XXX there may be multiple issuer certs,
with different validity dates. Also
need to deal with SKID/AKID . See
bugzilla 217387, 233118 */
SECItem* subject; /* DER of issuer subject */
SECItem* distributionPoint; /* DER of distribution point. This may be
NULL when distribution points aren't
in use (ie. the CA has a single CRL).
Currently not used. */
/* array of full CRLs matching this distribution point */
PRUint32 ncrls; /* total number of CRLs in crls */ PRUint32 ncrls; /* total number of CRLs in crls */
CERTSignedCrl** crls; /* array of all matching DER CRLs CachedCrl** crls; /* array of all matching CRLs */
from all tokens */
/* XCRL With iCRLs and multiple DPs, the CRL can be shared accross several /* 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 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 */ separate list in order to avoid extra lookups, decodes, and copies */
/* pointers to good decoded CRLs used to build the cache */ /* pointers to good decoded CRLs used to build the cache */
CERTSignedCrl* full; /* full CRL used for the cache */ CachedCrl* selected; /* full CRL selected for use in the cache */
#if 0 #if 0
/* for future use */ /* for future use */
PRInt32 numdeltas; /* number of delta CRLs used for the cache */ PRInt32 numdeltas; /* number of delta CRLs used for the cache */
CERTSignedCrl** deltas; /* delta CRLs used for the cache */ CachedCrl** deltas; /* delta CRLs used for the cache */
#endif #endif
/* invalidity bitflag */ /* cache invalidity bitflag */
PRUint16 invalid; /* this state will be set if either PRUint16 invalid; /* this state will be set if either
CRL_CACHE_INVALID_CRLS or CRL_CACHE_LAST_FETCH_FAILED is set. CRL_CACHE_INVALID_CRLS or CRL_CACHE_LAST_FETCH_FAILED is set.
In those cases, all certs are considered revoked as a In those cases, all certs are considered revoked as a
security precaution. The invalid state can only be cleared security precaution. The invalid state can only be cleared
during an update if all error states are cleared */ during an update if all error states are cleared */
PRBool refresh; /* manual refresh from tokens has been forced */
PRBool mustchoose; /* trigger reselection algorithm, for case when
RAM CRL objects are dropped from the cache */
PRIntervalTime lastfetch; /* time a CRL token fetch was last performed */
PRIntervalTime lastcheck; /* time CRL token objects were last checked for
existence */
}; };
/* create a DPCache object */
SECStatus DPCache_Create(CRLDPCache** returned, CERTCertificate* issuer,
SECItem* subject, SECItem* dp);
/* destructor for CRL DPCache object */
SECStatus DPCache_Destroy(CRLDPCache* cache);
/* add a new CRL object to the dynamic array of CRLs of the DPCache, and
returns the cached CRL object . Needs write access to DPCache. */
SECStatus DPCache_AddCRL(CRLDPCache* cache, CachedCrl* crl, PRBool* added);
/* fetch the CRL for this DP from the PKCS#11 tokens */
SECStatus DPCache_FetchFromTokens(CRLDPCache* cache, PRTime vfdate, void* wincx);
/* check if a particular SN is in the CRL cache and return its entry */
SECStatus DPCache_Lookup(CRLDPCache* cache, SECItem* sn, CERTCrlEntry** returned);
/* update the content of the CRL cache, including fetching of CRLs, and
reprocessing with specified issuer and date */
SECStatus DPCache_GetUpToDate(CRLDPCache* cache, CERTCertificate* issuer,
PRBool readlocked, PRTime vfdate, void* wincx);
/* returns true if there are CRLs from PKCS#11 slots */
PRBool DPCache_HasTokenCRLs(CRLDPCache* cache);
/* remove CRL at offset specified */
SECStatus DPCache_RemoveCRL(CRLDPCache* cache, PRUint32 offset);
/* Pick best CRL to use . needs write access */
SECStatus DPCache_SelectCRL(CRLDPCache* cache);
/* CRL issuer cache object /* CRL issuer cache object
This object tracks all the distribution point caches for a given issuer. This object tracks all the distribution point caches for a given issuer.
XCRL once we support multiple issuing distribution points, this object XCRL once we support multiple issuing distribution points, this object
@ -158,7 +232,6 @@ struct CRLDPCacheStr {
struct CRLIssuerCacheStr { struct CRLIssuerCacheStr {
SECItem* subject; /* DER of issuer subject */ SECItem* subject; /* DER of issuer subject */
CRLDPCache dp; /* DER of distribution point */
CRLDPCache* dpp; CRLDPCache* dpp;
#if 0 #if 0
/* XCRL for future use. /* XCRL for future use.
@ -171,12 +244,32 @@ struct CRLIssuerCacheStr {
#endif #endif
}; };
/* create an issuer cache object (per CA subject ) */
SECStatus IssuerCache_Create(CRLIssuerCache** returned,
CERTCertificate* issuer,
SECItem* subject, SECItem* dp);
/* destructor for CRL IssuerCache object */
SECStatus IssuerCache_Destroy(CRLIssuerCache* cache);
/* add a DPCache to the issuer cache */
SECStatus IssuerCache_AddDP(CRLIssuerCache* cache, CERTCertificate* issuer,
SECItem* subject, SECItem* dp, CRLDPCache** newdpc);
/* get a particular DPCache object from an IssuerCache */
CRLDPCache* IssuerCache_GetDPCache(CRLIssuerCache* cache, SECItem* dp);
/* CRL revocation cache object /* CRL revocation cache object
This object tracks all the issuer caches This object tracks all the issuer caches
*/ */
struct CRLCacheStr { struct CRLCacheStr {
#ifdef GLOBAL_RWLOCK
NSSRWLock* lock;
#else
PRLock* lock; PRLock* lock;
#endif
/* hash table of issuer to CRLIssuerCacheStr, /* hash table of issuer to CRLIssuerCacheStr,
indexed by issuer DER subject */ indexed by issuer DER subject */
PLHashTable* issuers; PLHashTable* issuers;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -813,6 +813,7 @@ SECMOD_WaitForAnyTokenEvent;
;+}; ;+};
;+NSS_3.10 { # NSS 3.10 release ;+NSS_3.10 { # NSS 3.10 release
;+ global: ;+ global:
CERT_CacheCRL;
CERT_DecodeAltNameExtension; CERT_DecodeAltNameExtension;
CERT_DecodeAuthInfoAccessExtension; CERT_DecodeAuthInfoAccessExtension;
CERT_DecodeAuthKeyID; CERT_DecodeAuthKeyID;
@ -824,6 +825,7 @@ CERT_GetNextGeneralName;
CERT_GetNextNameConstraint; CERT_GetNextNameConstraint;
CERT_GetPrevGeneralName; CERT_GetPrevGeneralName;
CERT_GetPrevNameConstraint; CERT_GetPrevNameConstraint;
CERT_UncacheCRL;
HASH_Clone; HASH_Clone;
HASH_HashBuf; HASH_HashBuf;
HASH_ResultLenByOidTag; HASH_ResultLenByOidTag;

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

@ -247,7 +247,8 @@ loser:
} }
/* /*
* Return a list of all the CRLs * Return a list of all the CRLs .
* CRLs are allocated in the list's arena.
*/ */
SECStatus SECStatus
PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) { PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
@ -271,6 +272,157 @@ PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx); return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx);
} }
struct crlOptionsStr {
CERTCrlHeadNode* head;
PRInt32 decodeOptions;
};
typedef struct crlOptionsStr crlOptions;
static SECStatus
pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
void *arg)
{
SECItem* derCrl = NULL;
crlOptions* options = (crlOptions*) arg;
CERTCrlHeadNode *head = options->head;
CERTCrlNode *new_node = NULL;
CK_ATTRIBUTE fetchCrl[3] = {
{ CKA_VALUE, NULL, 0},
{ CKA_NETSCAPE_KRL, NULL, 0},
{ CKA_NETSCAPE_URL, NULL, 0},
};
const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
CK_RV crv;
SECStatus rv = SECFailure;
PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
successfully */
int i;
crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize);
if (CKR_OK != crv) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
if (!fetchCrl[1].pValue) {
/* reject KRLs */
PORT_SetError(SEC_ERROR_CRL_INVALID);
goto loser;
}
new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
sizeof(CERTCrlNode));
if (new_node == NULL) {
goto loser;
}
new_node->type = SEC_CRL_TYPE;
derCrl = SECITEM_AllocItem(NULL, NULL, 0);
if (!derCrl) {
goto loser;
}
derCrl->type = siBuffer;
derCrl->data = (unsigned char *)fetchCrl[0].pValue;
derCrl->len = fetchCrl[0].ulValueLen;
new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type,
options->decodeOptions);
if (new_node->crl == NULL) {
goto loser;
}
adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
we won't need to free it upon exit */
if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
/* copy the URL if there is one */
int nnlen = fetchCrl[2].ulValueLen;
new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena,
nnlen+1);
if ( !new_node->crl->url ) {
goto loser;
}
PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
new_node->crl->url[nnlen] = 0;
} else {
new_node->crl->url = NULL;
}
new_node->next = NULL;
if (head->last) {
head->last->next = new_node;
head->last = new_node;
} else {
head->first = head->last = new_node;
}
rv = SECSuccess;
new_node->crl->slot = PK11_ReferenceSlot(slot);
new_node->crl->pkcs11ID = crlID;
loser:
/* free attributes that weren't adopted by the CRL */
for (i=1;i<fetchCrlSize;i++) {
if (fetchCrl[i].pValue) {
PORT_Free(fetchCrl[i].pValue);
}
}
/* free the DER if the CRL object didn't adopt it */
if (fetchCrl[0].pValue && PR_FALSE == adopted) {
PORT_Free(fetchCrl[0].pValue);
}
if (derCrl && !adopted) {
/* clear the data fields, which we already took care of above */
derCrl->data = NULL;
derCrl->len = 0;
/* free the memory for the SECItem structure itself */
SECITEM_FreeItem(derCrl, PR_TRUE);
}
return(rv);
}
/*
* Return a list of CRLs matching specified issuer and type
* CRLs are not allocated in the list's arena, but rather in their own,
* arena, so that they can be used individually in the CRL cache .
* CRLs are always partially decoded for efficiency.
*/
SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
void *wincx)
{
pk11TraverseSlot creater;
CK_ATTRIBUTE theTemplate[2];
CK_ATTRIBUTE *attrs;
CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL;
crlOptions options;
attrs = theTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++;
options.head = nodes;
/* - do a partial decoding - we don't need to decode the entries while
fetching
- don't copy the DER for optimal performance - CRL can be very large
- have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
- keep bad CRL objects. The CRL cache is interested in them, for
security purposes. Bad CRL objects are a sign of something amiss.
*/
options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
if (issuer)
{
PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); attrs++;
}
creater.callback = pk11_RetrieveCrlsCallback;
creater.callbackArg = (void *) &options;
creater.findTemplate = theTemplate;
creater.templateCount = (attrs - theTemplate);
return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx);
}
/* /*
* return the crl associated with a derSubjectName * return the crl associated with a derSubjectName
*/ */
@ -336,6 +488,7 @@ PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
goto loser; goto loser;
} }
/* why are we arbitrarily picking the first CRL ??? */
derCrl->data = crlData[0].pValue; derCrl->data = crlData[0].pValue;
derCrl->len = crlData[0].ulValueLen; derCrl->len = crlData[0].ulValueLen;

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

@ -211,6 +211,10 @@ SECStatus PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
SECStatus pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), SECStatus pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *),
void *cbArg, void *pwArg); void *cbArg, void *pwArg);
/* fetch multiple CRLs for a specific issuer */
SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
void *wincx);
SEC_END_PROTOS SEC_END_PROTOS
#endif #endif

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

@ -203,6 +203,7 @@ SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION = (SEC_ERROR_BASE + 149),
SEC_ERROR_UNKNOWN_OBJECT_TYPE = (SEC_ERROR_BASE + 150), SEC_ERROR_UNKNOWN_OBJECT_TYPE = (SEC_ERROR_BASE + 150),
SEC_ERROR_INCOMPATIBLE_PKCS11 = (SEC_ERROR_BASE + 151), SEC_ERROR_INCOMPATIBLE_PKCS11 = (SEC_ERROR_BASE + 151),
SEC_ERROR_NO_EVENT = (SEC_ERROR_BASE + 152), SEC_ERROR_NO_EVENT = (SEC_ERROR_BASE + 152),
SEC_ERROR_CRL_ALREADY_EXISTS = (SEC_ERROR_BASE + 153),
/* Add new error codes above here. */ /* Add new error codes above here. */
SEC_ERROR_END_OF_LIST SEC_ERROR_END_OF_LIST