Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/libpkix/pkix_pl_nss/pki/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 122 kB image not shown  

Quelle  pkix_pl_cert.c   Sprache: C

 
/* 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_cert.c
 *
 * Certificate Object Functions
 *
 */


#include "pkix_pl_cert.h"

extern PKIX_PL_HashTable *cachedCertSigTable;

/* --Private-Cert-Functions------------------------------------- */

/*
 * FUNCTION: pkix_pl_Cert_IsExtensionCritical
 * DESCRIPTION:
 *
 *  Checks the Cert specified by "cert" to determine whether the extension
 *  whose tag is the UInt32 value given by "tag" is marked as a critical
 *  extension, and stores the result in "pCritical".
 *
 *  Tags are the index into the table "oids" of SECOidData defined in the
 *  file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are
 *  are defined in secoidt.h for most of the table entries.
 *
 *  If the specified tag is invalid (not in the list of tags) or if the
 *  extension is not found in the certificate, PKIX_FALSE is stored.
 *
 * PARAMETERS
 *  "cert"
 *      Address of Cert whose extensions are to be examined. Must be non-NULL.
 *  "tag"
 *      The UInt32 value of the tag for the extension whose criticality is
 *      to be determined
 *  "pCritical"
 *      Address where the Boolean value 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 Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_pl_Cert_IsExtensionCritical(
        PKIX_PL_Cert *cert,
        PKIX_UInt32 tag,
        PKIX_Boolean *pCritical,
        void *plContext)
{
        PKIX_Boolean criticality = PKIX_FALSE;
        CERTCertExtension **extensions = NULL;
        SECStatus rv;

        PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical");
        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical);

        extensions = cert->nssCert->extensions;
        PKIX_NULLCHECK_ONE(extensions);

        PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n");
        rv = CERT_GetExtenCriticality(extensions, tag, &criticality);
        if (SECSuccess == rv) {
                *pCritical = criticality;
        } else {
                *pCritical = PKIX_FALSE;
        }

        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo
 * DESCRIPTION:
 *
 *  Decodes the contents of the CertificatePolicy extension in the
 *  CERTCertificate pointed to by "nssCert", to create a List of
 *  CertPolicyInfos, which is stored at the address "pCertPolicyInfos".
 *  A CERTCertificate contains the DER representation of the Cert.
 *  If this certificate does not have a CertificatePolicy extension,
 *  NULL will be stored. If a List is returned, it will be immutable.
 *
 * PARAMETERS
 *  "nssCert"
 *      Address of the Cert data whose extension is to be examined. Must be
 *      non-NULL.
 *  "pCertPolicyInfos"
 *      Address where the List of CertPolicyInfos 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 Cert 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_Cert_DecodePolicyInfo(
        CERTCertificate *nssCert,
        PKIX_List **pCertPolicyInfos,
        void *plContext)
{

        SECStatus rv;
        SECItem encodedCertPolicyInfo;

        /* Allocated in the arena; freed in CERT_Destroy... */
        CERTCertificatePolicies *certPol = NULL;
        CERTPolicyInfo **policyInfos = NULL;

        /* Holder for the return value */
        PKIX_List *infos = NULL;

        PKIX_PL_OID *pkixOID = NULL;
        PKIX_List *qualifiers = NULL;
        PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
        PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL;
        PKIX_PL_ByteArray *qualifierArray = NULL;

        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo");
        PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos);

        /* get PolicyInfo as a SECItem */
        PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
        rv = CERT_FindCertExtension
                (nssCert,
                SEC_OID_X509_CERTIFICATE_POLICIES,
                &encodedCertPolicyInfo);
        if (SECSuccess != rv) {
                *pCertPolicyInfos = NULL;
                goto cleanup;
        }

        /* translate PolicyInfo to CERTCertificatePolicies */
        PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n");
        certPol = CERT_DecodeCertificatePoliciesExtension
                (&encodedCertPolicyInfo);

        PORT_Free(encodedCertPolicyInfo.data);

        if (NULL == certPol) {
                PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED);
        }

        /*
         * Check whether there are any policyInfos, so we can
         * avoid creating an unnecessary List
         */

        policyInfos = certPol->policyInfos;
        if (!policyInfos) {
                *pCertPolicyInfos = NULL;
                goto cleanup;
        }

        /* create a List of CertPolicyInfo Objects */
        PKIX_CHECK(PKIX_List_Create(&infos, plContext),
                PKIX_LISTCREATEFAILED);

        /*
         * Traverse the CERTCertificatePolicies structure,
         * building each PKIX_PL_CertPolicyInfo object in turn
         */

        while (*policyInfos != NULL) {
                CERTPolicyInfo *policyInfo = *policyInfos;
                CERTPolicyQualifier **policyQualifiers =
                                          policyInfo->policyQualifiers;
                if (policyQualifiers) {
                        /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */
                        PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
                                PKIX_LISTCREATEFAILED);

                        while (*policyQualifiers != NULL) {
                            CERTPolicyQualifier *policyQualifier =
                                                         *policyQualifiers;

                            /* create the qualifier's OID object */
                            PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
                                (&policyQualifier->qualifierID,
                                 &pkixOID, plContext),
                                PKIX_OIDCREATEFAILED);

                            /* create qualifier's ByteArray object */

                            PKIX_CHECK(PKIX_PL_ByteArray_Create
                                (policyQualifier->qualifierValue.data,
                                policyQualifier->qualifierValue.len,
                                &qualifierArray,
                                plContext),
                                PKIX_BYTEARRAYCREATEFAILED);

                            /* create a CertPolicyQualifier object */

                            PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create
                                (pkixOID,
                                qualifierArray,
                                &certPolicyQualifier,
                                plContext),
                                PKIX_CERTPOLICYQUALIFIERCREATEFAILED);

                            PKIX_CHECK(PKIX_List_AppendItem
                                (qualifiers,
                                (PKIX_PL_Object *)certPolicyQualifier,
                                plContext),
                                PKIX_LISTAPPENDITEMFAILED);

                            PKIX_DECREF(pkixOID);
                            PKIX_DECREF(qualifierArray);
                            PKIX_DECREF(certPolicyQualifier);

                            policyQualifiers++;
                        }

                        PKIX_CHECK(PKIX_List_SetImmutable
                                (qualifiers, plContext),
                                PKIX_LISTSETIMMUTABLEFAILED);
                }


                /*
                 * Create an OID object pkixOID from policyInfo->policyID.
                 * (The CERTPolicyInfo structure has an oid field, but it
                 * is of type SECOidTag. This function wants a SECItem.)
                 */

                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
                        (&policyInfo->policyID, &pkixOID, plContext),
                        PKIX_OIDCREATEFAILED);

                /* Create a CertPolicyInfo object */
                PKIX_CHECK(pkix_pl_CertPolicyInfo_Create
                        (pkixOID, qualifiers, &certPolicyInfo, plContext),
                        PKIX_CERTPOLICYINFOCREATEFAILED);

                /* Append the new CertPolicyInfo object to the list */
                PKIX_CHECK(PKIX_List_AppendItem
                        (infos, (PKIX_PL_Object *)certPolicyInfo, plContext),
                        PKIX_LISTAPPENDITEMFAILED);

                PKIX_DECREF(pkixOID);
                PKIX_DECREF(qualifiers);
                PKIX_DECREF(certPolicyInfo);

                policyInfos++;
        }

        /*
         * If there were no policies, we went straight to
         * cleanup, so we don't have to NULLCHECK infos.
         */

        PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext),
                PKIX_LISTSETIMMUTABLEFAILED);

        *pCertPolicyInfos = infos;
        infos = NULL;

cleanup:
        if (certPol) {
            PKIX_CERT_DEBUG
                ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n");
            CERT_DestroyCertificatePoliciesExtension(certPol);
        }

        PKIX_DECREF(infos);
        PKIX_DECREF(pkixOID);
        PKIX_DECREF(qualifiers);
        PKIX_DECREF(certPolicyInfo);
        PKIX_DECREF(certPolicyQualifier);
        PKIX_DECREF(qualifierArray);

        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping
 * DESCRIPTION:
 *
 *  Decodes the contents of the PolicyMapping extension of the CERTCertificate
 *  pointed to by "nssCert", storing the resulting List of CertPolicyMaps at
 *  the address pointed to by "pCertPolicyMaps". If this certificate does not
 *  have a PolicyMapping extension, NULL will be stored. If a List is returned,
 *  it will be immutable.
 *
 * PARAMETERS
 *  "nssCert"
 *      Address of the Cert data whose extension is to be examined. Must be
 *      non-NULL.
 *  "pCertPolicyMaps"
 *      Address where the List of CertPolicyMaps 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 Cert 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_Cert_DecodePolicyMapping(
        CERTCertificate *nssCert,
        PKIX_List **pCertPolicyMaps,
        void *plContext)
{
        SECStatus rv;
        SECItem encodedCertPolicyMaps;

        /* Allocated in the arena; freed in CERT_Destroy... */
        CERTCertificatePolicyMappings *certPolMaps = NULL;
        CERTPolicyMap **policyMaps = NULL;

        /* Holder for the return value */
        PKIX_List *maps = NULL;

        PKIX_PL_OID *issuerDomainOID = NULL;
        PKIX_PL_OID *subjectDomainOID = NULL;
        PKIX_PL_CertPolicyMap *certPolicyMap = NULL;

        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping");
        PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps);

        /* get PolicyMappings as a SECItem */
        PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
        rv = CERT_FindCertExtension
                (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps);
        if (SECSuccess != rv) {
                *pCertPolicyMaps = NULL;
                goto cleanup;
        }

        /* translate PolicyMaps to CERTCertificatePolicyMappings */
        certPolMaps = CERT_DecodePolicyMappingsExtension
                (&encodedCertPolicyMaps);

        PORT_Free(encodedCertPolicyMaps.data);

        if (!certPolMaps) {
                PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED);
        }

        PKIX_NULLCHECK_ONE(certPolMaps->policyMaps);

        policyMaps = certPolMaps->policyMaps;

        /* create a List of CertPolicyMap Objects */
        PKIX_CHECK(PKIX_List_Create(&maps, plContext),
                PKIX_LISTCREATEFAILED);

        /*
         * Traverse the CERTCertificatePolicyMappings structure,
         * building each CertPolicyMap object in turn
         */

        do {
                CERTPolicyMap *policyMap = *policyMaps;

                /* create the OID for the issuer Domain Policy */
                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
                        (&policyMap->issuerDomainPolicy,
                         &issuerDomainOID, plContext),
                        PKIX_OIDCREATEFAILED);

                /* create the OID for the subject Domain Policy */
                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
                        (&policyMap->subjectDomainPolicy,
                         &subjectDomainOID, plContext),
                        PKIX_OIDCREATEFAILED);

                /* create the CertPolicyMap */

                PKIX_CHECK(pkix_pl_CertPolicyMap_Create
                        (issuerDomainOID,
                        subjectDomainOID,
                        &certPolicyMap,
                        plContext),
                        PKIX_CERTPOLICYMAPCREATEFAILED);

                PKIX_CHECK(PKIX_List_AppendItem
                        (maps, (PKIX_PL_Object *)certPolicyMap, plContext),
                        PKIX_LISTAPPENDITEMFAILED);

                PKIX_DECREF(issuerDomainOID);
                PKIX_DECREF(subjectDomainOID);
                PKIX_DECREF(certPolicyMap);

                policyMaps++;
        } while (*policyMaps != NULL);

        PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext),
                PKIX_LISTSETIMMUTABLEFAILED);

        *pCertPolicyMaps = maps;
        maps = NULL;

cleanup:
        if (certPolMaps) {
            PKIX_CERT_DEBUG
                ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n");
            CERT_DestroyPolicyMappingsExtension(certPolMaps);
        }

        PKIX_DECREF(maps);
        PKIX_DECREF(issuerDomainOID);
        PKIX_DECREF(subjectDomainOID);
        PKIX_DECREF(certPolicyMap);

        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints
 * DESCRIPTION:
 *
 *  Decodes the contents of the PolicyConstraints extension in the
 *  CERTCertificate pointed to by "nssCert", to obtain SkipCerts values
 *  which are stored at the addresses "pExplicitPolicySkipCerts" and
 *  "pInhibitMappingSkipCerts", respectively. If this certificate does
 *  not have an PolicyConstraints extension, or if either of the optional
 *  components is not supplied, this function stores a value of -1 for any
 *  missing component.
 *
 * PARAMETERS
 *  "nssCert"
 *      Address of the Cert data whose extension is to be examined. Must be
 *      non-NULL.
 *  "pExplicitPolicySkipCerts"
 *      Address where the SkipCert value for the requireExplicitPolicy
 *      component will be stored. Must be non-NULL.
 *  "pInhibitMappingSkipCerts"
 *      Address where the SkipCert value for the inhibitPolicyMapping
 *      component 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 Cert 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_Cert_DecodePolicyConstraints(
        CERTCertificate *nssCert,
        PKIX_Int32 *pExplicitPolicySkipCerts,
        PKIX_Int32 *pInhibitMappingSkipCerts,
        void *plContext)
{
        CERTCertificatePolicyConstraints policyConstraints;
        SECStatus rv;
        SECItem encodedCertPolicyConstraints;
        PKIX_Int32 explicitPolicySkipCerts = -1;
        PKIX_Int32 inhibitMappingSkipCerts = -1;

        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints");
        PKIX_NULLCHECK_THREE
                (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts);

        /* get the two skipCert values as SECItems */
        PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
        rv = CERT_FindCertExtension
                (nssCert,
                SEC_OID_X509_POLICY_CONSTRAINTS,
                &encodedCertPolicyConstraints);

        if (rv == SECSuccess) {

                policyConstraints.explicitPolicySkipCerts.data =
                        (unsigned char *)&explicitPolicySkipCerts;
                policyConstraints.inhibitMappingSkipCerts.data =
                        (unsigned char *)&inhibitMappingSkipCerts;

                /* translate DER to CERTCertificatePolicyConstraints */
                rv = CERT_DecodePolicyConstraintsExtension
                        (&policyConstraints, &encodedCertPolicyConstraints);

                PORT_Free(encodedCertPolicyConstraints.data);

                if (rv != SECSuccess) {
                    PKIX_ERROR
                        (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED);
                }
        }

        *pExplicitPolicySkipCerts = explicitPolicySkipCerts;
        *pInhibitMappingSkipCerts = inhibitMappingSkipCerts;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy
 * DESCRIPTION:
 *
 *  Decodes the contents of the InhibitAnyPolicy extension in the
 *  CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value,
 *  which is stored at the address "pSkipCerts". If this certificate does
 *  not have an InhibitAnyPolicy extension, -1 will be stored.
 *
 * PARAMETERS
 *  "nssCert"
 *      Address of the Cert data whose InhibitAnyPolicy extension is to be
 *      processed. Must be non-NULL.
 *  "pSkipCerts"
 *      Address where the SkipCert value from the InhibitAnyPolicy extension
 *      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 Cert 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_Cert_DecodeInhibitAnyPolicy(
        CERTCertificate *nssCert,
        PKIX_Int32 *pSkipCerts,
        void *plContext)
{
        CERTCertificateInhibitAny inhibitAny;
        SECStatus rv;
        SECItem encodedCertInhibitAny;
        PKIX_Int32 skipCerts = -1;

        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy");
        PKIX_NULLCHECK_TWO(nssCert, pSkipCerts);

        /* get InhibitAny as a SECItem */
        PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
        rv = CERT_FindCertExtension
                (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny);

        if (rv == SECSuccess) {
                inhibitAny.inhibitAnySkipCerts.data =
                        (unsigned char *)&skipCerts;

                /* translate DER to CERTCertificateInhibitAny */
                rv = CERT_DecodeInhibitAnyExtension
                        (&inhibitAny, &encodedCertInhibitAny);

                PORT_Free(encodedCertInhibitAny.data);

                if (rv != SECSuccess) {
                        PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED);
                }
        }

        *pSkipCerts = skipCerts;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames
 * DESCRIPTION:
 *
 *  Retrieves the Subject Alternative Names of the certificate specified by
 *  "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative
 *  Name extension is not present, NULL is returned at "pNssSubjAltNames".
 *  If the Subject Alternative Names has not been previously decoded, it is
 *  decoded here with lock on the "cert" unless the flag "hasLock" indicates
 *  the lock had been obtained at a higher call level.
 *
 * PARAMETERS
 *  "cert"
 *      Address of the certificate whose Subject Alternative Names extensions
 *      is retrieved. Must be non-NULL.
 *  "hasLock"
 *      Boolean indicates caller has acquired a lock.
 *      Must be non-NULL.
 *  "pNssSubjAltNames"
 *      Address where the returned Subject Alternative Names 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 Cert 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_Cert_GetNssSubjectAltNames(
        PKIX_PL_Cert *cert,
        PKIX_Boolean hasLock,
        CERTGeneralName **pNssSubjAltNames,
        void *plContext)
{
        CERTCertificate *nssCert = NULL;
        CERTGeneralName *nssOriginalAltName = NULL;
        PLArenaPool *arena = NULL;
        SECItem altNameExtension = {siBuffer, NULL, 0};
        SECStatus rv = SECFailure;

        PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames");
        PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert);

        nssCert = cert->nssCert;

        if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){

                if (!hasLock) {
                    PKIX_OBJECT_LOCK(cert);
                }

                if ((cert->nssSubjAltNames == NULL) &&
                    (!cert->subjAltNamesAbsent)){

                    PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
                        (nssCert,
                        SEC_OID_X509_SUBJECT_ALT_NAME,
                        &altNameExtension));

                    if (rv != SECSuccess) {
                        *pNssSubjAltNames = NULL;
                        cert->subjAltNamesAbsent = PKIX_TRUE;
                        goto cleanup;
                    }

                    if (cert->arenaNameConstraints == NULL) {
                        PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
                                (DER_DEFAULT_CHUNKSIZE));

                        if (arena == NULL) {
                            PKIX_ERROR(PKIX_OUTOFMEMORY);
                        }
                        cert->arenaNameConstraints = arena;
                    }

                    PKIX_PL_NSSCALLRV
                        (CERT,
                        nssOriginalAltName,
                        (CERTGeneralName *) CERT_DecodeAltNameExtension,
                        (cert->arenaNameConstraints, &altNameExtension));

                    PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data));

                    if (nssOriginalAltName == NULL) {
                        PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED);
                    }
                    cert->nssSubjAltNames = nssOriginalAltName;

                }

                if (!hasLock) {
                    PKIX_OBJECT_UNLOCK(cert);
                }
        }

        *pNssSubjAltNames = cert->nssSubjAltNames;

cleanup:
 PKIX_OBJECT_UNLOCK(lockedObject);
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage
 * DESCRIPTION:
 *
 *  For each of the ON bit in "requiredExtendedKeyUsages" that represents its
 *  SECCertUsageEnum type, this function checks "cert"'s certType (extended
 *  key usage) and key usage with what is required for SECCertUsageEnum type.
 *
 * PARAMETERS
 *  "cert"
 *      Address of the certificate whose Extended Key Usage extensions
 *      is retrieved. Must be non-NULL.
 *  "requiredExtendedKeyUsages"
 *      An unsigned integer, its bit location is ON based on the required key
 *      usage value representing in SECCertUsageEnum.
 *  "pPass"
 *      Address where the return value, indicating key usage check passed, is
 *       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 Cert 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_Cert_CheckExtendedKeyUsage(
        PKIX_PL_Cert *cert,
        PKIX_UInt32 requiredExtendedKeyUsages,
        PKIX_Boolean *pPass,
        void *plContext)
{
        PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
        PKIX_UInt32 certType = 0;
        PKIX_UInt32 requiredKeyUsage = 0;
        PKIX_UInt32 requiredCertType = 0;
        PKIX_UInt32 requiredExtendedKeyUsage = 0;
        PKIX_UInt32 i;
        PKIX_Boolean isCA = PKIX_FALSE;
        SECStatus rv = SECFailure;

        PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage");
        PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert);

        *pPass = PKIX_FALSE;

        PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n");
        cert_GetCertType(cert->nssCert);
        certType = cert->nssCert->nsCertType;

        PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
                    (cert,
                    &basicConstraints,
                    plContext),
                    PKIX_CERTGETBASICCONSTRAINTFAILED);

        if (basicConstraints != NULL) {
                PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
                    (basicConstraints, &isCA, plContext),
                    PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
        }

        i = 0;
        while (requiredExtendedKeyUsages != 0) {

                /* Find the bit location of the right-most non-zero bit */
                while (requiredExtendedKeyUsages != 0) {
                        if (((1 << i) & requiredExtendedKeyUsages) != 0) {
                                requiredExtendedKeyUsage = 1 << i;
                                break;
                        }
                        i++;
                }
                requiredExtendedKeyUsages ^= requiredExtendedKeyUsage;

                requiredExtendedKeyUsage = i;

                PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage,
                        (requiredExtendedKeyUsage,
                        isCA,
                        &requiredKeyUsage,
                        &requiredCertType));

                if (!(certType & requiredCertType)) {
                        goto cleanup;
                }

                PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage,
                        (cert->nssCert, requiredKeyUsage));
                if (rv != SECSuccess) {
                        goto cleanup;
                }
                i++;

        }

        *pPass = PKIX_TRUE;

cleanup:
        PKIX_DECREF(basicConstraints);
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_ToString_Helper
 * DESCRIPTION:
 *
 *  Helper function that creates a string representation of the Cert pointed
 *  to by "cert" and stores it at "pString", where the value of
 *  "partialString" determines whether a full or partial representation of
 *  the Cert is stored.
 *
 * PARAMETERS
 *  "cert"
 *      Address of Cert whose string representation is desired.
 *      Must be non-NULL.
 *  "partialString"
 *      Boolean indicating whether a partial Cert representation is desired.
 *  "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 Cert 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_Cert_ToString_Helper(
        PKIX_PL_Cert *cert,
        PKIX_Boolean partialString,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_String *certString = NULL;
        char *asciiFormat = NULL;
        PKIX_PL_String *formatString = NULL;
        PKIX_UInt32 certVersion;
        PKIX_PL_BigInt *certSN = NULL;
        PKIX_PL_String *certSNString = NULL;
        PKIX_PL_X500Name *certIssuer = NULL;
        PKIX_PL_String *certIssuerString = NULL;
        PKIX_PL_X500Name *certSubject = NULL;
        PKIX_PL_String *certSubjectString = NULL;
        PKIX_PL_String *notBeforeString = NULL;
        PKIX_PL_String *notAfterString = NULL;
        PKIX_List *subjAltNames = NULL;
        PKIX_PL_String *subjAltNamesString = NULL;
        PKIX_PL_ByteArray *authKeyId = NULL;
        PKIX_PL_String *authKeyIdString = NULL;
        PKIX_PL_ByteArray *subjKeyId = NULL;
        PKIX_PL_String *subjKeyIdString = NULL;
        PKIX_PL_PublicKey *nssPubKey = NULL;
        PKIX_PL_String *nssPubKeyString = NULL;
        PKIX_List *critExtOIDs = NULL;
        PKIX_PL_String *critExtOIDsString = NULL;
        PKIX_List *extKeyUsages = NULL;
        PKIX_PL_String *extKeyUsagesString = NULL;
        PKIX_PL_CertBasicConstraints *basicConstraint = NULL;
        PKIX_PL_String *certBasicConstraintsString = NULL;
        PKIX_List *policyInfo = NULL;
        PKIX_PL_String *certPolicyInfoString = NULL;
        PKIX_List *certPolicyMappings = NULL;
        PKIX_PL_String *certPolicyMappingsString = NULL;
        PKIX_Int32 certExplicitPolicy = 0;
        PKIX_Int32 certInhibitMapping = 0;
        PKIX_Int32 certInhibitAnyPolicy = 0;
        PKIX_PL_CertNameConstraints *nameConstraints = NULL;
        PKIX_PL_String *nameConstraintsString = NULL;
        PKIX_List *authorityInfoAccess = NULL;
        PKIX_PL_String *authorityInfoAccessString = NULL;
        PKIX_List *subjectInfoAccess = NULL;
        PKIX_PL_String *subjectInfoAccessString = NULL;

        PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper");
        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString);

        /*
         * XXX Add to this format as certificate components are developed.
         */


        if (partialString){
                asciiFormat =
                        "\t[Issuer: %s\n"
                        "\t Subject: %s]";
        } else {
                asciiFormat =
                        "[\n"
                        "\tVersion: v%d\n"
                        "\tSerialNumber: %s\n"
                        "\tIssuer: %s\n"
                        "\tSubject: %s\n"
                        "\tValidity: [From: %s\n"
                        "\t To: %s]\n"
                        "\tSubjectAltNames: %s\n"
                        "\tAuthorityKeyId: %s\n"
                        "\tSubjectKeyId: %s\n"
                        "\tSubjPubKeyAlgId: %s\n"
                        "\tCritExtOIDs: %s\n"
                        "\tExtKeyUsages: %s\n"
                        "\tBasicConstraint: %s\n"
                        "\tCertPolicyInfo: %s\n"
                        "\tPolicyMappings: %s\n"
                        "\tExplicitPolicy: %d\n"
                        "\tInhibitMapping: %d\n"
                        "\tInhibitAnyPolicy:%d\n"
                        "\tNameConstraints: %s\n"
                        "\tAuthorityInfoAccess: %s\n"
                        "\tSubjectInfoAccess: %s\n"
                        "\tCacheFlag: %d\n"
                        "]\n";
        }



        PKIX_CHECK(PKIX_PL_String_Create
                (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
                PKIX_STRINGCREATEFAILED);

        /* Issuer */
        PKIX_CHECK(PKIX_PL_Cert_GetIssuer
                (cert, &certIssuer, plContext),
                PKIX_CERTGETISSUERFAILED);

        PKIX_CHECK(PKIX_PL_Object_ToString
                ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext),
                PKIX_X500NAMETOSTRINGFAILED);

        /* Subject */
        PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext),
                PKIX_CERTGETSUBJECTFAILED);

        PKIX_TOSTRING(certSubject, &certSubjectString, plContext,
                PKIX_X500NAMETOSTRINGFAILED);

        if (partialString){
                PKIX_CHECK(PKIX_PL_Sprintf
                            (&certString,
                            plContext,
                            formatString,
                            certIssuerString,
                            certSubjectString),
                            PKIX_SPRINTFFAILED);

                *pString = certString;
                goto cleanup;
        }

        /* Version */
        PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext),
                PKIX_CERTGETVERSIONFAILED);

        /* SerialNumber */
        PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext),
                PKIX_CERTGETSERIALNUMBERFAILED);

        PKIX_CHECK(PKIX_PL_Object_ToString
                ((PKIX_PL_Object *)certSN, &certSNString, plContext),
                PKIX_BIGINTTOSTRINGFAILED);

        /* Validity: NotBefore */
        PKIX_CHECK(pkix_pl_Date_ToString_Helper
                (&(cert->nssCert->validity.notBefore),
                ¬BeforeString,
                plContext),
                PKIX_DATETOSTRINGHELPERFAILED);

        /* Validity: NotAfter */
        PKIX_CHECK(pkix_pl_Date_ToString_Helper
                (&(cert->nssCert->validity.notAfter),
                ¬AfterString,
                plContext),
                PKIX_DATETOSTRINGHELPERFAILED);

        /* SubjectAltNames */
        PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
                (cert, &subjAltNames, plContext),
                PKIX_CERTGETSUBJECTALTNAMESFAILED);

        PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        /* AuthorityKeyIdentifier */
        PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
                (cert, &authKeyId, plContext),
                PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);

        PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext,
                PKIX_BYTEARRAYTOSTRINGFAILED);

        /* SubjectKeyIdentifier */
        PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
                (cert, &subjKeyId, plContext),
                PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);

        PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext,
                PKIX_BYTEARRAYTOSTRINGFAILED);

        /* SubjectPublicKey */
        PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
                    (cert, &nssPubKey, plContext),
                    PKIX_CERTGETSUBJECTPUBLICKEYFAILED);

        PKIX_CHECK(PKIX_PL_Object_ToString
                ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext),
                PKIX_PUBLICKEYTOSTRINGFAILED);

        /* CriticalExtensionOIDs */
        PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
                (cert, &critExtOIDs, plContext),
                PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);

        PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        /* ExtendedKeyUsages */
        PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
                (cert, &extKeyUsages, plContext),
                PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);

        PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        /* CertBasicConstraints */
        PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
                (cert, &basicConstraint, plContext),
                PKIX_CERTGETBASICCONSTRAINTSFAILED);

        PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext,
                PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED);

        /* CertPolicyInfo */
        PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
                (cert, &policyInfo, plContext),
                PKIX_CERTGETPOLICYINFORMATIONFAILED);

        PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        /* Advanced Policies */
        PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
                (cert, &certPolicyMappings, plContext),
                PKIX_CERTGETPOLICYMAPPINGSFAILED);

        PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
                (cert, &certExplicitPolicy, plContext),
                PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);

        PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
                (cert, &certInhibitMapping, plContext),
                PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);

        PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
                (cert, &certInhibitAnyPolicy, plContext),
                PKIX_CERTGETINHIBITANYPOLICYFAILED);

        /* Name Constraints */
        PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
                (cert, &nameConstraints, plContext),
                PKIX_CERTGETNAMECONSTRAINTSFAILED);

        PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        /* Authority Information Access */
        PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
                (cert, &authorityInfoAccess, plContext),
                PKIX_CERTGETAUTHORITYINFOACCESSFAILED);

        PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        /* Subject Information Access */
        PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess
                (cert, &subjectInfoAccess, plContext),
                PKIX_CERTGETSUBJECTINFOACCESSFAILED);

        PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        PKIX_CHECK(PKIX_PL_Sprintf
                    (&certString,
                    plContext,
                    formatString,
                    certVersion + 1,
                    certSNString,
                    certIssuerString,
                    certSubjectString,
                    notBeforeString,
                    notAfterString,
                    subjAltNamesString,
                    authKeyIdString,
                    subjKeyIdString,
                    nssPubKeyString,
                    critExtOIDsString,
                    extKeyUsagesString,
                    certBasicConstraintsString,
                    certPolicyInfoString,
                    certPolicyMappingsString,
                    certExplicitPolicy,         /* an Int32, not a String */
                    certInhibitMapping,         /* an Int32, not a String */
                    certInhibitAnyPolicy,       /* an Int32, not a String */
                    nameConstraintsString,
                    authorityInfoAccessString,
                    subjectInfoAccessString,
                    cert->cacheFlag),           /* a boolean */
                    PKIX_SPRINTFFAILED);

        *pString = certString;

cleanup:
        PKIX_DECREF(certSN);
        PKIX_DECREF(certSNString);
        PKIX_DECREF(certIssuer);
        PKIX_DECREF(certIssuerString);
        PKIX_DECREF(certSubject);
        PKIX_DECREF(certSubjectString);
        PKIX_DECREF(notBeforeString);
        PKIX_DECREF(notAfterString);
        PKIX_DECREF(subjAltNames);
        PKIX_DECREF(subjAltNamesString);
        PKIX_DECREF(authKeyId);
        PKIX_DECREF(authKeyIdString);
        PKIX_DECREF(subjKeyId);
        PKIX_DECREF(subjKeyIdString);
        PKIX_DECREF(nssPubKey);
        PKIX_DECREF(nssPubKeyString);
        PKIX_DECREF(critExtOIDs);
        PKIX_DECREF(critExtOIDsString);
        PKIX_DECREF(extKeyUsages);
        PKIX_DECREF(extKeyUsagesString);
        PKIX_DECREF(basicConstraint);
        PKIX_DECREF(certBasicConstraintsString);
        PKIX_DECREF(policyInfo);
        PKIX_DECREF(certPolicyInfoString);
        PKIX_DECREF(certPolicyMappings);
        PKIX_DECREF(certPolicyMappingsString);
        PKIX_DECREF(nameConstraints);
        PKIX_DECREF(nameConstraintsString);
        PKIX_DECREF(authorityInfoAccess);
        PKIX_DECREF(authorityInfoAccessString);
        PKIX_DECREF(subjectInfoAccess);
        PKIX_DECREF(subjectInfoAccessString);
        PKIX_DECREF(formatString);

        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_Destroy
 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 */

static PKIX_Error *
pkix_pl_Cert_Destroy(
        PKIX_PL_Object *object,
        void *plContext)
{
        PKIX_PL_Cert *cert = NULL;

        PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy");
        PKIX_NULLCHECK_ONE(object);

        PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
                    PKIX_OBJECTNOTCERT);

        cert = (PKIX_PL_Cert*)object;

        PKIX_DECREF(cert->subject);
        PKIX_DECREF(cert->issuer);
        PKIX_DECREF(cert->subjAltNames);
        PKIX_DECREF(cert->publicKeyAlgId);
        PKIX_DECREF(cert->publicKey);
        PKIX_DECREF(cert->serialNumber);
        PKIX_DECREF(cert->critExtOids);
        PKIX_DECREF(cert->authKeyId);
        PKIX_DECREF(cert->subjKeyId);
        PKIX_DECREF(cert->extKeyUsages);
        PKIX_DECREF(cert->certBasicConstraints);
        PKIX_DECREF(cert->certPolicyInfos);
        PKIX_DECREF(cert->certPolicyMappings);
        PKIX_DECREF(cert->nameConstraints);
        PKIX_DECREF(cert->store);
        PKIX_DECREF(cert->authorityInfoAccess);
        PKIX_DECREF(cert->subjectInfoAccess);
        PKIX_DECREF(cert->crldpList);

        if (cert->arenaNameConstraints){
                /* This arena was allocated for SubjectAltNames */
                PKIX_PL_NSSCALL(CERT, PORT_FreeArena,
                        (cert->arenaNameConstraints, PR_FALSE));

                cert->arenaNameConstraints = NULL;
                cert->nssSubjAltNames = NULL;
        }

        CERT_DestroyCertificate(cert->nssCert);
        cert->nssCert = NULL;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_ToString
 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
 */

static PKIX_Error *
pkix_pl_Cert_ToString(
        PKIX_PL_Object *object,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_PL_String *certString = NULL;
        PKIX_PL_Cert *pkixCert = NULL;

        PKIX_ENTER(CERT, "pkix_pl_Cert_toString");
        PKIX_NULLCHECK_TWO(object, pString);

        PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
                    PKIX_OBJECTNOTCERT);

        pkixCert = (PKIX_PL_Cert *)object;

        PKIX_CHECK(pkix_pl_Cert_ToString_Helper
                    (pkixCert, PKIX_FALSE, &certString, plContext),
                    PKIX_CERTTOSTRINGHELPERFAILED);

        *pString = certString;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_Hashcode
 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
 */

static PKIX_Error *
pkix_pl_Cert_Hashcode(
        PKIX_PL_Object *object,
        PKIX_UInt32 *pHashcode,
        void *plContext)
{
        PKIX_PL_Cert *pkixCert = NULL;
        CERTCertificate *nssCert = NULL;
        unsigned char *derBytes = NULL;
        PKIX_UInt32 derLength;
        PKIX_UInt32 certHash;

        PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode");
        PKIX_NULLCHECK_TWO(object, pHashcode);

        PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
                    PKIX_OBJECTNOTCERT);

        pkixCert = (PKIX_PL_Cert *)object;

        nssCert = pkixCert->nssCert;
        derBytes = (nssCert->derCert).data;
        derLength = (nssCert->derCert).len;

        PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
                    PKIX_HASHFAILED);

        *pHashcode = certHash;

cleanup:
        PKIX_RETURN(CERT);
}


/*
 * FUNCTION: pkix_pl_Cert_Equals
 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
 */

static PKIX_Error *
pkix_pl_Cert_Equals(
        PKIX_PL_Object *firstObject,
        PKIX_PL_Object *secondObject,
        PKIX_Boolean *pResult,
        void *plContext)
{
        CERTCertificate *firstCert = NULL;
        CERTCertificate *secondCert = NULL;
        PKIX_UInt32 secondType;
        PKIX_Boolean cmpResult;

        PKIX_ENTER(CERT, "pkix_pl_Cert_Equals");
        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);

        /* test that firstObject is a Cert */
        PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext),
                    PKIX_FIRSTOBJECTNOTCERT);

        /*
         * Since we know firstObject is a Cert, if both references are
         * identical, they must be equal
         */

        if (firstObject == secondObject){
                *pResult = PKIX_TRUE;
                goto cleanup;
        }

        /*
         * If secondObject isn't a Cert, we don't throw an error.
         * We simply return a Boolean result of FALSE
         */

        *pResult = PKIX_FALSE;
        PKIX_CHECK(PKIX_PL_Object_GetType
                    (secondObject, &secondType, plContext),
                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
        if (secondType != PKIX_CERT_TYPE) goto cleanup;

        firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert;
        secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert;

        PKIX_NULLCHECK_TWO(firstCert, secondCert);

        /* CERT_CompareCerts does byte comparison on DER encodings of certs */
        PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n");
        cmpResult = CERT_CompareCerts(firstCert, secondCert);

        *pResult = cmpResult;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_RegisterSelf
 * DESCRIPTION:
 *  Registers PKIX_CERT_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_Cert_RegisterSelf(void *plContext)
{

        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
        pkix_ClassTable_Entry entry;

        PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf");

        entry.description = "Cert";
        entry.objCounter = 0;
        entry.typeObjectSize = sizeof(PKIX_PL_Cert);
        entry.destructor = pkix_pl_Cert_Destroy;
        entry.equalsFunction = pkix_pl_Cert_Equals;
        entry.hashcodeFunction = pkix_pl_Cert_Hashcode;
        entry.toStringFunction = pkix_pl_Cert_ToString;
        entry.comparator = NULL;
        entry.duplicateFunction = pkix_duplicateImmutable;

        systemClasses[PKIX_CERT_TYPE] = entry;

        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert
 * DESCRIPTION:
 *
 *  Creates a new certificate using the CERTCertificate pointed to by "nssCert"
 *  and stores it at "pCert". Once created, a Cert is immutable.
 *
 *  This function is primarily used as a convenience function for the
 *  performance tests that have easy access to a CERTCertificate.
 *
 * PARAMETERS:
 *  "nssCert"
 *      Address of CERTCertificate representing the NSS certificate.
 *      Must be non-NULL.
 *  "pCert"
 *      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 Cert 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_Cert_CreateWithNSSCert(
        CERTCertificate *nssCert,
        PKIX_PL_Cert **pCert,
        void *plContext)
{
        PKIX_PL_Cert *cert = NULL;

        PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert");
        PKIX_NULLCHECK_TWO(pCert, nssCert);

        /* create a PKIX_PL_Cert object */
        PKIX_CHECK(PKIX_PL_Object_Alloc
                    (PKIX_CERT_TYPE,
                    sizeof (PKIX_PL_Cert),
                    (PKIX_PL_Object **)&cert,
                    plContext),
                    PKIX_COULDNOTCREATEOBJECT);

        /* populate the nssCert field */
        cert->nssCert = nssCert;

        /* initialize remaining fields */
        /*
         * Fields ending with Absent are initialized to PKIX_FALSE so that the
         * first time we need the value we will look for it. If we find it is
         * actually absent, the flag will at that time be set to PKIX_TRUE to
         * prevent searching for it later.
         * Fields ending with Processed are those where a value is defined
         * for the Absent case, and a value of zero is possible. When the
         * flag is still true we have to look for the field, set the default
         * value if necessary, and set the Processed flag to PKIX_TRUE.
         */

        cert->subject = NULL;
        cert->issuer = NULL;
        cert->subjAltNames = NULL;
        cert->subjAltNamesAbsent = PKIX_FALSE;
        cert->publicKeyAlgId = NULL;
        cert->publicKey = NULL;
        cert->serialNumber = NULL;
        cert->critExtOids = NULL;
        cert->subjKeyId = NULL;
        cert->subjKeyIdAbsent = PKIX_FALSE;
        cert->authKeyId = NULL;
        cert->authKeyIdAbsent = PKIX_FALSE;
        cert->extKeyUsages = NULL;
        cert->extKeyUsagesAbsent = PKIX_FALSE;
        cert->certBasicConstraints = NULL;
        cert->basicConstraintsAbsent = PKIX_FALSE;
        cert->certPolicyInfos = NULL;
        cert->policyInfoAbsent = PKIX_FALSE;
        cert->policyMappingsAbsent = PKIX_FALSE;
        cert->certPolicyMappings = NULL;
        cert->policyConstraintsProcessed = PKIX_FALSE;
        cert->policyConstraintsExplicitPolicySkipCerts = 0;
        cert->policyConstraintsInhibitMappingSkipCerts = 0;
        cert->inhibitAnyPolicyProcessed = PKIX_FALSE;
        cert->inhibitAnySkipCerts = 0;
        cert->nameConstraints = NULL;
        cert->nameConstraintsAbsent = PKIX_FALSE;
        cert->arenaNameConstraints = NULL;
        cert->nssSubjAltNames = NULL;
        cert->cacheFlag = PKIX_FALSE;
        cert->store = NULL;
        cert->authorityInfoAccess = NULL;
        cert->subjectInfoAccess = NULL;
        cert->isUserTrustAnchor = PKIX_FALSE;
        cert->crldpList = NULL;

        *pCert = cert;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: pkix_pl_Cert_CreateToList
 * DESCRIPTION:
 *
 *  Creates a new certificate using the DER-encoding pointed to by "derCertItem"
 *  and appends it to the list pointed to by "certList". If Cert creation fails,
 *  the function returns with certList unchanged, but any decoding Error is
 *  discarded.
 *
 * PARAMETERS:
 *  "derCertItem"
 *      Address of SECItem containing the DER representation of a certificate.
 *      Must be non-NULL.
 *  "certList"
 *      Address of List to which the Cert will be appended, if successfully
 *      created. May be empty, but 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 Cert 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_Cert_CreateToList(
        SECItem *derCertItem,
        PKIX_List *certList,
        void *plContext)
{
        CERTCertificate *nssCert = NULL;
        PKIX_PL_Cert *cert = NULL;
        CERTCertDBHandle *handle;

        PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
        PKIX_NULLCHECK_TWO(derCertItem, certList);

        handle  = CERT_GetDefaultCertDB();
        nssCert = CERT_NewTempCertificate(handle, derCertItem,
       /* nickname */ NULL, 
       /* isPerm   */ PR_FALSE, 
       /* copyDer  */ PR_TRUE);
        if (!nssCert) {
            goto cleanup;
        }

        PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
                   (nssCert, &cert, plContext),
                   PKIX_CERTCREATEWITHNSSCERTFAILED);

        nssCert = NULL;

        PKIX_CHECK(PKIX_List_AppendItem
                   (certList, (PKIX_PL_Object *) cert, plContext),
                   PKIX_LISTAPPENDITEMFAILED);

cleanup:
        if (nssCert) {
            CERT_DestroyCertificate(nssCert);
        }

        PKIX_DECREF(cert);
        PKIX_RETURN(CERT);
}

/* --Public-Functions------------------------------------------------------- */

/*
 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h)
 * XXX We may want to cache the cert after parsing it, so it can be reused
 * XXX Are the NSS/NSPR functions thread safe
 */

PKIX_Error *
PKIX_PL_Cert_Create(
        PKIX_PL_ByteArray *byteArray,
        PKIX_PL_Cert **pCert,
        void *plContext)
{
        CERTCertificate *nssCert = NULL;
        SECItem *derCertItem = NULL;
        void *derBytes = NULL;
        PKIX_UInt32 derLength;
        PKIX_PL_Cert *cert = NULL;
        CERTCertDBHandle *handle;

        PKIX_ENTER(CERT, "PKIX_PL_Cert_Create");
        PKIX_NULLCHECK_TWO(pCert, byteArray);

        PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
                    (byteArray, &derBytes, plContext),
                    PKIX_BYTEARRAYGETPOINTERFAILED);

        PKIX_CHECK(PKIX_PL_ByteArray_GetLength
                    (byteArray, &derLength, plContext),
                    PKIX_BYTEARRAYGETLENGTHFAILED);

        derCertItem = SECITEM_AllocItem(NULL, NULL, derLength);
        if (derCertItem == NULL){
                PKIX_ERROR(PKIX_OUTOFMEMORY);
        }

        (void) PORT_Memcpy(derCertItem->data, derBytes, derLength);

        /*
         * setting copyDER to true forces NSS to make its own copy of the DER,
         * allowing us to free our copy without worrying about whether NSS
         * is still using it
         */

        handle  = CERT_GetDefaultCertDB();
        nssCert = CERT_NewTempCertificate(handle, derCertItem,
       /* nickname */ NULL, 
       /* isPerm   */ PR_FALSE, 
       /* copyDer  */ PR_TRUE);
        if (!nssCert){
                PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED);
        }

        PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
                (nssCert, &cert, plContext),
                PKIX_CERTCREATEWITHNSSCERTFAILED);

        *pCert = cert;

cleanup:
        if (derCertItem){
                SECITEM_FreeItem(derCertItem, PKIX_TRUE);
        }

        if (nssCert && PKIX_ERROR_RECEIVED){
                PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
                CERT_DestroyCertificate(nssCert);
                nssCert = NULL;
        }

        PKIX_FREE(derBytes);
        PKIX_RETURN(CERT);
}


/*
 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate
 *  (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_CreateFromCERTCertificate(
        const CERTCertificate *nssCert,
        PKIX_PL_Cert **pCert,
        void *plContext)
{
        void *buf = NULL;
        PKIX_UInt32 len;
        PKIX_PL_ByteArray *byteArray = NULL;

        PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert");
        PKIX_NULLCHECK_TWO(pCert, nssCert);

        buf = (void*)nssCert->derCert.data;
        len = nssCert->derCert.len;

        PKIX_CHECK(
            PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext),
            PKIX_BYTEARRAYCREATEFAILED);

        PKIX_CHECK(
            PKIX_PL_Cert_Create(byteArray, pCert, plContext),
            PKIX_CERTCREATEWITHNSSCERTFAILED);

#ifdef PKIX_UNDEF
        /* will be tested and used as a patch for bug 391612 */
        nssCert = CERT_DupCertificate(nssInCert);

        PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
                (nssCert, &cert, plContext),
                PKIX_CERTCREATEWITHNSSCERTFAILED);
#endif /* PKIX_UNDEF */

cleanup:

#ifdef PKIX_UNDEF
        if (nssCert && PKIX_ERROR_RECEIVED){
                PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
                CERT_DestroyCertificate(nssCert);
                nssCert = NULL;
        }
#endif /* PKIX_UNDEF */

        PKIX_DECREF(byteArray);
        PKIX_RETURN(CERT);
}


/*
 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_GetVersion(
        PKIX_PL_Cert *cert,
        PKIX_UInt32 *pVersion,
        void *plContext)
{
        CERTCertificate *nssCert = NULL;
        PKIX_UInt32 myVersion = 0;  /* v1 */

        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion");
        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion);

        nssCert = cert->nssCert;
        if (nssCert->version.len != 0) {
                myVersion = *(nssCert->version.data);
        }

        if (myVersion > 2){
                PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3);
        }

        *pVersion = myVersion;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_GetSerialNumber(
        PKIX_PL_Cert *cert,
        PKIX_PL_BigInt **pSerialNumber,
        void *plContext)
{
        CERTCertificate *nssCert = NULL;
        SECItem serialNumItem;
        PKIX_PL_BigInt *serialNumber = NULL;
        char *bytes = NULL;
        PKIX_UInt32 length;

        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber");
        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber);

        if (cert->serialNumber == NULL){

                PKIX_OBJECT_LOCK(cert);

                if (cert->serialNumber == NULL){

                        nssCert = cert->nssCert;
                        serialNumItem = nssCert->serialNumber;

                        length = serialNumItem.len;
                        bytes = (char *)serialNumItem.data;

                        PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
                                    (bytes, length, &serialNumber, plContext),
                                    PKIX_BIGINTCREATEWITHBYTESFAILED);

                        /* save a cached copy in case it is asked for again */
                        cert->serialNumber = serialNumber;
                }

                PKIX_OBJECT_UNLOCK(cert);
        }

        PKIX_INCREF(cert->serialNumber);
        *pSerialNumber = cert->serialNumber;

cleanup:
 PKIX_OBJECT_UNLOCK(lockedObject);
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_GetSubject(
        PKIX_PL_Cert *cert,
        PKIX_PL_X500Name **pCertSubject,
        void *plContext)
{
        PKIX_PL_X500Name *pkixSubject = NULL;
        CERTName *subjName = NULL;
        SECItem  *derSubjName = NULL;

        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject");
        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject);

        /* if we don't have a cached copy from before, we create one */
        if (cert->subject == NULL){

                PKIX_OBJECT_LOCK(cert);

                if (cert->subject == NULL){

                        subjName = &cert->nssCert->subject;
                        derSubjName = &cert->nssCert->derSubject;

                        /* if there is no subject name */
                        if (derSubjName->data == NULL) {

                                pkixSubject = NULL;

                        } else {
                                PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
                                    (derSubjName, subjName, &pkixSubject,
                                     plContext),
                                    PKIX_X500NAMECREATEFROMCERTNAMEFAILED);

                        }
                        /* save a cached copy in case it is asked for again */
                        cert->subject = pkixSubject;
                }

                PKIX_OBJECT_UNLOCK(cert);
        }

        PKIX_INCREF(cert->subject);
        *pCertSubject = cert->subject;

cleanup:
 PKIX_OBJECT_UNLOCK(lockedObject);
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_GetIssuer(
        PKIX_PL_Cert *cert,
        PKIX_PL_X500Name **pCertIssuer,
        void *plContext)
{
        PKIX_PL_X500Name *pkixIssuer = NULL;
        SECItem  *derIssuerName = NULL;
        CERTName *issuerName = NULL;

        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer");
        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer);

        /* if we don't have a cached copy from before, we create one */
        if (cert->issuer == NULL){

                PKIX_OBJECT_LOCK(cert);

                if (cert->issuer == NULL){

                        issuerName = &cert->nssCert->issuer;
                        derIssuerName = &cert->nssCert->derIssuer;

                        /* if there is no subject name */
                        PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
                                    (derIssuerName, issuerName,
                                     &pkixIssuer, plContext),
                                    PKIX_X500NAMECREATEFROMCERTNAMEFAILED);

                        /* save a cached copy in case it is asked for again */
                        cert->issuer = pkixIssuer;
                }

                PKIX_OBJECT_UNLOCK(cert);
        }

        PKIX_INCREF(cert->issuer);
        *pCertIssuer = cert->issuer;

cleanup:
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_GetSubjectAltNames(
        PKIX_PL_Cert *cert,
        PKIX_List **pSubjectAltNames,  /* list of PKIX_PL_GeneralName */
        void *plContext)
{
        PKIX_PL_GeneralName *pkixAltName = NULL;
        PKIX_List *altNamesList = NULL;

        CERTGeneralName *nssOriginalAltName = NULL;
        CERTGeneralName *nssTempAltName = NULL;

        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames");
        PKIX_NULLCHECK_TWO(cert, pSubjectAltNames);

        /* if we don't have a cached copy from before, we create one */
        if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){

                PKIX_OBJECT_LOCK(cert);

                if ((cert->subjAltNames == NULL) &&
                    (!cert->subjAltNamesAbsent)){

                        PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
                                (cert,
                                PKIX_TRUE,
                                &nssOriginalAltName,
                                plContext),
                                PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);

                        if (nssOriginalAltName == NULL) {
                                cert->subjAltNamesAbsent = PKIX_TRUE;
                                pSubjectAltNames = NULL;
                                goto cleanup;
                        }

                        nssTempAltName = nssOriginalAltName;

                        PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext),
                                PKIX_LISTCREATEFAILED);

                        do {
                            PKIX_CHECK(pkix_pl_GeneralName_Create
                                (nssTempAltName, &pkixAltName, plContext),
                                PKIX_GENERALNAMECREATEFAILED);

                            PKIX_CHECK(PKIX_List_AppendItem
                                (altNamesList,
                                (PKIX_PL_Object *)pkixAltName,
                                plContext),
                                PKIX_LISTAPPENDITEMFAILED);

                            PKIX_DECREF(pkixAltName);

                            PKIX_CERT_DEBUG
                                ("\t\tCalling CERT_GetNextGeneralName).\n");
                            nssTempAltName = CERT_GetNextGeneralName
                                (nssTempAltName);

                        } while (nssTempAltName != nssOriginalAltName);

                        /* save a cached copy in case it is asked for again */
                        cert->subjAltNames = altNamesList;
                        PKIX_CHECK(PKIX_List_SetImmutable
                                (cert->subjAltNames, plContext),
                                PKIX_LISTSETIMMUTABLEFAILED);

                }

                PKIX_OBJECT_UNLOCK(cert);
        }

        PKIX_INCREF(cert->subjAltNames);

        *pSubjectAltNames = cert->subjAltNames;

cleanup:
        PKIX_DECREF(pkixAltName);
        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(altNamesList);
        }
        PKIX_RETURN(CERT);
}

/*
 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h)
 */

PKIX_Error *
PKIX_PL_Cert_GetAllSubjectNames(
        PKIX_PL_Cert *cert,
        PKIX_List **pAllSubjectNames,  /* list of PKIX_PL_GeneralName */
        void *plContext)
{
        CERTGeneralName *nssOriginalSubjectName = NULL;
        CERTGeneralName *nssTempSubjectName = NULL;
        PKIX_List *allSubjectNames = NULL;
        PKIX_PL_GeneralName *pkixSubjectName = NULL;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=75 G=85

¤ Dauer der Verarbeitung: 0.60 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.