Source code

Revision control

Copy as Markdown

Other Tools

/* 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);
}