/*
 * 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);
}
Example #5
0
/*
 * 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);
}
Example #6
0
/*
 * 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);
}