зеркало из https://github.com/mozilla/gecko-dev.git
Fix for 243585 - add the ability to use CRL objects from RAM . r=nelson, neil.williams
This commit is contained in:
Родитель
1d28e9d8ef
Коммит
1b8fc2a9d7
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче