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
*
* $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_
@ -428,6 +428,7 @@ CERT_DecodeDERCrlWithFlags(PRArenaPool *narena, SECItem *derSignedCrl,
#define CRL_DECODE_DONT_COPY_DER 0x00000001
#define CRL_DECODE_SKIP_ENTRIES 0x00000002
#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
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). */
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
*/

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

@ -36,7 +36,7 @@
/*
* 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_
#define _CERTI_H_
@ -44,7 +44,11 @@
#include "certt.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 */
@ -53,16 +57,15 @@ typedef struct CRLEntryCacheStr CRLEntryCache;
typedef struct CRLDPCacheStr CRLDPCache;
typedef struct CRLIssuerCacheStr CRLIssuerCache;
typedef struct CRLCacheStr CRLCache;
typedef struct CachedCrlStr CachedCrl;
struct OpaqueCRLFieldsStr {
PRBool partial;
PRBool decodingError;
PRBool badEntries;
PRBool bad;
PRBool badDER;
PRBool badExtensions;
PRBool deleted;
PRBool heapDER;
PRBool unverified;
};
typedef struct PreAllocatorStr PreAllocator;
@ -95,23 +98,14 @@ struct CRLEntryCacheStr {
#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 */
/* 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; /* 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) */
typedef enum {
CRL_OriginToken = 0, /* CRL came from PKCS#11 token */
CRL_OriginExplicit = 1, /* CRL was explicitly added to the cache, from RAM */
} CRLOrigin;
struct CachedCrlStr {
CERTSignedCrl* crl;
CRLOrigin origin;
/* 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.
@ -125,30 +119,110 @@ struct CRLDPCacheStr {
*/
PLHashTable* entries;
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 */
CERTSignedCrl** crls; /* array of all matching DER CRLs
from all tokens */
CachedCrl** crls; /* array of all matching CRLs */
/* 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 */
CachedCrl* selected; /* full CRL selected for use in 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 */
CachedCrl** deltas; /* delta CRLs used for the cache */
#endif
/* invalidity bitflag */
/* cache 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 */
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
This object tracks all the distribution point caches for a given issuer.
XCRL once we support multiple issuing distribution points, this object
@ -158,7 +232,6 @@ struct CRLDPCacheStr {
struct CRLIssuerCacheStr {
SECItem* subject; /* DER of issuer subject */
CRLDPCache dp; /* DER of distribution point */
CRLDPCache* dpp;
#if 0
/* XCRL for future use.
@ -171,12 +244,32 @@ struct CRLIssuerCacheStr {
#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
This object tracks all the issuer caches
*/
struct CRLCacheStr {
#ifdef GLOBAL_RWLOCK
NSSRWLock* lock;
#else
PRLock* lock;
#endif
/* hash table of issuer to CRLIssuerCacheStr,
indexed by issuer DER subject */
PLHashTable* issuers;

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

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

@ -813,6 +813,7 @@ SECMOD_WaitForAnyTokenEvent;
;+};
;+NSS_3.10 { # NSS 3.10 release
;+ global:
CERT_CacheCRL;
CERT_DecodeAltNameExtension;
CERT_DecodeAuthInfoAccessExtension;
CERT_DecodeAuthKeyID;
@ -824,6 +825,7 @@ CERT_GetNextGeneralName;
CERT_GetNextNameConstraint;
CERT_GetPrevGeneralName;
CERT_GetPrevNameConstraint;
CERT_UncacheCRL;
HASH_Clone;
HASH_HashBuf;
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
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);
}
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
*/
@ -336,6 +488,7 @@ PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
goto loser;
}
/* why are we arbitrarily picking the first CRL ??? */
derCrl->data = crlData[0].pValue;
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 *),
void *cbArg, void *pwArg);
/* fetch multiple CRLs for a specific issuer */
SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
void *wincx);
SEC_END_PROTOS
#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_INCOMPATIBLE_PKCS11 = (SEC_ERROR_BASE + 151),
SEC_ERROR_NO_EVENT = (SEC_ERROR_BASE + 152),
SEC_ERROR_CRL_ALREADY_EXISTS = (SEC_ERROR_BASE + 153),
/* Add new error codes above here. */
SEC_ERROR_END_OF_LIST