diff options
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c')
-rw-r--r-- | security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c new file mode 100644 index 000000000..e2b3e0268 --- /dev/null +++ b/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c @@ -0,0 +1,880 @@ +/* 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); +} |