summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c')
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c1068
1 files changed, 1068 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
new file mode 100644
index 0000000000..b83db357ac
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crl.c
@@ -0,0 +1,1068 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_crl.c
+ *
+ * CRL Function Definitions
+ *
+ */
+
+#include "pkix_pl_crl.h"
+#include "certxutl.h"
+
+extern PKIX_PL_HashTable *cachedCrlSigTable;
+
+/* --Private-CRL-Functions------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetVersion
+ * DESCRIPTION:
+ *
+ * Retrieves the version of the CRL pointed to by "crl" and stores it at
+ * "pVersion". The version number will either be 0 or 1 (corresponding to
+ * v1 or v2, respectively).
+ *
+ * Version ::= INTEGER { v1(0), v2(1), v3(2) }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose version is to be stored. Must be non-NULL.
+ * "pVersion"
+ * Address where a version will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetVersion(
+ PKIX_PL_CRL *crl,
+ PKIX_UInt32 *pVersion,
+ void *plContext)
+{
+ PKIX_UInt32 myVersion;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion);
+
+ PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data);
+
+ myVersion = *(crl->nssSignedCrl->crl.version.data);
+
+ if (myVersion > 1) {
+ PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2);
+ }
+
+ *pVersion = myVersion;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCRLNumber(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_BigInt **pCrlNumber,
+ void *plContext)
+{
+ PKIX_PL_BigInt *crlNumber = NULL;
+ SECItem nssCrlNumber;
+ PLArenaPool *arena = NULL;
+ SECStatus status;
+ PKIX_UInt32 length = 0;
+ char *bytes = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
+
+ nssCrlNumber.type = 0;
+ nssCrlNumber.len = 0;
+ nssCrlNumber.data = NULL;
+
+ PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n");
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ PKIX_ERROR(PKIX_OUTOFMEMORY);
+ }
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n");
+ status = CERT_FindCRLNumberExten
+ (arena, &crl->nssSignedCrl->crl, &nssCrlNumber);
+
+ if (status == SECSuccess) {
+ /* Get data in bytes then convert to bigint */
+ length = nssCrlNumber.len;
+ bytes = (char *)nssCrlNumber.data;
+
+ PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
+ (bytes, length, &crlNumber, plContext),
+ PKIX_BIGINTCREATEWITHBYTESFAILED);
+
+ /* arena release does the job
+ PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
+ SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE);
+ */
+ crl->crlNumber = crlNumber;
+
+ } else {
+
+ crl->crlNumberAbsent = PKIX_TRUE;
+ }
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->crlNumber);
+
+ *pCrlNumber = crl->crlNumber;
+
+cleanup:
+
+ if (arena){
+ PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n");
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
+ *
+ * DESCRIPTION:
+ * Retrieves a pointer to the OID that represents the signature algorithm of
+ * the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
+ *
+ * AlgorithmIdentifier ::= SEQUENCE {
+ * algorithm OBJECT IDENTIFIER,
+ * parameters ANY DEFINED BY algorithm OPTIONAL }
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose signature algorithm OID is to be stored.
+ * Must be non-NULL.
+ * "pSignatureAlgId"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetSignatureAlgId(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_OID **pSignatureAlgId,
+ void *plContext)
+{
+ PKIX_PL_OID *signatureAlgId = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->signatureAlgId == NULL){
+ PKIX_OBJECT_LOCK(crl);
+ if (crl->signatureAlgId == NULL){
+ CERTCrl *nssCrl = &(crl->nssSignedCrl->crl);
+ SECAlgorithmID *algorithm = &nssCrl->signatureAlg;
+ SECItem *algBytes = &algorithm->algorithm;
+
+ if (!algBytes->data || !algBytes->len) {
+ PKIX_ERROR(PKIX_OIDBYTESLENGTH0);
+ }
+ PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
+ (algBytes, &signatureAlgId, plContext),
+ PKIX_OIDCREATEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ crl->signatureAlgId = signatureAlgId;
+ signatureAlgId = NULL;
+ }
+ PKIX_OBJECT_UNLOCK(crl);
+ }
+ PKIX_INCREF(crl->signatureAlgId);
+ *pSignatureAlgId = crl->signatureAlgId;
+cleanup:
+ PKIX_DECREF(signatureAlgId);
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_GetCRLEntries
+ * DESCRIPTION:
+ *
+ * Retrieves a pointer to the List of CRLEntries found in the CRL pointed to
+ * by "crl" and stores it at "pCRLEntries". If there are no CRLEntries,
+ * this functions stores NULL at "pCRLEntries".
+ *
+ * PARAMETERS:
+ * "crl"
+ * Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL.
+ * "pCRLEntries"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_GetCRLEntries(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pCrlEntries,
+ void *plContext)
+{
+ PKIX_List *entryList = NULL;
+ CERTCrl *nssCrl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->crlEntryList == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (crl->crlEntryList == NULL){
+
+ nssCrl = &(crl->nssSignedCrl->crl);
+
+ PKIX_CHECK(pkix_pl_CRLEntry_Create
+ (nssCrl->entries, &entryList, plContext),
+ PKIX_CRLENTRYCREATEFAILED);
+
+ PKIX_CHECK(PKIX_List_SetImmutable
+ (entryList, plContext),
+ PKIX_LISTSETIMMUTABLEFAILED);
+
+ crl->crlEntryList = entryList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->crlEntryList);
+
+ *pCrlEntries = crl->crlEntryList;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL*)object;
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
+ if (crl->nssSignedCrl) {
+ CERT_DestroyCrl(crl->nssSignedCrl);
+ }
+ if (crl->adoptedDerCrl) {
+ SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE);
+ }
+ crl->nssSignedCrl = NULL;
+ crl->adoptedDerCrl = NULL;
+ crl->crlNumberAbsent = PKIX_FALSE;
+
+ PKIX_DECREF(crl->issuer);
+ PKIX_DECREF(crl->signatureAlgId);
+ PKIX_DECREF(crl->crlNumber);
+ PKIX_DECREF(crl->crlEntryList);
+ PKIX_DECREF(crl->critExtOids);
+ if (crl->derGenName) {
+ SECITEM_FreeItem(crl->derGenName, PR_TRUE);
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_ToString_Helper
+ * DESCRIPTION:
+ *
+ * Helper function that creates a string representation of the CRL pointed
+ * to by "crl" and stores it at "pString".
+ *
+ * PARAMETERS
+ * "crl"
+ * Address of CRL whose string representation is desired.
+ * Must be non-NULL.
+ * "pString"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_CRL_ToString_Helper(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ char *asciiFormat = NULL;
+ PKIX_UInt32 crlVersion = 0;
+ PKIX_PL_X500Name *crlIssuer = NULL;
+ PKIX_PL_OID *nssSignatureAlgId = NULL;
+ PKIX_PL_BigInt *crlNumber = NULL;
+ PKIX_List *crlEntryList = NULL;
+ PKIX_List *critExtOIDs = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *crlIssuerString = NULL;
+ PKIX_PL_String *lastUpdateString = NULL;
+ PKIX_PL_String *nextUpdateString = NULL;
+ PKIX_PL_String *nssSignatureAlgIdString = NULL;
+ PKIX_PL_String *crlNumberString = NULL;
+ PKIX_PL_String *crlEntryListString = NULL;
+ PKIX_PL_String *critExtOIDsString = NULL;
+ PKIX_PL_String *crlString = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString);
+
+ asciiFormat =
+ "[\n"
+ "\tVersion: v%d\n"
+ "\tIssuer: %s\n"
+ "\tUpdate: [Last: %s\n"
+ "\t Next: %s]\n"
+ "\tSignatureAlgId: %s\n"
+ "\tCRL Number : %s\n"
+ "\n"
+ "\tEntry List: %s\n"
+ "\n"
+ "\tCritExtOIDs: %s\n"
+ "]\n";
+
+ PKIX_CHECK(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiFormat,
+ 0,
+ &formatString,
+ plContext),
+ PKIX_STRINGCREATEFAILED);
+
+ /* Version */
+ PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext),
+ PKIX_CRLGETVERSIONFAILED);
+
+ /* Issuer */
+ PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext),
+ PKIX_CRLGETISSUERFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext),
+ PKIX_X500NAMETOSTRINGFAILED);
+
+ /* This update - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crl->nssSignedCrl->crl.lastUpdate),
+ &lastUpdateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Next update - No Date object created, use nss data directly */
+ PKIX_CHECK(pkix_pl_Date_ToString_Helper
+ (&(crl->nssSignedCrl->crl.nextUpdate),
+ &nextUpdateString,
+ plContext),
+ PKIX_DATETOSTRINGHELPERFAILED);
+
+ /* Signature Algorithm Id */
+ PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId
+ (crl, &nssSignatureAlgId, plContext),
+ PKIX_CRLGETSIGNATUREALGIDFAILED);
+
+ PKIX_CHECK(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)nssSignatureAlgId,
+ &nssSignatureAlgIdString,
+ plContext),
+ PKIX_OIDTOSTRINGFAILED);
+
+ /* CRL Number */
+ PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber
+ (crl, &crlNumber, plContext),
+ PKIX_CRLGETCRLNUMBERFAILED);
+
+ PKIX_TOSTRING(crlNumber, &crlNumberString, plContext,
+ PKIX_BIGINTTOSTRINGFAILED);
+
+ /* CRL Entries */
+ PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
+ PKIX_CRLGETCRLENTRIESFAILED);
+
+ PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ /* CriticalExtensionOIDs */
+ PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
+ (crl, &critExtOIDs, plContext),
+ PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);
+
+ PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
+ PKIX_LISTTOSTRINGFAILED);
+
+ PKIX_CHECK(PKIX_PL_Sprintf
+ (&crlString,
+ plContext,
+ formatString,
+ crlVersion + 1,
+ crlIssuerString,
+ lastUpdateString,
+ nextUpdateString,
+ nssSignatureAlgIdString,
+ crlNumberString,
+ crlEntryListString,
+ critExtOIDsString),
+ PKIX_SPRINTFFAILED);
+
+ *pString = crlString;
+
+cleanup:
+
+ PKIX_DECREF(crlIssuer);
+ PKIX_DECREF(nssSignatureAlgId);
+ PKIX_DECREF(crlNumber);
+ PKIX_DECREF(crlEntryList);
+ PKIX_DECREF(critExtOIDs);
+ PKIX_DECREF(crlIssuerString);
+ PKIX_DECREF(lastUpdateString);
+ PKIX_DECREF(nextUpdateString);
+ PKIX_DECREF(nssSignatureAlgIdString);
+ PKIX_DECREF(crlNumberString);
+ PKIX_DECREF(crlEntryListString);
+ PKIX_DECREF(critExtOIDsString);
+ PKIX_DECREF(formatString);
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_ToString
+ * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_ToString(
+ PKIX_PL_Object *object,
+ PKIX_PL_String **pString,
+ void *plContext)
+{
+ PKIX_PL_String *crlString = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_ToString");
+ PKIX_NULLCHECK_TWO(object, pString);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL *) object;
+
+ PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext),
+ PKIX_CRLTOSTRINGHELPERFAILED);
+
+ *pString = crlString;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_UInt32 certHash;
+ SECItem *crlDer = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
+ PKIX_OBJECTNOTCRL);
+
+ crl = (PKIX_PL_CRL *)object;
+ if (crl->adoptedDerCrl) {
+ crlDer = crl->adoptedDerCrl;
+ } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) {
+ crlDer = crl->nssSignedCrl->derCrl;
+ }
+ if (!crlDer || !crlDer->data) {
+ PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
+ }
+
+ PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len,
+ &certHash, plContext),
+ PKIX_ERRORINHASH);
+
+ *pHashcode = certHash;
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_CRL_Equals(
+ PKIX_PL_Object *firstObject,
+ PKIX_PL_Object *secondObject,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_CRL *firstCrl = NULL;
+ PKIX_PL_CRL *secondCrl = NULL;
+ SECItem *crlDerOne = NULL, *crlDerTwo = NULL;
+ PKIX_UInt32 secondType;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_Equals");
+ PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
+
+ /* test that firstObject is a CRL */
+ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext),
+ PKIX_FIRSTOBJECTNOTCRL);
+
+ firstCrl = (PKIX_PL_CRL *)firstObject;
+ secondCrl = (PKIX_PL_CRL *)secondObject;
+
+ /*
+ * Since we know firstObject is a CRL, if both references are
+ * identical, they must be equal
+ */
+ if (firstCrl == secondCrl){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondCrl isn't a CRL, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ ((PKIX_PL_Object *)secondCrl, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_CRL_TYPE) goto cleanup;
+
+ if (firstCrl->adoptedDerCrl) {
+ crlDerOne = firstCrl->adoptedDerCrl;
+ } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) {
+ crlDerOne = firstCrl->nssSignedCrl->derCrl;
+ }
+
+ if (secondCrl->adoptedDerCrl) {
+ crlDerTwo = secondCrl->adoptedDerCrl;
+ } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) {
+ crlDerTwo = secondCrl->nssSignedCrl->derCrl;
+ }
+
+ if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) {
+ *pResult = PKIX_TRUE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_RegisterSelf
+ *
+ * DESCRIPTION:
+ * Registers PKIX_CRL_TYPE and its related functions with systemClasses[]
+ * THREAD SAFETY:
+ *
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_CRL_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE];
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf");
+
+ entry->description = "CRL";
+ entry->typeObjectSize = sizeof(PKIX_PL_CRL);
+ entry->destructor = pkix_pl_CRL_Destroy;
+ entry->equalsFunction = pkix_pl_CRL_Equals;
+ entry->hashcodeFunction = pkix_pl_CRL_Hashcode;
+ entry->toStringFunction = pkix_pl_CRL_ToString;
+ entry->duplicateFunction = pkix_duplicateImmutable;
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifyUpdateTime(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_Date *date,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PRTime timeToCheck;
+ PRTime nextUpdate;
+ PRTime lastUpdate;
+ SECStatus status;
+ CERTCrl *nssCrl = NULL;
+ SECItem *nextUpdateDer = NULL;
+ PKIX_Boolean haveNextUpdate = PR_FALSE;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
+ PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ nssCrl = &(crl->nssSignedCrl->crl);
+ timeToCheck = date->nssTime;
+
+ /* nextUpdate can be NULL. Checking before using it */
+ nextUpdateDer = &nssCrl->nextUpdate;
+ if (nextUpdateDer->data && nextUpdateDer->len) {
+ haveNextUpdate = PR_TRUE;
+ status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
+ }
+ }
+
+ status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
+ if (status != SECSuccess) {
+ PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
+ }
+
+ if (!haveNextUpdate || nextUpdate < timeToCheck) {
+ *pResult = PKIX_FALSE;
+ goto cleanup;
+ }
+
+ if (lastUpdate <= timeToCheck) {
+ *pResult = PKIX_TRUE;
+ } else {
+ *pResult = PKIX_FALSE;
+ }
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
+ * DESCRIPTION:
+ *
+ * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
+ * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
+ * a PKIX_Error is returned.
+ *
+ * PARAMETERS:
+ * "nssSignedCrl"
+ * Address of CERTSignedCrl. Must be non-NULL.
+ * "adoptedDerCrl"
+ * SECItem ponter that if not NULL is indicating that memory used
+ * for der should be adopted by crl that is about to be created.
+ * "pCRL"
+ * Address where object pointer will be stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns a CRL Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_CRL_CreateWithSignedCRL(
+ CERTSignedCrl *nssSignedCrl,
+ SECItem *adoptedDerCrl,
+ SECItem *derGenName,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
+ PKIX_NULLCHECK_ONE(pCrl);
+
+ /* create a PKIX_PL_CRL object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_CRL_TYPE,
+ sizeof (PKIX_PL_CRL),
+ (PKIX_PL_Object **)&crl,
+ plContext),
+ PKIX_COULDNOTCREATECRLOBJECT);
+
+ /* populate the nssSignedCrl field */
+ crl->nssSignedCrl = nssSignedCrl;
+ crl->adoptedDerCrl = adoptedDerCrl;
+ crl->issuer = NULL;
+ crl->signatureAlgId = NULL;
+ crl->crlNumber = NULL;
+ crl->crlNumberAbsent = PKIX_FALSE;
+ crl->crlEntryList = NULL;
+ crl->critExtOids = NULL;
+ if (derGenName) {
+ crl->derGenName =
+ SECITEM_DupItem(derGenName);
+ if (!crl->derGenName) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ }
+
+ *pCrl = crl;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED){
+ PKIX_DECREF(crl);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/* --Public-CRL-Functions------------------------------------- */
+
+/*
+ * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_Create(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_PL_CRL **pCrl,
+ void *plContext)
+{
+ CERTSignedCrl *nssSignedCrl = NULL;
+ SECItem derItem, *derCrl = NULL;
+ PKIX_PL_CRL *crl = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
+ PKIX_NULLCHECK_TWO(byteArray, pCrl);
+
+ if (byteArray->length == 0){
+ PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
+ }
+ derItem.type = siBuffer;
+ derItem.data = byteArray->array;
+ derItem.len = byteArray->length;
+ derCrl = SECITEM_DupItem(&derItem);
+ if (!derCrl) {
+ PKIX_ERROR(PKIX_ALLOCERROR);
+ }
+ nssSignedCrl =
+ CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE,
+ CRL_DECODE_DONT_COPY_DER |
+ CRL_DECODE_SKIP_ENTRIES);
+ if (!nssSignedCrl) {
+ PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
+ }
+ PKIX_CHECK(
+ pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL,
+ &crl, plContext),
+ PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
+ nssSignedCrl = NULL;
+ derCrl = NULL;
+ *pCrl = crl;
+
+cleanup:
+ if (derCrl) {
+ SECITEM_FreeItem(derCrl, PR_TRUE);
+ }
+ if (nssSignedCrl) {
+ SEC_DestroyCrl(nssSignedCrl);
+ }
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetIssuer(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_X500Name **pCRLIssuer,
+ void *plContext)
+{
+ PKIX_PL_String *crlString = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ SECItem *derIssuerName = NULL;
+ CERTName *issuerName = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->issuer == NULL){
+
+ PKIX_OBJECT_LOCK(crl);
+
+ if (crl->issuer == NULL) {
+
+ issuerName = &crl->nssSignedCrl->crl.name;
+ derIssuerName = &crl->nssSignedCrl->crl.derName;
+
+ PKIX_CHECK(
+ PKIX_PL_X500Name_CreateFromCERTName(derIssuerName,
+ issuerName,
+ &issuer,
+ plContext),
+ PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
+
+ /* save a cached copy in case it is asked for again */
+ crl->issuer = issuer;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ PKIX_INCREF(crl->issuer);
+
+ *pCRLIssuer = crl->issuer;
+
+cleanup:
+
+ PKIX_DECREF(crlString);
+
+ PKIX_RETURN(CRL);
+}
+
+
+/*
+ * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
+ * (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_GetCriticalExtensionOIDs(
+ PKIX_PL_CRL *crl,
+ PKIX_List **pExtensions, /* list of PKIX_PL_OID */
+ void *plContext)
+{
+ PKIX_List *oidsList = NULL;
+ CERTCertExtension **extensions = NULL;
+ CERTCrl *nssSignedCrl = NULL;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ /* if we don't have a cached copy from before, we create one */
+ if (crl->critExtOids == NULL) {
+
+ PKIX_OBJECT_LOCK(crl);
+
+ nssSignedCrl = &(crl->nssSignedCrl->crl);
+ extensions = nssSignedCrl->extensions;
+
+ if (crl->critExtOids == NULL) {
+
+ PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
+ (extensions, &oidsList, plContext),
+ PKIX_GETCRITICALEXTENSIONOIDSFAILED);
+
+ crl->critExtOids = oidsList;
+ }
+
+ PKIX_OBJECT_UNLOCK(crl);
+
+ }
+
+ /* We should return a copy of the List since this list changes */
+ PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext,
+ PKIX_OBJECTDUPLICATELISTFAILED);
+
+cleanup:
+
+ PKIX_RETURN(CRL);
+}
+
+/*
+ * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h)
+ */
+PKIX_Error *
+PKIX_PL_CRL_VerifySignature(
+ PKIX_PL_CRL *crl,
+ PKIX_PL_PublicKey *pubKey,
+ void *plContext)
+{
+ PKIX_PL_CRL *cachedCrl = NULL;
+ PKIX_Error *verifySig = NULL;
+ PKIX_Error *cachedSig = NULL;
+ PKIX_Boolean crlEqual = PKIX_FALSE;
+ PKIX_Boolean crlInHash= PKIX_FALSE;
+ CERTSignedCrl *nssSignedCrl = NULL;
+ SECKEYPublicKey *nssPubKey = NULL;
+ CERTSignedData *tbsCrl = NULL;
+ void* wincx = NULL;
+ SECStatus status;
+
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature");
+ PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey);
+
+ /* Can call this function only with der been adopted. */
+ PORT_Assert(crl->adoptedDerCrl);
+
+ verifySig = PKIX_PL_HashTable_Lookup
+ (cachedCrlSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object **) &cachedCrl,
+ plContext);
+
+ if (cachedCrl != NULL && verifySig == NULL) {
+ /* Cached Signature Table lookup succeed */
+ PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext,
+ PKIX_OBJECTEQUALSFAILED);
+ if (crlEqual == PKIX_TRUE) {
+ goto cleanup;
+ }
+ /* Different PubKey may hash to same value, skip add */
+ crlInHash = PKIX_TRUE;
+ }
+
+ nssSignedCrl = crl->nssSignedCrl;
+ tbsCrl = &nssSignedCrl->signatureWrap;
+
+ PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n");
+ nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
+ if (!nssPubKey){
+ PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
+ }
+
+ PKIX_CHECK(pkix_pl_NssContext_GetWincx
+ ((PKIX_PL_NssContext *)plContext, &wincx),
+ PKIX_NSSCONTEXTGETWINCXFAILED);
+
+ PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n");
+ status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx);
+
+ if (status != SECSuccess) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
+ }
+
+ if (crlInHash == PKIX_FALSE) {
+ cachedSig = PKIX_PL_HashTable_Add
+ (cachedCrlSigTable,
+ (PKIX_PL_Object *) pubKey,
+ (PKIX_PL_Object *) crl,
+ plContext);
+
+ if (cachedSig != NULL) {
+ PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
+ }
+ }
+
+cleanup:
+
+ if (nssPubKey){
+ PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n");
+ SECKEY_DestroyPublicKey(nssPubKey);
+ nssPubKey = NULL;
+ }
+
+ PKIX_DECREF(cachedCrl);
+ PKIX_DECREF(verifySig);
+ PKIX_DECREF(cachedSig);
+
+ PKIX_RETURN(CRL);
+}
+
+PKIX_Error*
+PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl,
+ SECItem **derCrl,
+ void *plContext)
+{
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl");
+ *derCrl = crl->adoptedDerCrl;
+ crl->adoptedDerCrl = NULL;
+
+ PKIX_RETURN(CRL);
+}
+
+PKIX_Error*
+PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl,
+ SECItem *derCrl,
+ void *plContext)
+{
+ PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl");
+ if (crl->adoptedDerCrl) {
+ PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
+ }
+ crl->adoptedDerCrl = derCrl;
+cleanup:
+ PKIX_RETURN(CRL);
+}