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