/* * FUNCTION: pkix_pl_CRL_Destroy * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CRL_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_CRL *crl = NULL; PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy"); PKIX_NULLCHECK_ONE(object); PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext), PKIX_OBJECTNOTCRL); crl = (PKIX_PL_CRL*)object; PKIX_NULLCHECK_ONE(crl->nssSignedCrl); PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n"); CERT_DestroyCrl(crl->nssSignedCrl); crl->nssSignedCrl = NULL; crl->crlNumberAbsent = PKIX_FALSE; PKIX_DECREF(crl->issuer); PKIX_DECREF(crl->signatureAlgId); PKIX_DECREF(crl->crlNumber); PKIX_DECREF(crl->crlEntryList); PKIX_DECREF(crl->critExtOids); cleanup: PKIX_RETURN(CRL); }
/* * FUNCTION: pkix_pl_CRL_Equals * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) */ static PKIX_Error * pkix_pl_CRL_Equals( PKIX_PL_Object *firstObject, PKIX_PL_Object *secondObject, PKIX_Boolean *pResult, void *plContext) { PKIX_PL_CRL *firstCrl = NULL; PKIX_PL_CRL *secondCrl = NULL; PKIX_UInt32 secondType; PKIX_ENTER(CRL, "pkix_pl_CRL_Equals"); PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); /* test that firstObject is a CRL */ PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext), PKIX_FIRSTOBJECTNOTCRL); firstCrl = (PKIX_PL_CRL *)firstObject; secondCrl = (PKIX_PL_CRL *)secondObject; /* * Since we know firstObject is a CRL, if both references are * identical, they must be equal */ if (firstCrl == secondCrl) { *pResult = PKIX_TRUE; goto cleanup; } /* * If secondCrl isn't a CRL, we don't throw an error. * We simply return a Boolean result of FALSE */ *pResult = PKIX_FALSE; PKIX_CHECK(PKIX_PL_Object_GetType ((PKIX_PL_Object *)secondCrl, &secondType, plContext), PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); if (secondType != PKIX_CRL_TYPE) goto cleanup; /* Compare DER Bytes */ PKIX_NULLCHECK_TWO (firstCrl->nssSignedCrl, firstCrl->nssSignedCrl->derCrl); PKIX_NULLCHECK_TWO (secondCrl->nssSignedCrl, secondCrl->nssSignedCrl->derCrl); PKIX_CRL_DEBUG("\t\tCalling SECITEM_CompareItem on derCrl\n"); if (SECITEM_CompareItem(firstCrl->nssSignedCrl->derCrl, secondCrl->nssSignedCrl->derCrl) == SECEqual) { *pResult = PKIX_TRUE; } cleanup: PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRL_VerifyUpdateTime( PKIX_PL_CRL *crl, PKIX_PL_Date *date, PKIX_Boolean *pResult, void *plContext) { PRTime timeToCheck; PRTime nextUpdate; PRTime lastUpdate; SECStatus status; CERTCrl *nssCrl = NULL; SECItem *nextUpdateDer = NULL; PKIX_Boolean haveNextUpdate = PR_FALSE; PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime"); PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult); nssCrl = &(crl->nssSignedCrl->crl); PKIX_CRL_DEBUG("\t\tCalling DER_DecodeTimeChoice on date\n"); status = DER_DecodeTimeChoice(&timeToCheck, &(date->nssTime)); if (status != SECSuccess) { PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED); } /* nextUpdate can be NULL. Checking before using it */ nextUpdateDer = &nssCrl->nextUpdate; if (nextUpdateDer->data && nextUpdateDer->len) { haveNextUpdate = PR_TRUE; status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer); if (status != SECSuccess) { PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED); } } status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate)); if (status != SECSuccess) { PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED); } if (!haveNextUpdate || nextUpdate < timeToCheck) { *pResult = PKIX_FALSE; goto cleanup; } if (lastUpdate <= timeToCheck) { *pResult = PKIX_TRUE; } else { *pResult = PKIX_FALSE; } cleanup: PKIX_RETURN(CRL); }
/* * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL * DESCRIPTION: * * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl" * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails, * a PKIX_Error is returned. * * PARAMETERS: * "nssSignedCrl" * Address of CERTSignedCrl. Must be non-NULL. * "pCRL" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a CRL Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_CRL_CreateWithSignedCRL( CERTSignedCrl *nssSignedCrl, PKIX_PL_CRL **pCrl, void *plContext) { SECStatus status; PKIX_PL_CRL *crl = NULL; PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL"); PKIX_NULLCHECK_TWO(nssSignedCrl, pCrl); /* create a PKIX_PL_CRL object */ PKIX_CHECK(PKIX_PL_Object_Alloc (PKIX_CRL_TYPE, sizeof (PKIX_PL_CRL), (PKIX_PL_Object **)&crl, plContext), PKIX_COULDNOTCREATECRLOBJECT); /* populate the nssSignedCrl field */ crl->nssSignedCrl = nssSignedCrl; PKIX_CRL_DEBUG("\t\tCalling CERT_CompleteCRLDecodeEntries\n"); status = CERT_CompleteCRLDecodeEntries(crl->nssSignedCrl); if (status != SECSuccess) { PKIX_ERROR(PKIX_CERTCOMPLETECRLDECODEDENTRIESFAILED); } crl->issuer = NULL; crl->signatureAlgId = NULL; crl->crlNumber = NULL; crl->crlNumberAbsent = PKIX_FALSE; crl->crlEntryList = NULL; crl->critExtOids = NULL; *pCrl = crl; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(crl); } PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRL_VerifySignature( PKIX_PL_CRL *crl, PKIX_PL_PublicKey *pubKey, void *plContext) { PKIX_PL_CRL *cachedCrl = NULL; PKIX_Error *verifySig = NULL; PKIX_Error *cachedSig = NULL; PKIX_Boolean crlEqual = PKIX_FALSE; PKIX_Boolean crlInHash= PKIX_FALSE; CERTSignedCrl *nssSignedCrl = NULL; SECKEYPublicKey *nssPubKey = NULL; CERTSignedData *tbsCrl = NULL; void* wincx = NULL; SECStatus status; PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature"); PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey); /* Can call this function only with der been adopted. */ PORT_Assert(crl->adoptedDerCrl); verifySig = PKIX_PL_HashTable_Lookup (cachedCrlSigTable, (PKIX_PL_Object *) pubKey, (PKIX_PL_Object **) &cachedCrl, plContext); if (cachedCrl != NULL && verifySig == NULL) { /* Cached Signature Table lookup succeed */ PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext, PKIX_OBJECTEQUALSFAILED); if (crlEqual == PKIX_TRUE) { goto cleanup; } /* Different PubKey may hash to same value, skip add */ crlInHash = PKIX_TRUE; } nssSignedCrl = crl->nssSignedCrl; tbsCrl = &nssSignedCrl->signatureWrap; PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n"); nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI); if (!nssPubKey){ PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED); } PKIX_CHECK(pkix_pl_NssContext_GetWincx ((PKIX_PL_NssContext *)plContext, &wincx), PKIX_NSSCONTEXTGETWINCXFAILED); PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n"); status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx); if (status != SECSuccess) { PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY); } if (crlInHash == PKIX_FALSE) { cachedSig = PKIX_PL_HashTable_Add (cachedCrlSigTable, (PKIX_PL_Object *) pubKey, (PKIX_PL_Object *) crl, plContext); if (cachedSig != NULL) { PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n"); } } cleanup: if (nssPubKey){ PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n"); SECKEY_DestroyPublicKey(nssPubKey); nssPubKey = NULL; } PKIX_DECREF(cachedCrl); PKIX_DECREF(verifySig); PKIX_DECREF(cachedSig); PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRL_GetCRLNumber( PKIX_PL_CRL *crl, PKIX_PL_BigInt **pCrlNumber, void *plContext) { PKIX_PL_BigInt *crlNumber = NULL; SECItem nssCrlNumber; PLArenaPool *arena = NULL; SECStatus status; PKIX_UInt32 length = 0; char *bytes = NULL; PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber"); PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber); /* Can call this function only with der been adopted. */ PORT_Assert(crl->adoptedDerCrl); if (!crl->crlNumberAbsent && crl->crlNumber == NULL) { PKIX_OBJECT_LOCK(crl); if (!crl->crlNumberAbsent && crl->crlNumber == NULL) { nssCrlNumber.type = 0; nssCrlNumber.len = 0; nssCrlNumber.data = NULL; PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n"); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n"); status = CERT_FindCRLNumberExten (arena, &crl->nssSignedCrl->crl, &nssCrlNumber); if (status == SECSuccess) { /* Get data in bytes then convert to bigint */ length = nssCrlNumber.len; bytes = (char *)nssCrlNumber.data; PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes (bytes, length, &crlNumber, plContext), PKIX_BIGINTCREATEWITHBYTESFAILED); /* arena release does the job PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n"); SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE); */ crl->crlNumber = crlNumber; } else { crl->crlNumberAbsent = PKIX_TRUE; } } PKIX_OBJECT_UNLOCK(crl); } PKIX_INCREF(crl->crlNumber); *pCrlNumber = crl->crlNumber; cleanup: if (arena){ PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n"); PORT_FreeArena(arena, PR_FALSE); } PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_CRL_Create( PKIX_PL_ByteArray *byteArray, PKIX_PL_CRL **pCrl, void *plContext) { CERTSignedCrl *nssSignedCrl = NULL; SECItem *derCrlItem = NULL; void *derBytes = NULL; PKIX_UInt32 derLength; PKIX_PL_CRL *crl = NULL; PKIX_ENTER(CRL, "PKIX_PL_CRL_Create"); PKIX_NULLCHECK_TWO(byteArray, pCrl); PKIX_CHECK(PKIX_PL_ByteArray_GetLength (byteArray, &derLength, plContext), PKIX_BYTEARRAYGETLENGTHFAILED); if (derLength == 0) { PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING); } PKIX_CHECK(PKIX_PL_ByteArray_GetPointer (byteArray, &derBytes, plContext), PKIX_BYTEARRAYGETPOINTERFAILED); PKIX_CRL_DEBUG("\t\tCalling SECITEM_AllocItem\n"); derCrlItem = SECITEM_AllocItem(NULL, NULL, derLength); if (derCrlItem == NULL) { PKIX_ERROR(PKIX_OUTOFMEMORY); } PKIX_CRL_DEBUG("\t\tCalling PORT_Memcpy\n"); (void) PORT_Memcpy(derCrlItem->data, derBytes, derLength); PKIX_CRL_DEBUG("\t\tCalling CERT_DecodeDERCrl\n"); nssSignedCrl = CERT_DecodeDERCrl(NULL, derCrlItem, SEC_CRL_TYPE); if (nssSignedCrl == NULL) { PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED); } PKIX_CHECK(pkix_pl_CRL_CreateWithSignedCRL (nssSignedCrl, &crl, plContext), PKIX_CRLCREATEWITHSIGNEDCRLFAILED); *pCrl = crl; cleanup: if (derCrlItem != NULL) { PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n"); SECITEM_FreeItem(derCrlItem, PKIX_TRUE); derCrlItem = NULL; } if (PKIX_ERROR_RECEIVED) { if (nssSignedCrl != NULL) { PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n"); CERT_DestroyCrl(nssSignedCrl); nssSignedCrl = NULL; } PKIX_DECREF(crl); } PKIX_FREE(derBytes); PKIX_RETURN(CRL); }