/* 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_crlentry.c * * CRLENTRY Function Definitions * */ #include "pkix_pl_crlentry.h" /* --Private-CRLEntry-Functions------------------------------------- */ /* * FUNCTION: pkix_pl_CRLEntry_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CRLEntry_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_CRLEntry *crlEntry = NULL; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), PKIX_OBJECTNOTCRLENTRY); crlEntry = (PKIX_PL_CRLEntry*)object; /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */ crlEntry->userReasonCode = 0; crlEntry->userReasonCodeAbsent = PKIX_FALSE; crlEntry->nssCrlEntry = NULL; PKIX_DECREF(crlEntry->serialNumber); PKIX_DECREF(crlEntry->critExtOids); cleanup: PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_ToString_Helper * * DESCRIPTION: * Helper function that creates a string representation of the CRLEntry * pointed to by "crlEntry" and stores it at "pString". * * PARAMETERS * "crlEntry" * Address of CRLEntry 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 CRLEntry 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_CRLEntry_ToString_Helper( PKIX_PL_CRLEntry *crlEntry, PKIX_PL_String **pString, void *plContext) { char *asciiFormat = NULL; PKIX_List *critExtOIDs = NULL; PKIX_PL_String *crlEntryString = NULL; PKIX_PL_String *formatString = NULL; PKIX_PL_String *crlSerialNumberString = NULL; PKIX_PL_String *crlRevocationDateString = NULL; PKIX_PL_String *critExtOIDsString = NULL; PKIX_Int32 reasonCode = 0; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper"); PKIX_NULLCHECK_FOUR (crlEntry, crlEntry->serialNumber, crlEntry->nssCrlEntry, pString); asciiFormat = "\n\t[\n" "\tSerialNumber: %s\n" "\tReasonCode: %d\n" "\tRevocationDate: %s\n" "\tCritExtOIDs: %s\n" "\t]\n\t"; PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), PKIX_STRINGCREATEFAILED); /* SerialNumber */ PKIX_CHECK(PKIX_PL_Object_ToString ((PKIX_PL_Object *)crlEntry->serialNumber, &crlSerialNumberString, plContext), PKIX_BIGINTTOSTRINGHELPERFAILED); /* RevocationDate - No Date object created, use nss data directly */ PKIX_CHECK(pkix_pl_Date_ToString_Helper (&(crlEntry->nssCrlEntry->revocationDate), &crlRevocationDateString, plContext), PKIX_DATETOSTRINGHELPERFAILED); /* CriticalExtensionOIDs */ PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (crlEntry, &critExtOIDs, plContext), PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED); PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, PKIX_LISTTOSTRINGFAILED); /* Revocation Reason Code */ PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode (crlEntry, &reasonCode, plContext), PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); PKIX_CHECK(PKIX_PL_Sprintf (&crlEntryString, plContext, formatString, crlSerialNumberString, reasonCode, crlRevocationDateString, critExtOIDsString), PKIX_SPRINTFFAILED); *pString = crlEntryString; cleanup: PKIX_DECREF(critExtOIDs); PKIX_DECREF(crlSerialNumberString); PKIX_DECREF(crlRevocationDateString); PKIX_DECREF(critExtOIDsString); PKIX_DECREF(formatString); PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_ToString * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CRLEntry_ToString( PKIX_PL_Object *object, PKIX_PL_String **pString, void *plContext) { PKIX_PL_String *crlEntryString = NULL; PKIX_PL_CRLEntry *crlEntry = NULL; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString"); PKIX_NULLCHECK_TWO(object, pString); PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), PKIX_OBJECTNOTCRLENTRY); crlEntry = (PKIX_PL_CRLEntry *) object; PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper (crlEntry, &crlEntryString, plContext), PKIX_CRLENTRYTOSTRINGHELPERFAILED); *pString = crlEntryString; cleanup: PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode * DESCRIPTION: * * For each CRL Entry extension stored at NSS structure CERTCertExtension, * get its derbyte data and do the hash. * * PARAMETERS * "extensions" * Address of arrray of CERTCertExtension whose hash value is desired. * Must be non-NULL. * "pHashValue" * Address where the final hash value is returned. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Conditional Thread Safe * Though the value of extensions once created is not supposed to change, * it may be de-allocated while we are accessing it. But since we are * validating the object, it is unlikely we or someone is de-allocating * at the moment. * RETURNS: * Returns NULL if the function succeeds. * Returns an OID 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_CRLEntry_Extensions_Hashcode( CERTCertExtension **extensions, PKIX_UInt32 *pHashValue, void *plContext) { CERTCertExtension *extension = NULL; PLArenaPool *arena = NULL; PKIX_UInt32 extHash = 0; PKIX_UInt32 hashValue = 0; SECItem *derBytes = NULL; SECItem *resultSecItem = NULL; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode"); PKIX_NULLCHECK_TWO(extensions, pHashValue); if (extensions) { PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n"); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } while (*extensions) { extension = *extensions++; PKIX_NULLCHECK_ONE(extension); PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); derBytes = PORT_ArenaZNew(arena, SECItem); if (derBytes == NULL) { PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); } PKIX_CRLENTRY_DEBUG ("\t\tCalling SEC_ASN1EncodeItem\n"); resultSecItem = SEC_ASN1EncodeItem (arena, derBytes, extension, CERT_CertExtensionTemplate); if (resultSecItem == NULL){ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); } PKIX_CHECK(pkix_hash (derBytes->data, derBytes->len, &extHash, plContext), PKIX_HASHFAILED); hashValue += (extHash << 7); } } *pHashValue = hashValue; cleanup: if (arena){ /* Note that freeing the arena also frees derBytes */ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n"); PORT_FreeArena(arena, PR_FALSE); arena = NULL; } PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_Hashcode * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CRLEntry_Hashcode( PKIX_PL_Object *object, PKIX_UInt32 *pHashcode, void *plContext) { SECItem *nssDate = NULL; PKIX_PL_CRLEntry *crlEntry = NULL; PKIX_UInt32 crlEntryHash; PKIX_UInt32 hashValue; PKIX_Int32 reasonCode = 0; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode"); PKIX_NULLCHECK_TWO(object, pHashcode); PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext), PKIX_OBJECTNOTCRLENTRY); crlEntry = (PKIX_PL_CRLEntry *)object; PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry); nssDate = &(crlEntry->nssCrlEntry->revocationDate); PKIX_NULLCHECK_ONE(nssDate->data); PKIX_CHECK(pkix_hash ((const unsigned char *)nssDate->data, nssDate->len, &crlEntryHash, plContext), PKIX_ERRORGETTINGHASHCODE); PKIX_CHECK(PKIX_PL_Object_Hashcode ((PKIX_PL_Object *)crlEntry->serialNumber, &hashValue, plContext), PKIX_OBJECTHASHCODEFAILED); crlEntryHash += (hashValue << 7); hashValue = 0; if (crlEntry->nssCrlEntry->extensions) { PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode (crlEntry->nssCrlEntry->extensions, &hashValue, plContext), PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED); } crlEntryHash += (hashValue << 7); PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode (crlEntry, &reasonCode, plContext), PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); crlEntryHash += (reasonCode + 777) << 3; *pHashcode = crlEntryHash; cleanup: PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals * DESCRIPTION: * * Compare each extension's DERbyte data in "firstExtensions" with extension * in "secondExtensions" in sequential order and store the result in * "pResult". * * PARAMETERS * "firstExtensions" * Address of first NSS structure CERTCertExtension to be compared. * Must be non-NULL. * "secondExtensions" * Address of second NSS structure CERTCertExtension to be compared. * Must be non-NULL. * "pResult" * Address where the comparison result is returned. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Conditionally Thread Safe * Though the value of extensions once created is not supposed to change, * it may be de-allocated while we are accessing it. But since we are * validating the object, it is unlikely we or someone is de-allocating * at the moment. * RETURNS: * Returns NULL if the function succeeds. * Returns an OID 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_CRLEntry_Extensions_Equals( CERTCertExtension **extensions1, CERTCertExtension **extensions2, PKIX_Boolean *pResult, void *plContext) { CERTCertExtension **firstExtensions; CERTCertExtension **secondExtensions; CERTCertExtension *firstExtension = NULL; CERTCertExtension *secondExtension = NULL; PLArenaPool *arena = NULL; PKIX_Boolean cmpResult = PKIX_FALSE; SECItem *firstDerBytes = NULL; SECItem *secondDerBytes = NULL; SECItem *firstResultSecItem = NULL; SECItem *secondResultSecItem = NULL; PKIX_UInt32 firstNumExt = 0; PKIX_UInt32 secondNumExt = 0; SECComparison secResult; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals"); PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult); firstExtensions = extensions1; secondExtensions = extensions2; if (firstExtensions) { while (*firstExtensions) { firstExtension = *firstExtensions++; firstNumExt++; } } if (secondExtensions) { while (*secondExtensions) { secondExtension = *secondExtensions++; secondNumExt++; } } if (firstNumExt != secondNumExt) { *pResult = PKIX_FALSE; goto cleanup; } if (firstNumExt == 0 && secondNumExt == 0) { *pResult = PKIX_TRUE; goto cleanup; } /* now have equal number, but non-zero extension items to compare */ firstExtensions = extensions1; secondExtensions = extensions2; cmpResult = PKIX_TRUE; PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n"); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2); if (arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } while (firstNumExt--) { firstExtension = *firstExtensions++; secondExtension = *secondExtensions++; PKIX_NULLCHECK_TWO(firstExtension, secondExtension); PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); firstDerBytes = PORT_ArenaZNew(arena, SECItem); if (firstDerBytes == NULL) { PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); } PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n"); secondDerBytes = PORT_ArenaZNew(arena, SECItem); if (secondDerBytes == NULL) { PKIX_ERROR(PKIX_PORTARENAALLOCFAILED); } PKIX_CRLENTRY_DEBUG ("\t\tCalling SEC_ASN1EncodeItem\n"); firstResultSecItem = SEC_ASN1EncodeItem (arena, firstDerBytes, firstExtension, CERT_CertExtensionTemplate); if (firstResultSecItem == NULL){ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); } PKIX_CRLENTRY_DEBUG ("\t\tCalling SEC_ASN1EncodeItem\n"); secondResultSecItem = SEC_ASN1EncodeItem (arena, secondDerBytes, secondExtension, CERT_CertExtensionTemplate); if (secondResultSecItem == NULL){ PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); } PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); secResult = SECITEM_CompareItem (firstResultSecItem, secondResultSecItem); if (secResult != SECEqual) { cmpResult = PKIX_FALSE; break; } } *pResult = cmpResult; cleanup: if (arena){ /* Note that freeing the arena also frees derBytes */ PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n"); PORT_FreeArena(arena, PR_FALSE); arena = NULL; } PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_Equals * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CRLEntry_Equals( PKIX_PL_Object *firstObject, PKIX_PL_Object *secondObject, PKIX_Boolean *pResult, void *plContext) { PKIX_PL_CRLEntry *firstCrlEntry = NULL; PKIX_PL_CRLEntry *secondCrlEntry = NULL; PKIX_UInt32 secondType; PKIX_Boolean cmpResult = PKIX_FALSE; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals"); PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); /* test that firstObject is a CRLEntry */ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext), PKIX_FIRSTOBJECTNOTCRLENTRY); firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject; secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject; PKIX_NULLCHECK_TWO (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry); /* * Since we know firstObject is a CRLEntry, if both references are * identical, they must be equal */ if (firstCrlEntry == secondCrlEntry){ *pResult = PKIX_TRUE; goto cleanup; } /* * If secondCrlEntry isn't a CRL Entry, 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 *)secondCrlEntry, &secondType, plContext), PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup; /* Compare userSerialNumber */ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); if (SECITEM_CompareItem( &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber), &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber)) != SECEqual) { *pResult = PKIX_FALSE; goto cleanup; } /* Compare revocationDate */ PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n"); if (SECITEM_CompareItem (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry-> revocationDate), &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry-> revocationDate)) != SECEqual) { *pResult = PKIX_FALSE; goto cleanup; } /* Compare Critical Extension List */ PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals (firstCrlEntry->nssCrlEntry->extensions, secondCrlEntry->nssCrlEntry->extensions, &cmpResult, plContext), PKIX_CRLENTRYEXTENSIONSEQUALSFAILED); if (cmpResult != PKIX_TRUE){ *pResult = PKIX_FALSE; goto cleanup; } cmpResult = (firstCrlEntry->userReasonCode == secondCrlEntry->userReasonCode); *pResult = cmpResult; cleanup: PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_RegisterSelf * DESCRIPTION: * Registers PKIX_CRLEntry_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_CRLEntry_RegisterSelf(void *plContext) { extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; pkix_ClassTable_Entry entry; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf"); entry.description = "CRLEntry"; entry.objCounter = 0; entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry); entry.destructor = pkix_pl_CRLEntry_Destroy; entry.equalsFunction = pkix_pl_CRLEntry_Equals; entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode; entry.toStringFunction = pkix_pl_CRLEntry_ToString; entry.comparator = NULL; entry.duplicateFunction = pkix_duplicateImmutable; systemClasses[PKIX_CRLENTRY_TYPE] = entry; PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_CreateEntry * DESCRIPTION: * * Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry" * and stores it at "pCrlEntry". Once created, a CRLEntry is immutable. * * revokedCertificates SEQUENCE OF SEQUENCE { * userCertificate CertificateSerialNumber, * revocationDate Time, * crlEntryExtensions Extensions OPTIONAL * -- if present, MUST be v2 * * PARAMETERS: * "nssCrlEntry" * Address of CERTCrlEntry representing an NSS CRL entry. * Must be non-NULL. * "pCrlEntry" * 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 CRLEntry 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_CRLEntry_CreateEntry( CERTCrlEntry *nssCrlEntry, /* entry data to be created from */ PKIX_PL_CRLEntry **pCrlEntry, void *plContext) { PKIX_PL_CRLEntry *crlEntry = NULL; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry"); PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry); PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_CRLENTRY_TYPE, sizeof (PKIX_PL_CRLEntry), (PKIX_PL_Object **)&crlEntry, plContext), PKIX_COULDNOTCREATECRLENTRYOBJECT); crlEntry->nssCrlEntry = nssCrlEntry; crlEntry->serialNumber = NULL; crlEntry->critExtOids = NULL; crlEntry->userReasonCode = 0; crlEntry->userReasonCodeAbsent = PKIX_FALSE; *pCrlEntry = crlEntry; cleanup: PKIX_RETURN(CRLENTRY); } /* * FUNCTION: pkix_pl_CRLEntry_Create * DESCRIPTION: * * Creates a List of CRLEntries using the array of CERTCrlEntries pointed to * by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is * NULL, this function stores an empty List at "pCrlEntryList". * } * PARAMETERS: * "nssCrlEntries" * Address of array of CERTCrlEntries representing NSS CRL entries. * Can be NULL if CRL has no NSS CRL entries. * "pCrlEntryList" * 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 CRLEntry 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_CRLEntry_Create( CERTCrlEntry **nssCrlEntries, /* head of entry list */ PKIX_List **pCrlEntryList, void *plContext) { PKIX_List *entryList = NULL; PKIX_PL_CRLEntry *crlEntry = NULL; CERTCrlEntry **entries = NULL; SECItem serialNumberItem; PKIX_PL_BigInt *serialNumber; char *bytes = NULL; PKIX_UInt32 length; PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create"); PKIX_NULLCHECK_ONE(pCrlEntryList); entries = nssCrlEntries; PKIX_CHECK(PKIX_List_Create(&entryList, plContext), PKIX_LISTCREATEFAILED); if (entries) { while (*entries){ PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry (*entries, &crlEntry, plContext), PKIX_COULDNOTCREATECRLENTRYOBJECT); /* Get Serial Number */ serialNumberItem = (*entries)->serialNumber; length = serialNumberItem.len; bytes = (char *)serialNumberItem.data; PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes (bytes, length, &serialNumber, plContext), PKIX_BIGINTCREATEWITHBYTESFAILED); crlEntry->serialNumber = serialNumber; crlEntry->nssCrlEntry = *entries; PKIX_CHECK(PKIX_List_AppendItem (entryList, (PKIX_PL_Object *)crlEntry, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(crlEntry); entries++; } } *pCrlEntryList = entryList; cleanup: PKIX_DECREF(crlEntry); if (PKIX_ERROR_RECEIVED){ PKIX_DECREF(entryList); } PKIX_RETURN(CRLENTRY); } /* --Public-CRLENTRY-Functions------------------------------------- */ /* * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode * (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRLEntry_GetCRLEntryReasonCode ( PKIX_PL_CRLEntry *crlEntry, PKIX_Int32 *pReason, void *plContext) { SECStatus status; CERTCRLEntryReasonCode nssReasonCode; PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode"); PKIX_NULLCHECK_TWO(crlEntry, pReason); if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) { PKIX_OBJECT_LOCK(crlEntry); if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) { /* reason code has not been cached in */ PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n"); status = CERT_FindCRLEntryReasonExten (crlEntry->nssCrlEntry, &nssReasonCode); if (status == SECSuccess) { crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode; } else { crlEntry->userReasonCodeAbsent = PKIX_TRUE; } } PKIX_OBJECT_UNLOCK(crlEntry); } *pReason = crlEntry->userReasonCode; cleanup: PKIX_RETURN(CRLENTRY); } /* * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs * (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRLEntry_GetCriticalExtensionOIDs ( PKIX_PL_CRLEntry *crlEntry, PKIX_List **pList, /* list of PKIX_PL_OID */ void *plContext) { PKIX_List *oidsList = NULL; CERTCertExtension **extensions; PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs"); PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList); /* if we don't have a cached copy from before, we create one */ if (crlEntry->critExtOids == NULL) { PKIX_OBJECT_LOCK(crlEntry); if (crlEntry->critExtOids == NULL) { extensions = crlEntry->nssCrlEntry->extensions; PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs (extensions, &oidsList, plContext), PKIX_GETCRITICALEXTENSIONOIDSFAILED); crlEntry->critExtOids = oidsList; } PKIX_OBJECT_UNLOCK(crlEntry); } /* We should return a copy of the List since this list changes */ PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext, PKIX_OBJECTDUPLICATELISTFAILED); cleanup: PKIX_RETURN(CRLENTRY); }