tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_cert.c (125791B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_pl_cert.c
      6 *
      7 * Certificate Object Functions
      8 *
      9 */
     10 
     11 #include "pkix_pl_cert.h"
     12 
     13 extern PKIX_PL_HashTable *cachedCertSigTable;
     14 
     15 /* --Private-Cert-Functions------------------------------------- */
     16 
     17 /*
     18 * FUNCTION: pkix_pl_Cert_IsExtensionCritical
     19 * DESCRIPTION:
     20 *
     21 *  Checks the Cert specified by "cert" to determine whether the extension
     22 *  whose tag is the UInt32 value given by "tag" is marked as a critical
     23 *  extension, and stores the result in "pCritical".
     24 *
     25 *  Tags are the index into the table "oids" of SECOidData defined in the
     26 *  file secoid.c. Constants, such as SEC_OID_X509_CERTIFICATE_POLICIES, are
     27 *  are defined in secoidt.h for most of the table entries.
     28 *
     29 *  If the specified tag is invalid (not in the list of tags) or if the
     30 *  extension is not found in the certificate, PKIX_FALSE is stored.
     31 *
     32 * PARAMETERS
     33 *  "cert"
     34 *      Address of Cert whose extensions are to be examined. Must be non-NULL.
     35 *  "tag"
     36 *      The UInt32 value of the tag for the extension whose criticality is
     37 *      to be determined
     38 *  "pCritical"
     39 *      Address where the Boolean value will be stored. Must be non-NULL.
     40 *  "plContext"
     41 *      Platform-specific context pointer.
     42 * THREAD SAFETY:
     43 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     44 * RETURNS:
     45 *  Returns NULL if the function succeeds.
     46 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     47 */
     48 static PKIX_Error *
     49 pkix_pl_Cert_IsExtensionCritical(
     50        PKIX_PL_Cert *cert,
     51        PKIX_UInt32 tag,
     52        PKIX_Boolean *pCritical,
     53        void *plContext)
     54 {
     55        PKIX_Boolean criticality = PKIX_FALSE;
     56        CERTCertExtension **extensions = NULL;
     57        SECStatus rv;
     58 
     59        PKIX_ENTER(CERT, "pkix_pl_Cert_IsExtensionCritical");
     60        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCritical);
     61 
     62        extensions = cert->nssCert->extensions;
     63        PKIX_NULLCHECK_ONE(extensions);
     64 
     65        PKIX_CERT_DEBUG("\t\tCalling CERT_GetExtenCriticality).\n");
     66        rv = CERT_GetExtenCriticality(extensions, tag, &criticality);
     67        if (SECSuccess == rv) {
     68                *pCritical = criticality;
     69        } else {
     70                *pCritical = PKIX_FALSE;
     71        }
     72 
     73        PKIX_RETURN(CERT);
     74 }
     75 
     76 /*
     77 * FUNCTION: pkix_pl_Cert_DecodePolicyInfo
     78 * DESCRIPTION:
     79 *
     80 *  Decodes the contents of the CertificatePolicy extension in the
     81 *  CERTCertificate pointed to by "nssCert", to create a List of
     82 *  CertPolicyInfos, which is stored at the address "pCertPolicyInfos".
     83 *  A CERTCertificate contains the DER representation of the Cert.
     84 *  If this certificate does not have a CertificatePolicy extension,
     85 *  NULL will be stored. If a List is returned, it will be immutable.
     86 *
     87 * PARAMETERS
     88 *  "nssCert"
     89 *      Address of the Cert data whose extension is to be examined. Must be
     90 *      non-NULL.
     91 *  "pCertPolicyInfos"
     92 *      Address where the List of CertPolicyInfos will be stored. Must be
     93 *      non-NULL.
     94 *  "plContext"
     95 *      Platform-specific context pointer.
     96 * THREAD SAFETY:
     97 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     98 * RETURNS:
     99 *  Returns NULL if the function succeeds.
    100 *  Returns a Cert Error if the function fails in a non-fatal way.
    101 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    102 */
    103 static PKIX_Error *
    104 pkix_pl_Cert_DecodePolicyInfo(
    105        CERTCertificate *nssCert,
    106        PKIX_List **pCertPolicyInfos,
    107        void *plContext)
    108 {
    109 
    110        SECStatus rv;
    111        SECItem encodedCertPolicyInfo;
    112 
    113        /* Allocated in the arena; freed in CERT_Destroy... */
    114        CERTCertificatePolicies *certPol = NULL;
    115        CERTPolicyInfo **policyInfos = NULL;
    116 
    117        /* Holder for the return value */
    118        PKIX_List *infos = NULL;
    119 
    120        PKIX_PL_OID *pkixOID = NULL;
    121        PKIX_List *qualifiers = NULL;
    122        PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
    123        PKIX_PL_CertPolicyQualifier *certPolicyQualifier = NULL;
    124        PKIX_PL_ByteArray *qualifierArray = NULL;
    125 
    126        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyInfo");
    127        PKIX_NULLCHECK_TWO(nssCert, pCertPolicyInfos);
    128 
    129        /* get PolicyInfo as a SECItem */
    130        PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
    131        rv = CERT_FindCertExtension
    132                (nssCert,
    133                SEC_OID_X509_CERTIFICATE_POLICIES,
    134                &encodedCertPolicyInfo);
    135        if (SECSuccess != rv) {
    136                *pCertPolicyInfos = NULL;
    137                goto cleanup;
    138        }
    139 
    140        /* translate PolicyInfo to CERTCertificatePolicies */
    141        PKIX_CERT_DEBUG("\t\tCERT_DecodeCertificatePoliciesExtension).\n");
    142        certPol = CERT_DecodeCertificatePoliciesExtension
    143                (&encodedCertPolicyInfo);
    144 
    145        PORT_Free(encodedCertPolicyInfo.data);
    146 
    147        if (NULL == certPol) {
    148                PKIX_ERROR(PKIX_CERTDECODECERTIFICATEPOLICIESEXTENSIONFAILED);
    149        }
    150 
    151        /*
    152         * Check whether there are any policyInfos, so we can
    153         * avoid creating an unnecessary List
    154         */
    155        policyInfos = certPol->policyInfos;
    156        if (!policyInfos) {
    157                *pCertPolicyInfos = NULL;
    158                goto cleanup;
    159        }
    160 
    161        /* create a List of CertPolicyInfo Objects */
    162        PKIX_CHECK(PKIX_List_Create(&infos, plContext),
    163                PKIX_LISTCREATEFAILED);
    164 
    165        /*
    166         * Traverse the CERTCertificatePolicies structure,
    167         * building each PKIX_PL_CertPolicyInfo object in turn
    168         */
    169        while (*policyInfos != NULL) {
    170                CERTPolicyInfo *policyInfo = *policyInfos;
    171                CERTPolicyQualifier **policyQualifiers =
    172                                          policyInfo->policyQualifiers;
    173                if (policyQualifiers) {
    174                        /* create a PKIX_List of PKIX_PL_CertPolicyQualifiers */
    175                        PKIX_CHECK(PKIX_List_Create(&qualifiers, plContext),
    176                                PKIX_LISTCREATEFAILED);
    177 
    178                        while (*policyQualifiers != NULL) {
    179                            CERTPolicyQualifier *policyQualifier =
    180                                                         *policyQualifiers;
    181 
    182                            /* create the qualifier's OID object */
    183                            PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
    184                                (&policyQualifier->qualifierID,
    185                                 &pkixOID, plContext),
    186                                PKIX_OIDCREATEFAILED);
    187 
    188                            /* create qualifier's ByteArray object */
    189 
    190                            PKIX_CHECK(PKIX_PL_ByteArray_Create
    191                                (policyQualifier->qualifierValue.data,
    192                                policyQualifier->qualifierValue.len,
    193                                &qualifierArray,
    194                                plContext),
    195                                PKIX_BYTEARRAYCREATEFAILED);
    196 
    197                            /* create a CertPolicyQualifier object */
    198 
    199                            PKIX_CHECK(pkix_pl_CertPolicyQualifier_Create
    200                                (pkixOID,
    201                                qualifierArray,
    202                                &certPolicyQualifier,
    203                                plContext),
    204                                PKIX_CERTPOLICYQUALIFIERCREATEFAILED);
    205 
    206                            PKIX_CHECK(PKIX_List_AppendItem
    207                                (qualifiers,
    208                                (PKIX_PL_Object *)certPolicyQualifier,
    209                                plContext),
    210                                PKIX_LISTAPPENDITEMFAILED);
    211 
    212                            PKIX_DECREF(pkixOID);
    213                            PKIX_DECREF(qualifierArray);
    214                            PKIX_DECREF(certPolicyQualifier);
    215 
    216                            policyQualifiers++;
    217                        }
    218 
    219                        PKIX_CHECK(PKIX_List_SetImmutable
    220                                (qualifiers, plContext),
    221                                PKIX_LISTSETIMMUTABLEFAILED);
    222                }
    223 
    224 
    225                /*
    226                 * Create an OID object pkixOID from policyInfo->policyID.
    227                 * (The CERTPolicyInfo structure has an oid field, but it
    228                 * is of type SECOidTag. This function wants a SECItem.)
    229                 */
    230                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
    231                        (&policyInfo->policyID, &pkixOID, plContext),
    232                        PKIX_OIDCREATEFAILED);
    233 
    234                /* Create a CertPolicyInfo object */
    235                PKIX_CHECK(pkix_pl_CertPolicyInfo_Create
    236                        (pkixOID, qualifiers, &certPolicyInfo, plContext),
    237                        PKIX_CERTPOLICYINFOCREATEFAILED);
    238 
    239                /* Append the new CertPolicyInfo object to the list */
    240                PKIX_CHECK(PKIX_List_AppendItem
    241                        (infos, (PKIX_PL_Object *)certPolicyInfo, plContext),
    242                        PKIX_LISTAPPENDITEMFAILED);
    243 
    244                PKIX_DECREF(pkixOID);
    245                PKIX_DECREF(qualifiers);
    246                PKIX_DECREF(certPolicyInfo);
    247 
    248                policyInfos++;
    249        }
    250 
    251        /*
    252         * If there were no policies, we went straight to
    253         * cleanup, so we don't have to NULLCHECK infos.
    254         */
    255        PKIX_CHECK(PKIX_List_SetImmutable(infos, plContext),
    256                PKIX_LISTSETIMMUTABLEFAILED);
    257 
    258        *pCertPolicyInfos = infos;
    259        infos = NULL;
    260 
    261 cleanup:
    262        if (certPol) {
    263            PKIX_CERT_DEBUG
    264                ("\t\tCalling CERT_DestroyCertificatePoliciesExtension).\n");
    265            CERT_DestroyCertificatePoliciesExtension(certPol);
    266        }
    267 
    268        PKIX_DECREF(infos);
    269        PKIX_DECREF(pkixOID);
    270        PKIX_DECREF(qualifiers);
    271        PKIX_DECREF(certPolicyInfo);
    272        PKIX_DECREF(certPolicyQualifier);
    273        PKIX_DECREF(qualifierArray);
    274 
    275        PKIX_RETURN(CERT);
    276 }
    277 
    278 /*
    279 * FUNCTION: pkix_pl_Cert_DecodePolicyMapping
    280 * DESCRIPTION:
    281 *
    282 *  Decodes the contents of the PolicyMapping extension of the CERTCertificate
    283 *  pointed to by "nssCert", storing the resulting List of CertPolicyMaps at
    284 *  the address pointed to by "pCertPolicyMaps". If this certificate does not
    285 *  have a PolicyMapping extension, NULL will be stored. If a List is returned,
    286 *  it will be immutable.
    287 *
    288 * PARAMETERS
    289 *  "nssCert"
    290 *      Address of the Cert data whose extension is to be examined. Must be
    291 *      non-NULL.
    292 *  "pCertPolicyMaps"
    293 *      Address where the List of CertPolicyMaps will be stored. Must be
    294 *      non-NULL.
    295 *  "plContext"
    296 *      Platform-specific context pointer.
    297 * THREAD SAFETY:
    298 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    299 * RETURNS:
    300 *  Returns NULL if the function succeeds.
    301 *  Returns a Cert Error if the function fails in a non-fatal way.
    302 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    303 */
    304 static PKIX_Error *
    305 pkix_pl_Cert_DecodePolicyMapping(
    306        CERTCertificate *nssCert,
    307        PKIX_List **pCertPolicyMaps,
    308        void *plContext)
    309 {
    310        SECStatus rv;
    311        SECItem encodedCertPolicyMaps;
    312 
    313        /* Allocated in the arena; freed in CERT_Destroy... */
    314        CERTCertificatePolicyMappings *certPolMaps = NULL;
    315        CERTPolicyMap **policyMaps = NULL;
    316 
    317        /* Holder for the return value */
    318        PKIX_List *maps = NULL;
    319 
    320        PKIX_PL_OID *issuerDomainOID = NULL;
    321        PKIX_PL_OID *subjectDomainOID = NULL;
    322        PKIX_PL_CertPolicyMap *certPolicyMap = NULL;
    323 
    324        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyMapping");
    325        PKIX_NULLCHECK_TWO(nssCert, pCertPolicyMaps);
    326 
    327        /* get PolicyMappings as a SECItem */
    328        PKIX_CERT_DEBUG("\t\tCERT_FindCertExtension).\n");
    329        rv = CERT_FindCertExtension
    330                (nssCert, SEC_OID_X509_POLICY_MAPPINGS, &encodedCertPolicyMaps);
    331        if (SECSuccess != rv) {
    332                *pCertPolicyMaps = NULL;
    333                goto cleanup;
    334        }
    335 
    336        /* translate PolicyMaps to CERTCertificatePolicyMappings */
    337        certPolMaps = CERT_DecodePolicyMappingsExtension
    338                (&encodedCertPolicyMaps);
    339 
    340        PORT_Free(encodedCertPolicyMaps.data);
    341 
    342        if (!certPolMaps) {
    343                PKIX_ERROR(PKIX_CERTDECODEPOLICYMAPPINGSEXTENSIONFAILED);
    344        }
    345 
    346        PKIX_NULLCHECK_ONE(certPolMaps->policyMaps);
    347 
    348        policyMaps = certPolMaps->policyMaps;
    349 
    350        /* create a List of CertPolicyMap Objects */
    351        PKIX_CHECK(PKIX_List_Create(&maps, plContext),
    352                PKIX_LISTCREATEFAILED);
    353 
    354        /*
    355         * Traverse the CERTCertificatePolicyMappings structure,
    356         * building each CertPolicyMap object in turn
    357         */
    358        do {
    359                CERTPolicyMap *policyMap = *policyMaps;
    360 
    361                /* create the OID for the issuer Domain Policy */
    362                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
    363                        (&policyMap->issuerDomainPolicy,
    364                         &issuerDomainOID, plContext),
    365                        PKIX_OIDCREATEFAILED);
    366 
    367                /* create the OID for the subject Domain Policy */
    368                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
    369                        (&policyMap->subjectDomainPolicy,
    370                         &subjectDomainOID, plContext),
    371                        PKIX_OIDCREATEFAILED);
    372 
    373                /* create the CertPolicyMap */
    374 
    375                PKIX_CHECK(pkix_pl_CertPolicyMap_Create
    376                        (issuerDomainOID,
    377                        subjectDomainOID,
    378                        &certPolicyMap,
    379                        plContext),
    380                        PKIX_CERTPOLICYMAPCREATEFAILED);
    381 
    382                PKIX_CHECK(PKIX_List_AppendItem
    383                        (maps, (PKIX_PL_Object *)certPolicyMap, plContext),
    384                        PKIX_LISTAPPENDITEMFAILED);
    385 
    386                PKIX_DECREF(issuerDomainOID);
    387                PKIX_DECREF(subjectDomainOID);
    388                PKIX_DECREF(certPolicyMap);
    389 
    390                policyMaps++;
    391        } while (*policyMaps != NULL);
    392 
    393        PKIX_CHECK(PKIX_List_SetImmutable(maps, plContext),
    394                PKIX_LISTSETIMMUTABLEFAILED);
    395 
    396        *pCertPolicyMaps = maps;
    397        maps = NULL;
    398 
    399 cleanup:
    400        if (certPolMaps) {
    401            PKIX_CERT_DEBUG
    402                ("\t\tCalling CERT_DestroyPolicyMappingsExtension).\n");
    403            CERT_DestroyPolicyMappingsExtension(certPolMaps);
    404        }
    405 
    406        PKIX_DECREF(maps);
    407        PKIX_DECREF(issuerDomainOID);
    408        PKIX_DECREF(subjectDomainOID);
    409        PKIX_DECREF(certPolicyMap);
    410 
    411        PKIX_RETURN(CERT);
    412 }
    413 
    414 /*
    415 * FUNCTION: pkix_pl_Cert_DecodePolicyConstraints
    416 * DESCRIPTION:
    417 *
    418 *  Decodes the contents of the PolicyConstraints extension in the
    419 *  CERTCertificate pointed to by "nssCert", to obtain SkipCerts values
    420 *  which are stored at the addresses "pExplicitPolicySkipCerts" and
    421 *  "pInhibitMappingSkipCerts", respectively. If this certificate does
    422 *  not have an PolicyConstraints extension, or if either of the optional
    423 *  components is not supplied, this function stores a value of -1 for any
    424 *  missing component.
    425 *
    426 * PARAMETERS
    427 *  "nssCert"
    428 *      Address of the Cert data whose extension is to be examined. Must be
    429 *      non-NULL.
    430 *  "pExplicitPolicySkipCerts"
    431 *      Address where the SkipCert value for the requireExplicitPolicy
    432 *      component will be stored. Must be non-NULL.
    433 *  "pInhibitMappingSkipCerts"
    434 *      Address where the SkipCert value for the inhibitPolicyMapping
    435 *      component will be stored. Must be non-NULL.
    436 *  "plContext"
    437 *      Platform-specific context pointer.
    438 * THREAD SAFETY:
    439 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    440 * RETURNS:
    441 *  Returns NULL if the function succeeds.
    442 *  Returns a Cert Error if the function fails in a non-fatal way.
    443 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    444 */
    445 static PKIX_Error *
    446 pkix_pl_Cert_DecodePolicyConstraints(
    447        CERTCertificate *nssCert,
    448        PKIX_Int32 *pExplicitPolicySkipCerts,
    449        PKIX_Int32 *pInhibitMappingSkipCerts,
    450        void *plContext)
    451 {
    452        CERTCertificatePolicyConstraints policyConstraints;
    453        SECStatus rv;
    454        SECItem encodedCertPolicyConstraints;
    455        PKIX_Int32 explicitPolicySkipCerts = -1;
    456        PKIX_Int32 inhibitMappingSkipCerts = -1;
    457 
    458        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodePolicyConstraints");
    459        PKIX_NULLCHECK_THREE
    460                (nssCert, pExplicitPolicySkipCerts, pInhibitMappingSkipCerts);
    461 
    462        /* get the two skipCert values as SECItems */
    463        PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
    464        rv = CERT_FindCertExtension
    465                (nssCert,
    466                SEC_OID_X509_POLICY_CONSTRAINTS,
    467                &encodedCertPolicyConstraints);
    468 
    469        if (rv == SECSuccess) {
    470 
    471                policyConstraints.explicitPolicySkipCerts.data =
    472                        (unsigned char *)&explicitPolicySkipCerts;
    473                policyConstraints.inhibitMappingSkipCerts.data =
    474                        (unsigned char *)&inhibitMappingSkipCerts;
    475 
    476                /* translate DER to CERTCertificatePolicyConstraints */
    477                rv = CERT_DecodePolicyConstraintsExtension
    478                        (&policyConstraints, &encodedCertPolicyConstraints);
    479 
    480                PORT_Free(encodedCertPolicyConstraints.data);
    481 
    482                if (rv != SECSuccess) {
    483                    PKIX_ERROR
    484                        (PKIX_CERTDECODEPOLICYCONSTRAINTSEXTENSIONFAILED);
    485                }
    486        }
    487 
    488        *pExplicitPolicySkipCerts = explicitPolicySkipCerts;
    489        *pInhibitMappingSkipCerts = inhibitMappingSkipCerts;
    490 
    491 cleanup:
    492        PKIX_RETURN(CERT);
    493 }
    494 
    495 /*
    496 * FUNCTION: pkix_pl_Cert_DecodeInhibitAnyPolicy
    497 * DESCRIPTION:
    498 *
    499 *  Decodes the contents of the InhibitAnyPolicy extension in the
    500 *  CERTCertificate pointed to by "nssCert", to obtain a SkipCerts value,
    501 *  which is stored at the address "pSkipCerts". If this certificate does
    502 *  not have an InhibitAnyPolicy extension, -1 will be stored.
    503 *
    504 * PARAMETERS
    505 *  "nssCert"
    506 *      Address of the Cert data whose InhibitAnyPolicy extension is to be
    507 *      processed. Must be non-NULL.
    508 *  "pSkipCerts"
    509 *      Address where the SkipCert value from the InhibitAnyPolicy extension
    510 *      will be stored. Must be non-NULL.
    511 *  "plContext"
    512 *      Platform-specific context pointer.
    513 * THREAD SAFETY:
    514 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    515 * RETURNS:
    516 *  Returns NULL if the function succeeds.
    517 *  Returns a Cert Error if the function fails in a non-fatal way.
    518 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    519 */
    520 PKIX_Error *
    521 pkix_pl_Cert_DecodeInhibitAnyPolicy(
    522        CERTCertificate *nssCert,
    523        PKIX_Int32 *pSkipCerts,
    524        void *plContext)
    525 {
    526        CERTCertificateInhibitAny inhibitAny;
    527        SECStatus rv;
    528        SECItem encodedCertInhibitAny;
    529        PKIX_Int32 skipCerts = -1;
    530 
    531        PKIX_ENTER(CERT, "pkix_pl_Cert_DecodeInhibitAnyPolicy");
    532        PKIX_NULLCHECK_TWO(nssCert, pSkipCerts);
    533 
    534        /* get InhibitAny as a SECItem */
    535        PKIX_CERT_DEBUG("\t\tCalling CERT_FindCertExtension).\n");
    536        rv = CERT_FindCertExtension
    537                (nssCert, SEC_OID_X509_INHIBIT_ANY_POLICY, &encodedCertInhibitAny);
    538 
    539        if (rv == SECSuccess) {
    540                inhibitAny.inhibitAnySkipCerts.data =
    541                        (unsigned char *)&skipCerts;
    542 
    543                /* translate DER to CERTCertificateInhibitAny */
    544                rv = CERT_DecodeInhibitAnyExtension
    545                        (&inhibitAny, &encodedCertInhibitAny);
    546 
    547                PORT_Free(encodedCertInhibitAny.data);
    548 
    549                if (rv != SECSuccess) {
    550                        PKIX_ERROR(PKIX_CERTDECODEINHIBITANYEXTENSIONFAILED);
    551                }
    552        }
    553 
    554        *pSkipCerts = skipCerts;
    555 
    556 cleanup:
    557        PKIX_RETURN(CERT);
    558 }
    559 
    560 /*
    561 * FUNCTION: pkix_pl_Cert_GetNssSubjectAltNames
    562 * DESCRIPTION:
    563 *
    564 *  Retrieves the Subject Alternative Names of the certificate specified by
    565 *  "cert" and stores it at "pNssSubjAltNames". If the Subject Alternative
    566 *  Name extension is not present, NULL is returned at "pNssSubjAltNames".
    567 *  If the Subject Alternative Names has not been previously decoded, it is
    568 *  decoded here with lock on the "cert" unless the flag "hasLock" indicates
    569 *  the lock had been obtained at a higher call level.
    570 *
    571 * PARAMETERS
    572 *  "cert"
    573 *      Address of the certificate whose Subject Alternative Names extensions
    574 *      is retrieved. Must be non-NULL.
    575 *  "hasLock"
    576 *      Boolean indicates caller has acquired a lock.
    577 *      Must be non-NULL.
    578 *  "pNssSubjAltNames"
    579 *      Address where the returned Subject Alternative Names will be stored.
    580 *      Must be non-NULL.
    581 *  "plContext"
    582 *      Platform-specific context pointer.
    583 * THREAD SAFETY:
    584 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    585 * RETURNS:
    586 *  Returns NULL if the function succeeds.
    587 *  Returns a Cert Error if the function fails in a non-fatal way.
    588 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    589 */
    590 static PKIX_Error *
    591 pkix_pl_Cert_GetNssSubjectAltNames(
    592        PKIX_PL_Cert *cert,
    593        PKIX_Boolean hasLock,
    594        CERTGeneralName **pNssSubjAltNames,
    595        void *plContext)
    596 {
    597        CERTCertificate *nssCert = NULL;
    598        CERTGeneralName *nssOriginalAltName = NULL;
    599        PLArenaPool *arena = NULL;
    600        SECItem altNameExtension = {siBuffer, NULL, 0};
    601        SECStatus rv = SECFailure;
    602 
    603        PKIX_ENTER(CERT, "pkix_pl_Cert_GetNssSubjectAltNames");
    604        PKIX_NULLCHECK_THREE(cert, pNssSubjAltNames, cert->nssCert);
    605 
    606        nssCert = cert->nssCert;
    607 
    608        if ((cert->nssSubjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
    609 
    610                if (!hasLock) {
    611                    PKIX_OBJECT_LOCK(cert);
    612                }
    613 
    614                if ((cert->nssSubjAltNames == NULL) &&
    615                    (!cert->subjAltNamesAbsent)){
    616 
    617                    PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
    618                        (nssCert,
    619                        SEC_OID_X509_SUBJECT_ALT_NAME,
    620                        &altNameExtension));
    621 
    622                    if (rv != SECSuccess) {
    623                        *pNssSubjAltNames = NULL;
    624                        cert->subjAltNamesAbsent = PKIX_TRUE;
    625                        goto cleanup;
    626                    }
    627 
    628                    if (cert->arenaNameConstraints == NULL) {
    629                        PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
    630                                (DER_DEFAULT_CHUNKSIZE));
    631 
    632                        if (arena == NULL) {
    633                            PKIX_ERROR(PKIX_OUTOFMEMORY);
    634                        }
    635                        cert->arenaNameConstraints = arena;
    636                    }
    637 
    638                    PKIX_PL_NSSCALLRV
    639                        (CERT,
    640                        nssOriginalAltName,
    641                        (CERTGeneralName *) CERT_DecodeAltNameExtension,
    642                        (cert->arenaNameConstraints, &altNameExtension));
    643 
    644                    PKIX_PL_NSSCALL(CERT, PORT_Free, (altNameExtension.data));
    645 
    646                    if (nssOriginalAltName == NULL) {
    647                        PKIX_ERROR(PKIX_CERTDECODEALTNAMEEXTENSIONFAILED);
    648                    }
    649                    cert->nssSubjAltNames = nssOriginalAltName;
    650 
    651                }
    652 
    653                if (!hasLock) {
    654                    PKIX_OBJECT_UNLOCK(cert);
    655                }
    656        }
    657 
    658        *pNssSubjAltNames = cert->nssSubjAltNames;
    659 
    660 cleanup:
    661 PKIX_OBJECT_UNLOCK(lockedObject);
    662        PKIX_RETURN(CERT);
    663 }
    664 
    665 /*
    666 * FUNCTION: pkix_pl_Cert_CheckExtendKeyUsage
    667 * DESCRIPTION:
    668 *
    669 *  For each of the ON bit in "requiredExtendedKeyUsages" that represents its
    670 *  SECCertUsageEnum type, this function checks "cert"'s certType (extended
    671 *  key usage) and key usage with what is required for SECCertUsageEnum type.
    672 *
    673 * PARAMETERS
    674 *  "cert"
    675 *      Address of the certificate whose Extended Key Usage extensions
    676 *      is retrieved. Must be non-NULL.
    677 *  "requiredExtendedKeyUsages"
    678 *      An unsigned integer, its bit location is ON based on the required key
    679 *      usage value representing in SECCertUsageEnum.
    680 *  "pPass"
    681 *      Address where the return value, indicating key usage check passed, is
    682 *       stored. Must be non-NULL.
    683 *  "plContext"
    684 *      Platform-specific context pointer.
    685 * THREAD SAFETY:
    686 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    687 * RETURNS:
    688 *  Returns NULL if the function succeeds.
    689 *  Returns a Cert Error if the function fails in a non-fatal way.
    690 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    691 */
    692 PKIX_Error *
    693 pkix_pl_Cert_CheckExtendedKeyUsage(
    694        PKIX_PL_Cert *cert,
    695        PKIX_UInt32 requiredExtendedKeyUsages,
    696        PKIX_Boolean *pPass,
    697        void *plContext)
    698 {
    699        PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
    700        PKIX_UInt32 certType = 0;
    701        PKIX_UInt32 requiredKeyUsage = 0;
    702        PKIX_UInt32 requiredCertType = 0;
    703        PKIX_UInt32 requiredExtendedKeyUsage = 0;
    704        PKIX_UInt32 i;
    705        PKIX_Boolean isCA = PKIX_FALSE;
    706        SECStatus rv = SECFailure;
    707 
    708        PKIX_ENTER(CERT, "pkix_pl_Cert_CheckExtendKeyUsage");
    709        PKIX_NULLCHECK_THREE(cert, pPass, cert->nssCert);
    710 
    711        *pPass = PKIX_FALSE;
    712 
    713        PKIX_CERT_DEBUG("\t\tCalling cert_GetCertType).\n");
    714        cert_GetCertType(cert->nssCert);
    715        certType = cert->nssCert->nsCertType;
    716 
    717        PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
    718                    (cert,
    719                    &basicConstraints,
    720                    plContext),
    721                    PKIX_CERTGETBASICCONSTRAINTFAILED);
    722 
    723        if (basicConstraints != NULL) {
    724                PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag
    725                    (basicConstraints, &isCA, plContext),
    726                    PKIX_BASICCONSTRAINTSGETCAFLAGFAILED);
    727        }
    728 
    729        i = 0;
    730        while (requiredExtendedKeyUsages != 0) {
    731 
    732                /* Find the bit location of the right-most non-zero bit */
    733                while (requiredExtendedKeyUsages != 0) {
    734                        if (((1 << i) & requiredExtendedKeyUsages) != 0) {
    735                                requiredExtendedKeyUsage = 1 << i;
    736                                break;
    737                        }
    738                        i++;
    739                }
    740                requiredExtendedKeyUsages ^= requiredExtendedKeyUsage;
    741 
    742                requiredExtendedKeyUsage = i;
    743 
    744                PKIX_PL_NSSCALLRV(CERT, rv, CERT_KeyUsageAndTypeForCertUsage,
    745                        (requiredExtendedKeyUsage,
    746                        isCA,
    747                        &requiredKeyUsage,
    748                        &requiredCertType));
    749 
    750                if (!(certType & requiredCertType)) {
    751                        goto cleanup;
    752                }
    753 
    754                PKIX_PL_NSSCALLRV(CERT, rv, CERT_CheckKeyUsage,
    755                        (cert->nssCert, requiredKeyUsage));
    756                if (rv != SECSuccess) {
    757                        goto cleanup;
    758                }
    759                i++;
    760 
    761        }
    762 
    763        *pPass = PKIX_TRUE;
    764 
    765 cleanup:
    766        PKIX_DECREF(basicConstraints);
    767        PKIX_RETURN(CERT);
    768 }
    769 
    770 /*
    771 * FUNCTION: pkix_pl_Cert_ToString_Helper
    772 * DESCRIPTION:
    773 *
    774 *  Helper function that creates a string representation of the Cert pointed
    775 *  to by "cert" and stores it at "pString", where the value of
    776 *  "partialString" determines whether a full or partial representation of
    777 *  the Cert is stored.
    778 *
    779 * PARAMETERS
    780 *  "cert"
    781 *      Address of Cert whose string representation is desired.
    782 *      Must be non-NULL.
    783 *  "partialString"
    784 *      Boolean indicating whether a partial Cert representation is desired.
    785 *  "pString"
    786 *      Address where object pointer will be stored. Must be non-NULL.
    787 *  "plContext"
    788 *      Platform-specific context pointer.
    789 * THREAD SAFETY:
    790 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    791 * RETURNS:
    792 *  Returns NULL if the function succeeds.
    793 *  Returns a Cert Error if the function fails in a non-fatal way.
    794 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    795 */
    796 PKIX_Error *
    797 pkix_pl_Cert_ToString_Helper(
    798        PKIX_PL_Cert *cert,
    799        PKIX_Boolean partialString,
    800        PKIX_PL_String **pString,
    801        void *plContext)
    802 {
    803        PKIX_PL_String *certString = NULL;
    804        char *asciiFormat = NULL;
    805        PKIX_PL_String *formatString = NULL;
    806        PKIX_UInt32 certVersion;
    807        PKIX_PL_BigInt *certSN = NULL;
    808        PKIX_PL_String *certSNString = NULL;
    809        PKIX_PL_X500Name *certIssuer = NULL;
    810        PKIX_PL_String *certIssuerString = NULL;
    811        PKIX_PL_X500Name *certSubject = NULL;
    812        PKIX_PL_String *certSubjectString = NULL;
    813        PKIX_PL_String *notBeforeString = NULL;
    814        PKIX_PL_String *notAfterString = NULL;
    815        PKIX_List *subjAltNames = NULL;
    816        PKIX_PL_String *subjAltNamesString = NULL;
    817        PKIX_PL_ByteArray *authKeyId = NULL;
    818        PKIX_PL_String *authKeyIdString = NULL;
    819        PKIX_PL_ByteArray *subjKeyId = NULL;
    820        PKIX_PL_String *subjKeyIdString = NULL;
    821        PKIX_PL_PublicKey *nssPubKey = NULL;
    822        PKIX_PL_String *nssPubKeyString = NULL;
    823        PKIX_List *critExtOIDs = NULL;
    824        PKIX_PL_String *critExtOIDsString = NULL;
    825        PKIX_List *extKeyUsages = NULL;
    826        PKIX_PL_String *extKeyUsagesString = NULL;
    827        PKIX_PL_CertBasicConstraints *basicConstraint = NULL;
    828        PKIX_PL_String *certBasicConstraintsString = NULL;
    829        PKIX_List *policyInfo = NULL;
    830        PKIX_PL_String *certPolicyInfoString = NULL;
    831        PKIX_List *certPolicyMappings = NULL;
    832        PKIX_PL_String *certPolicyMappingsString = NULL;
    833        PKIX_Int32 certExplicitPolicy = 0;
    834        PKIX_Int32 certInhibitMapping = 0;
    835        PKIX_Int32 certInhibitAnyPolicy = 0;
    836        PKIX_PL_CertNameConstraints *nameConstraints = NULL;
    837        PKIX_PL_String *nameConstraintsString = NULL;
    838        PKIX_List *authorityInfoAccess = NULL;
    839        PKIX_PL_String *authorityInfoAccessString = NULL;
    840        PKIX_List *subjectInfoAccess = NULL;
    841        PKIX_PL_String *subjectInfoAccessString = NULL;
    842 
    843        PKIX_ENTER(CERT, "pkix_pl_Cert_ToString_Helper");
    844        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pString);
    845 
    846        /*
    847         * XXX Add to this format as certificate components are developed.
    848         */
    849 
    850        if (partialString){
    851                asciiFormat =
    852                        "\t[Issuer:          %s\n"
    853                        "\t Subject:         %s]";
    854        } else {
    855                asciiFormat =
    856                        "[\n"
    857                        "\tVersion:         v%d\n"
    858                        "\tSerialNumber:    %s\n"
    859                        "\tIssuer:          %s\n"
    860                        "\tSubject:         %s\n"
    861                        "\tValidity: [From: %s\n"
    862                        "\t           To:   %s]\n"
    863                        "\tSubjectAltNames: %s\n"
    864                        "\tAuthorityKeyId:  %s\n"
    865                        "\tSubjectKeyId:    %s\n"
    866                        "\tSubjPubKeyAlgId: %s\n"
    867                        "\tCritExtOIDs:     %s\n"
    868                        "\tExtKeyUsages:    %s\n"
    869                        "\tBasicConstraint: %s\n"
    870                        "\tCertPolicyInfo:  %s\n"
    871                        "\tPolicyMappings:  %s\n"
    872                        "\tExplicitPolicy:  %d\n"
    873                        "\tInhibitMapping:  %d\n"
    874                        "\tInhibitAnyPolicy:%d\n"
    875                        "\tNameConstraints: %s\n"
    876                        "\tAuthorityInfoAccess: %s\n"
    877                        "\tSubjectInfoAccess: %s\n"
    878                        "\tCacheFlag:       %d\n"
    879                        "]\n";
    880        }
    881 
    882 
    883 
    884        PKIX_CHECK(PKIX_PL_String_Create
    885                (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
    886                PKIX_STRINGCREATEFAILED);
    887 
    888        /* Issuer */
    889        PKIX_CHECK(PKIX_PL_Cert_GetIssuer
    890                (cert, &certIssuer, plContext),
    891                PKIX_CERTGETISSUERFAILED);
    892 
    893        PKIX_CHECK(PKIX_PL_Object_ToString
    894                ((PKIX_PL_Object *)certIssuer, &certIssuerString, plContext),
    895                PKIX_X500NAMETOSTRINGFAILED);
    896 
    897        /* Subject */
    898        PKIX_CHECK(PKIX_PL_Cert_GetSubject(cert, &certSubject, plContext),
    899                PKIX_CERTGETSUBJECTFAILED);
    900 
    901        PKIX_TOSTRING(certSubject, &certSubjectString, plContext,
    902                PKIX_X500NAMETOSTRINGFAILED);
    903 
    904        if (partialString){
    905                PKIX_CHECK(PKIX_PL_Sprintf
    906                            (&certString,
    907                            plContext,
    908                            formatString,
    909                            certIssuerString,
    910                            certSubjectString),
    911                            PKIX_SPRINTFFAILED);
    912 
    913                *pString = certString;
    914                goto cleanup;
    915        }
    916 
    917        /* Version */
    918        PKIX_CHECK(PKIX_PL_Cert_GetVersion(cert, &certVersion, plContext),
    919                PKIX_CERTGETVERSIONFAILED);
    920 
    921        /* SerialNumber */
    922        PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber(cert, &certSN, plContext),
    923                PKIX_CERTGETSERIALNUMBERFAILED);
    924 
    925        PKIX_CHECK(PKIX_PL_Object_ToString
    926                ((PKIX_PL_Object *)certSN, &certSNString, plContext),
    927                PKIX_BIGINTTOSTRINGFAILED);
    928 
    929        /* Validity: NotBefore */
    930        PKIX_CHECK(pkix_pl_Date_ToString_Helper
    931                (&(cert->nssCert->validity.notBefore),
    932                &notBeforeString,
    933                plContext),
    934                PKIX_DATETOSTRINGHELPERFAILED);
    935 
    936        /* Validity: NotAfter */
    937        PKIX_CHECK(pkix_pl_Date_ToString_Helper
    938                (&(cert->nssCert->validity.notAfter),
    939                &notAfterString,
    940                plContext),
    941                PKIX_DATETOSTRINGHELPERFAILED);
    942 
    943        /* SubjectAltNames */
    944        PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames
    945                (cert, &subjAltNames, plContext),
    946                PKIX_CERTGETSUBJECTALTNAMESFAILED);
    947 
    948        PKIX_TOSTRING(subjAltNames, &subjAltNamesString, plContext,
    949                PKIX_LISTTOSTRINGFAILED);
    950 
    951        /* AuthorityKeyIdentifier */
    952        PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
    953                (cert, &authKeyId, plContext),
    954                PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
    955 
    956        PKIX_TOSTRING(authKeyId, &authKeyIdString, plContext,
    957                PKIX_BYTEARRAYTOSTRINGFAILED);
    958 
    959        /* SubjectKeyIdentifier */
    960        PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier
    961                (cert, &subjKeyId, plContext),
    962                PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED);
    963 
    964        PKIX_TOSTRING(subjKeyId, &subjKeyIdString, plContext,
    965                PKIX_BYTEARRAYTOSTRINGFAILED);
    966 
    967        /* SubjectPublicKey */
    968        PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
    969                    (cert, &nssPubKey, plContext),
    970                    PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
    971 
    972        PKIX_CHECK(PKIX_PL_Object_ToString
    973                ((PKIX_PL_Object *)nssPubKey, &nssPubKeyString, plContext),
    974                PKIX_PUBLICKEYTOSTRINGFAILED);
    975 
    976        /* CriticalExtensionOIDs */
    977        PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
    978                (cert, &critExtOIDs, plContext),
    979                PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
    980 
    981        PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
    982                PKIX_LISTTOSTRINGFAILED);
    983 
    984        /* ExtendedKeyUsages */
    985        PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage
    986                (cert, &extKeyUsages, plContext),
    987                PKIX_CERTGETEXTENDEDKEYUSAGEFAILED);
    988 
    989        PKIX_TOSTRING(extKeyUsages, &extKeyUsagesString, plContext,
    990                PKIX_LISTTOSTRINGFAILED);
    991 
    992        /* CertBasicConstraints */
    993        PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints
    994                (cert, &basicConstraint, plContext),
    995                PKIX_CERTGETBASICCONSTRAINTSFAILED);
    996 
    997        PKIX_TOSTRING(basicConstraint, &certBasicConstraintsString, plContext,
    998                PKIX_CERTBASICCONSTRAINTSTOSTRINGFAILED);
    999 
   1000        /* CertPolicyInfo */
   1001        PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
   1002                (cert, &policyInfo, plContext),
   1003                PKIX_CERTGETPOLICYINFORMATIONFAILED);
   1004 
   1005        PKIX_TOSTRING(policyInfo, &certPolicyInfoString, plContext,
   1006                PKIX_LISTTOSTRINGFAILED);
   1007 
   1008        /* Advanced Policies */
   1009        PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
   1010                (cert, &certPolicyMappings, plContext),
   1011                PKIX_CERTGETPOLICYMAPPINGSFAILED);
   1012 
   1013        PKIX_TOSTRING(certPolicyMappings, &certPolicyMappingsString, plContext,
   1014                PKIX_LISTTOSTRINGFAILED);
   1015 
   1016        PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
   1017                (cert, &certExplicitPolicy, plContext),
   1018                PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
   1019 
   1020        PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
   1021                (cert, &certInhibitMapping, plContext),
   1022                PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
   1023 
   1024        PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
   1025                (cert, &certInhibitAnyPolicy, plContext),
   1026                PKIX_CERTGETINHIBITANYPOLICYFAILED);
   1027 
   1028        /* Name Constraints */
   1029        PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
   1030                (cert, &nameConstraints, plContext),
   1031                PKIX_CERTGETNAMECONSTRAINTSFAILED);
   1032 
   1033        PKIX_TOSTRING(nameConstraints, &nameConstraintsString, plContext,
   1034                PKIX_LISTTOSTRINGFAILED);
   1035 
   1036        /* Authority Information Access */
   1037        PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess
   1038                (cert, &authorityInfoAccess, plContext),
   1039                PKIX_CERTGETAUTHORITYINFOACCESSFAILED);
   1040 
   1041        PKIX_TOSTRING(authorityInfoAccess, &authorityInfoAccessString, plContext,
   1042                PKIX_LISTTOSTRINGFAILED);
   1043 
   1044        /* Subject Information Access */
   1045        PKIX_CHECK(PKIX_PL_Cert_GetSubjectInfoAccess
   1046                (cert, &subjectInfoAccess, plContext),
   1047                PKIX_CERTGETSUBJECTINFOACCESSFAILED);
   1048 
   1049        PKIX_TOSTRING(subjectInfoAccess, &subjectInfoAccessString, plContext,
   1050                PKIX_LISTTOSTRINGFAILED);
   1051 
   1052        PKIX_CHECK(PKIX_PL_Sprintf
   1053                    (&certString,
   1054                    plContext,
   1055                    formatString,
   1056                    certVersion + 1,
   1057                    certSNString,
   1058                    certIssuerString,
   1059                    certSubjectString,
   1060                    notBeforeString,
   1061                    notAfterString,
   1062                    subjAltNamesString,
   1063                    authKeyIdString,
   1064                    subjKeyIdString,
   1065                    nssPubKeyString,
   1066                    critExtOIDsString,
   1067                    extKeyUsagesString,
   1068                    certBasicConstraintsString,
   1069                    certPolicyInfoString,
   1070                    certPolicyMappingsString,
   1071                    certExplicitPolicy,         /* an Int32, not a String */
   1072                    certInhibitMapping,         /* an Int32, not a String */
   1073                    certInhibitAnyPolicy,       /* an Int32, not a String */
   1074                    nameConstraintsString,
   1075                    authorityInfoAccessString,
   1076                    subjectInfoAccessString,
   1077                    cert->cacheFlag),           /* a boolean */
   1078                    PKIX_SPRINTFFAILED);
   1079 
   1080        *pString = certString;
   1081 
   1082 cleanup:
   1083        PKIX_DECREF(certSN);
   1084        PKIX_DECREF(certSNString);
   1085        PKIX_DECREF(certIssuer);
   1086        PKIX_DECREF(certIssuerString);
   1087        PKIX_DECREF(certSubject);
   1088        PKIX_DECREF(certSubjectString);
   1089        PKIX_DECREF(notBeforeString);
   1090        PKIX_DECREF(notAfterString);
   1091        PKIX_DECREF(subjAltNames);
   1092        PKIX_DECREF(subjAltNamesString);
   1093        PKIX_DECREF(authKeyId);
   1094        PKIX_DECREF(authKeyIdString);
   1095        PKIX_DECREF(subjKeyId);
   1096        PKIX_DECREF(subjKeyIdString);
   1097        PKIX_DECREF(nssPubKey);
   1098        PKIX_DECREF(nssPubKeyString);
   1099        PKIX_DECREF(critExtOIDs);
   1100        PKIX_DECREF(critExtOIDsString);
   1101        PKIX_DECREF(extKeyUsages);
   1102        PKIX_DECREF(extKeyUsagesString);
   1103        PKIX_DECREF(basicConstraint);
   1104        PKIX_DECREF(certBasicConstraintsString);
   1105        PKIX_DECREF(policyInfo);
   1106        PKIX_DECREF(certPolicyInfoString);
   1107        PKIX_DECREF(certPolicyMappings);
   1108        PKIX_DECREF(certPolicyMappingsString);
   1109        PKIX_DECREF(nameConstraints);
   1110        PKIX_DECREF(nameConstraintsString);
   1111        PKIX_DECREF(authorityInfoAccess);
   1112        PKIX_DECREF(authorityInfoAccessString);
   1113        PKIX_DECREF(subjectInfoAccess);
   1114        PKIX_DECREF(subjectInfoAccessString);
   1115        PKIX_DECREF(formatString);
   1116 
   1117        PKIX_RETURN(CERT);
   1118 }
   1119 
   1120 /*
   1121 * FUNCTION: pkix_pl_Cert_Destroy
   1122 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
   1123 */
   1124 static PKIX_Error *
   1125 pkix_pl_Cert_Destroy(
   1126        PKIX_PL_Object *object,
   1127        void *plContext)
   1128 {
   1129        PKIX_PL_Cert *cert = NULL;
   1130 
   1131        PKIX_ENTER(CERT, "pkix_pl_Cert_Destroy");
   1132        PKIX_NULLCHECK_ONE(object);
   1133 
   1134        PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
   1135                    PKIX_OBJECTNOTCERT);
   1136 
   1137        cert = (PKIX_PL_Cert*)object;
   1138 
   1139        PKIX_DECREF(cert->subject);
   1140        PKIX_DECREF(cert->issuer);
   1141        PKIX_DECREF(cert->subjAltNames);
   1142        PKIX_DECREF(cert->publicKeyAlgId);
   1143        PKIX_DECREF(cert->publicKey);
   1144        PKIX_DECREF(cert->serialNumber);
   1145        PKIX_DECREF(cert->critExtOids);
   1146        PKIX_DECREF(cert->authKeyId);
   1147        PKIX_DECREF(cert->subjKeyId);
   1148        PKIX_DECREF(cert->extKeyUsages);
   1149        PKIX_DECREF(cert->certBasicConstraints);
   1150        PKIX_DECREF(cert->certPolicyInfos);
   1151        PKIX_DECREF(cert->certPolicyMappings);
   1152        PKIX_DECREF(cert->nameConstraints);
   1153        PKIX_DECREF(cert->store);
   1154        PKIX_DECREF(cert->authorityInfoAccess);
   1155        PKIX_DECREF(cert->subjectInfoAccess);
   1156        PKIX_DECREF(cert->crldpList);
   1157 
   1158        if (cert->arenaNameConstraints){
   1159                /* This arena was allocated for SubjectAltNames */
   1160                PKIX_PL_NSSCALL(CERT, PORT_FreeArena,
   1161                        (cert->arenaNameConstraints, PR_FALSE));
   1162 
   1163                cert->arenaNameConstraints = NULL;
   1164                cert->nssSubjAltNames = NULL;
   1165        }
   1166 
   1167        CERT_DestroyCertificate(cert->nssCert);
   1168        cert->nssCert = NULL;
   1169 
   1170 cleanup:
   1171        PKIX_RETURN(CERT);
   1172 }
   1173 
   1174 /*
   1175 * FUNCTION: pkix_pl_Cert_ToString
   1176 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
   1177 */
   1178 static PKIX_Error *
   1179 pkix_pl_Cert_ToString(
   1180        PKIX_PL_Object *object,
   1181        PKIX_PL_String **pString,
   1182        void *plContext)
   1183 {
   1184        PKIX_PL_String *certString = NULL;
   1185        PKIX_PL_Cert *pkixCert = NULL;
   1186 
   1187        PKIX_ENTER(CERT, "pkix_pl_Cert_toString");
   1188        PKIX_NULLCHECK_TWO(object, pString);
   1189 
   1190        PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
   1191                    PKIX_OBJECTNOTCERT);
   1192 
   1193        pkixCert = (PKIX_PL_Cert *)object;
   1194 
   1195        PKIX_CHECK(pkix_pl_Cert_ToString_Helper
   1196                    (pkixCert, PKIX_FALSE, &certString, plContext),
   1197                    PKIX_CERTTOSTRINGHELPERFAILED);
   1198 
   1199        *pString = certString;
   1200 
   1201 cleanup:
   1202        PKIX_RETURN(CERT);
   1203 }
   1204 
   1205 /*
   1206 * FUNCTION: pkix_pl_Cert_Hashcode
   1207 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
   1208 */
   1209 static PKIX_Error *
   1210 pkix_pl_Cert_Hashcode(
   1211        PKIX_PL_Object *object,
   1212        PKIX_UInt32 *pHashcode,
   1213        void *plContext)
   1214 {
   1215        PKIX_PL_Cert *pkixCert = NULL;
   1216        CERTCertificate *nssCert = NULL;
   1217        unsigned char *derBytes = NULL;
   1218        PKIX_UInt32 derLength;
   1219        PKIX_UInt32 certHash;
   1220 
   1221        PKIX_ENTER(CERT, "pkix_pl_Cert_Hashcode");
   1222        PKIX_NULLCHECK_TWO(object, pHashcode);
   1223 
   1224        PKIX_CHECK(pkix_CheckType(object, PKIX_CERT_TYPE, plContext),
   1225                    PKIX_OBJECTNOTCERT);
   1226 
   1227        pkixCert = (PKIX_PL_Cert *)object;
   1228 
   1229        nssCert = pkixCert->nssCert;
   1230        derBytes = (nssCert->derCert).data;
   1231        derLength = (nssCert->derCert).len;
   1232 
   1233        PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
   1234                    PKIX_HASHFAILED);
   1235 
   1236        *pHashcode = certHash;
   1237 
   1238 cleanup:
   1239        PKIX_RETURN(CERT);
   1240 }
   1241 
   1242 
   1243 /*
   1244 * FUNCTION: pkix_pl_Cert_Equals
   1245 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
   1246 */
   1247 static PKIX_Error *
   1248 pkix_pl_Cert_Equals(
   1249        PKIX_PL_Object *firstObject,
   1250        PKIX_PL_Object *secondObject,
   1251        PKIX_Boolean *pResult,
   1252        void *plContext)
   1253 {
   1254        CERTCertificate *firstCert = NULL;
   1255        CERTCertificate *secondCert = NULL;
   1256        PKIX_UInt32 secondType;
   1257        PKIX_Boolean cmpResult;
   1258 
   1259        PKIX_ENTER(CERT, "pkix_pl_Cert_Equals");
   1260        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
   1261 
   1262        /* test that firstObject is a Cert */
   1263        PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CERT_TYPE, plContext),
   1264                    PKIX_FIRSTOBJECTNOTCERT);
   1265 
   1266        /*
   1267         * Since we know firstObject is a Cert, if both references are
   1268         * identical, they must be equal
   1269         */
   1270        if (firstObject == secondObject){
   1271                *pResult = PKIX_TRUE;
   1272                goto cleanup;
   1273        }
   1274 
   1275        /*
   1276         * If secondObject isn't a Cert, we don't throw an error.
   1277         * We simply return a Boolean result of FALSE
   1278         */
   1279        *pResult = PKIX_FALSE;
   1280        PKIX_CHECK(PKIX_PL_Object_GetType
   1281                    (secondObject, &secondType, plContext),
   1282                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
   1283        if (secondType != PKIX_CERT_TYPE) goto cleanup;
   1284 
   1285        firstCert = ((PKIX_PL_Cert *)firstObject)->nssCert;
   1286        secondCert = ((PKIX_PL_Cert *)secondObject)->nssCert;
   1287 
   1288        PKIX_NULLCHECK_TWO(firstCert, secondCert);
   1289 
   1290        /* CERT_CompareCerts does byte comparison on DER encodings of certs */
   1291        PKIX_CERT_DEBUG("\t\tCalling CERT_CompareCerts).\n");
   1292        cmpResult = CERT_CompareCerts(firstCert, secondCert);
   1293 
   1294        *pResult = cmpResult;
   1295 
   1296 cleanup:
   1297        PKIX_RETURN(CERT);
   1298 }
   1299 
   1300 /*
   1301 * FUNCTION: pkix_pl_Cert_RegisterSelf
   1302 * DESCRIPTION:
   1303 *  Registers PKIX_CERT_TYPE and its related functions with systemClasses[]
   1304 * THREAD SAFETY:
   1305 *  Not Thread Safe - for performance and complexity reasons
   1306 *
   1307 *  Since this function is only called by PKIX_PL_Initialize, which should
   1308 *  only be called once, it is acceptable that this function is not
   1309 *  thread-safe.
   1310 */
   1311 PKIX_Error *
   1312 pkix_pl_Cert_RegisterSelf(void *plContext)
   1313 {
   1314 
   1315        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   1316        pkix_ClassTable_Entry entry;
   1317 
   1318        PKIX_ENTER(CERT, "pkix_pl_Cert_RegisterSelf");
   1319 
   1320        entry.description = "Cert";
   1321        entry.objCounter = 0;
   1322        entry.typeObjectSize = sizeof(PKIX_PL_Cert);
   1323        entry.destructor = pkix_pl_Cert_Destroy;
   1324        entry.equalsFunction = pkix_pl_Cert_Equals;
   1325        entry.hashcodeFunction = pkix_pl_Cert_Hashcode;
   1326        entry.toStringFunction = pkix_pl_Cert_ToString;
   1327        entry.comparator = NULL;
   1328        entry.duplicateFunction = pkix_duplicateImmutable;
   1329 
   1330        systemClasses[PKIX_CERT_TYPE] = entry;
   1331 
   1332        PKIX_RETURN(CERT);
   1333 }
   1334 
   1335 /*
   1336 * FUNCTION: pkix_pl_Cert_CreateWithNSSCert
   1337 * DESCRIPTION:
   1338 *
   1339 *  Creates a new certificate using the CERTCertificate pointed to by "nssCert"
   1340 *  and stores it at "pCert". Once created, a Cert is immutable.
   1341 *
   1342 *  This function is primarily used as a convenience function for the
   1343 *  performance tests that have easy access to a CERTCertificate.
   1344 *
   1345 * PARAMETERS:
   1346 *  "nssCert"
   1347 *      Address of CERTCertificate representing the NSS certificate.
   1348 *      Must be non-NULL.
   1349 *  "pCert"
   1350 *      Address where object pointer will be stored. Must be non-NULL.
   1351 *  "plContext"
   1352 *      Platform-specific context pointer.
   1353 * THREAD SAFETY:
   1354 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1355 * RETURNS:
   1356 *  Returns NULL if the function succeeds.
   1357 *  Returns a Cert Error if the function fails in a non-fatal way.
   1358 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1359 */
   1360 PKIX_Error *
   1361 pkix_pl_Cert_CreateWithNSSCert(
   1362        CERTCertificate *nssCert,
   1363        PKIX_PL_Cert **pCert,
   1364        void *plContext)
   1365 {
   1366        PKIX_PL_Cert *cert = NULL;
   1367 
   1368        PKIX_ENTER(CERT, "pkix_pl_Cert_CreateWithNSSCert");
   1369        PKIX_NULLCHECK_TWO(pCert, nssCert);
   1370 
   1371        /* create a PKIX_PL_Cert object */
   1372        PKIX_CHECK(PKIX_PL_Object_Alloc
   1373                    (PKIX_CERT_TYPE,
   1374                    sizeof (PKIX_PL_Cert),
   1375                    (PKIX_PL_Object **)&cert,
   1376                    plContext),
   1377                    PKIX_COULDNOTCREATEOBJECT);
   1378 
   1379        /* populate the nssCert field */
   1380        cert->nssCert = nssCert;
   1381 
   1382        /* initialize remaining fields */
   1383        /*
   1384         * Fields ending with Absent are initialized to PKIX_FALSE so that the
   1385         * first time we need the value we will look for it. If we find it is
   1386         * actually absent, the flag will at that time be set to PKIX_TRUE to
   1387         * prevent searching for it later.
   1388         * Fields ending with Processed are those where a value is defined
   1389         * for the Absent case, and a value of zero is possible. When the
   1390         * flag is still true we have to look for the field, set the default
   1391         * value if necessary, and set the Processed flag to PKIX_TRUE.
   1392         */
   1393        cert->subject = NULL;
   1394        cert->issuer = NULL;
   1395        cert->subjAltNames = NULL;
   1396        cert->subjAltNamesAbsent = PKIX_FALSE;
   1397        cert->publicKeyAlgId = NULL;
   1398        cert->publicKey = NULL;
   1399        cert->serialNumber = NULL;
   1400        cert->critExtOids = NULL;
   1401        cert->subjKeyId = NULL;
   1402        cert->subjKeyIdAbsent = PKIX_FALSE;
   1403        cert->authKeyId = NULL;
   1404        cert->authKeyIdAbsent = PKIX_FALSE;
   1405        cert->extKeyUsages = NULL;
   1406        cert->extKeyUsagesAbsent = PKIX_FALSE;
   1407        cert->certBasicConstraints = NULL;
   1408        cert->basicConstraintsAbsent = PKIX_FALSE;
   1409        cert->certPolicyInfos = NULL;
   1410        cert->policyInfoAbsent = PKIX_FALSE;
   1411        cert->policyMappingsAbsent = PKIX_FALSE;
   1412        cert->certPolicyMappings = NULL;
   1413        cert->policyConstraintsProcessed = PKIX_FALSE;
   1414        cert->policyConstraintsExplicitPolicySkipCerts = 0;
   1415        cert->policyConstraintsInhibitMappingSkipCerts = 0;
   1416        cert->inhibitAnyPolicyProcessed = PKIX_FALSE;
   1417        cert->inhibitAnySkipCerts = 0;
   1418        cert->nameConstraints = NULL;
   1419        cert->nameConstraintsAbsent = PKIX_FALSE;
   1420        cert->arenaNameConstraints = NULL;
   1421        cert->nssSubjAltNames = NULL;
   1422        cert->cacheFlag = PKIX_FALSE;
   1423        cert->store = NULL;
   1424        cert->authorityInfoAccess = NULL;
   1425        cert->subjectInfoAccess = NULL;
   1426        cert->isUserTrustAnchor = PKIX_FALSE;
   1427        cert->crldpList = NULL;
   1428 
   1429        *pCert = cert;
   1430 
   1431 cleanup:
   1432        PKIX_RETURN(CERT);
   1433 }
   1434 
   1435 /*
   1436 * FUNCTION: pkix_pl_Cert_CreateToList
   1437 * DESCRIPTION:
   1438 *
   1439 *  Creates a new certificate using the DER-encoding pointed to by "derCertItem"
   1440 *  and appends it to the list pointed to by "certList". If Cert creation fails,
   1441 *  the function returns with certList unchanged, but any decoding Error is
   1442 *  discarded.
   1443 *
   1444 * PARAMETERS:
   1445 *  "derCertItem"
   1446 *      Address of SECItem containing the DER representation of a certificate.
   1447 *      Must be non-NULL.
   1448 *  "certList"
   1449 *      Address of List to which the Cert will be appended, if successfully
   1450 *      created. May be empty, but must be non-NULL.
   1451 *  "plContext"
   1452 *      Platform-specific context pointer.
   1453 * THREAD SAFETY:
   1454 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1455 * RETURNS:
   1456 *  Returns NULL if the function succeeds.
   1457 *  Returns a Cert Error if the function fails in a non-fatal way.
   1458 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1459 */
   1460 PKIX_Error *
   1461 pkix_pl_Cert_CreateToList(
   1462        SECItem *derCertItem,
   1463        PKIX_List *certList,
   1464        void *plContext)
   1465 {
   1466        CERTCertificate *nssCert = NULL;
   1467        PKIX_PL_Cert *cert = NULL;
   1468        CERTCertDBHandle *handle;
   1469 
   1470        PKIX_ENTER(CERT, "pkix_pl_Cert_CreateToList");
   1471        PKIX_NULLCHECK_TWO(derCertItem, certList);
   1472 
   1473        handle  = CERT_GetDefaultCertDB();
   1474        nssCert = CERT_NewTempCertificate(handle, derCertItem,
   1475 				  /* nickname */ NULL, 
   1476 				  /* isPerm   */ PR_FALSE, 
   1477 				  /* copyDer  */ PR_TRUE);
   1478        if (!nssCert) {
   1479            goto cleanup;
   1480        }
   1481 
   1482        PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
   1483                   (nssCert, &cert, plContext),
   1484                   PKIX_CERTCREATEWITHNSSCERTFAILED);
   1485 
   1486        nssCert = NULL;
   1487 
   1488        PKIX_CHECK(PKIX_List_AppendItem
   1489                   (certList, (PKIX_PL_Object *) cert, plContext),
   1490                   PKIX_LISTAPPENDITEMFAILED);
   1491 
   1492 cleanup:
   1493        if (nssCert) {
   1494            CERT_DestroyCertificate(nssCert);
   1495        }
   1496 
   1497        PKIX_DECREF(cert);
   1498        PKIX_RETURN(CERT);
   1499 }
   1500 
   1501 /* --Public-Functions------------------------------------------------------- */
   1502 
   1503 /*
   1504 * FUNCTION: PKIX_PL_Cert_Create (see comments in pkix_pl_pki.h)
   1505 * XXX We may want to cache the cert after parsing it, so it can be reused
   1506 * XXX Are the NSS/NSPR functions thread safe
   1507 */
   1508 PKIX_Error *
   1509 PKIX_PL_Cert_Create(
   1510        PKIX_PL_ByteArray *byteArray,
   1511        PKIX_PL_Cert **pCert,
   1512        void *plContext)
   1513 {
   1514        CERTCertificate *nssCert = NULL;
   1515        SECItem *derCertItem = NULL;
   1516        void *derBytes = NULL;
   1517        PKIX_UInt32 derLength;
   1518        PKIX_PL_Cert *cert = NULL;
   1519        CERTCertDBHandle *handle;
   1520 
   1521        PKIX_ENTER(CERT, "PKIX_PL_Cert_Create");
   1522        PKIX_NULLCHECK_TWO(pCert, byteArray);
   1523 
   1524        PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
   1525                    (byteArray, &derBytes, plContext),
   1526                    PKIX_BYTEARRAYGETPOINTERFAILED);
   1527 
   1528        PKIX_CHECK(PKIX_PL_ByteArray_GetLength
   1529                    (byteArray, &derLength, plContext),
   1530                    PKIX_BYTEARRAYGETLENGTHFAILED);
   1531 
   1532        derCertItem = SECITEM_AllocItem(NULL, NULL, derLength);
   1533        if (derCertItem == NULL){
   1534                PKIX_ERROR(PKIX_OUTOFMEMORY);
   1535        }
   1536 
   1537        (void) PORT_Memcpy(derCertItem->data, derBytes, derLength);
   1538 
   1539        /*
   1540         * setting copyDER to true forces NSS to make its own copy of the DER,
   1541         * allowing us to free our copy without worrying about whether NSS
   1542         * is still using it
   1543         */
   1544        handle  = CERT_GetDefaultCertDB();
   1545        nssCert = CERT_NewTempCertificate(handle, derCertItem,
   1546 				  /* nickname */ NULL, 
   1547 				  /* isPerm   */ PR_FALSE, 
   1548 				  /* copyDer  */ PR_TRUE);
   1549        if (!nssCert){
   1550                PKIX_ERROR(PKIX_CERTDECODEDERCERTIFICATEFAILED);
   1551        }
   1552 
   1553        PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
   1554                (nssCert, &cert, plContext),
   1555                PKIX_CERTCREATEWITHNSSCERTFAILED);
   1556 
   1557        *pCert = cert;
   1558 
   1559 cleanup:
   1560        if (derCertItem){
   1561                SECITEM_FreeItem(derCertItem, PKIX_TRUE);
   1562        }
   1563 
   1564        if (nssCert && PKIX_ERROR_RECEIVED){
   1565                PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
   1566                CERT_DestroyCertificate(nssCert);
   1567                nssCert = NULL;
   1568        }
   1569 
   1570        PKIX_FREE(derBytes);
   1571        PKIX_RETURN(CERT);
   1572 }
   1573 
   1574 
   1575 /*
   1576 * FUNCTION: PKIX_PL_Cert_CreateFromCERTCertificate
   1577 *  (see comments in pkix_pl_pki.h)
   1578 */
   1579 PKIX_Error *
   1580 PKIX_PL_Cert_CreateFromCERTCertificate(
   1581        const CERTCertificate *nssCert,
   1582        PKIX_PL_Cert **pCert,
   1583        void *plContext)
   1584 {
   1585        void *buf = NULL;
   1586        PKIX_UInt32 len;
   1587        PKIX_PL_ByteArray *byteArray = NULL;
   1588 
   1589        PKIX_ENTER(CERT, "PKIX_PL_Cert_CreateWithNssCert");
   1590        PKIX_NULLCHECK_TWO(pCert, nssCert);
   1591 
   1592        buf = (void*)nssCert->derCert.data;
   1593        len = nssCert->derCert.len;
   1594 
   1595        PKIX_CHECK(
   1596            PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext),
   1597            PKIX_BYTEARRAYCREATEFAILED);
   1598 
   1599        PKIX_CHECK(
   1600            PKIX_PL_Cert_Create(byteArray, pCert, plContext),
   1601            PKIX_CERTCREATEWITHNSSCERTFAILED);
   1602 
   1603 #ifdef PKIX_UNDEF
   1604        /* will be tested and used as a patch for bug 391612 */
   1605        nssCert = CERT_DupCertificate(nssInCert);
   1606 
   1607        PKIX_CHECK(pkix_pl_Cert_CreateWithNSSCert
   1608                (nssCert, &cert, plContext),
   1609                PKIX_CERTCREATEWITHNSSCERTFAILED);
   1610 #endif /* PKIX_UNDEF */
   1611 
   1612 cleanup:
   1613 
   1614 #ifdef PKIX_UNDEF
   1615        if (nssCert && PKIX_ERROR_RECEIVED){
   1616                PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyCertificate).\n");
   1617                CERT_DestroyCertificate(nssCert);
   1618                nssCert = NULL;
   1619        }
   1620 #endif /* PKIX_UNDEF */
   1621 
   1622        PKIX_DECREF(byteArray);
   1623        PKIX_RETURN(CERT);
   1624 }
   1625 
   1626 
   1627 /*
   1628 * FUNCTION: PKIX_PL_Cert_GetVersion (see comments in pkix_pl_pki.h)
   1629 */
   1630 PKIX_Error *
   1631 PKIX_PL_Cert_GetVersion(
   1632        PKIX_PL_Cert *cert,
   1633        PKIX_UInt32 *pVersion,
   1634        void *plContext)
   1635 {
   1636        CERTCertificate *nssCert = NULL;
   1637        PKIX_UInt32 myVersion = 0;  /* v1 */
   1638 
   1639        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetVersion");
   1640        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pVersion);
   1641 
   1642        nssCert = cert->nssCert;
   1643        if (nssCert->version.len != 0) {
   1644                myVersion = *(nssCert->version.data);
   1645        }
   1646 
   1647        if (myVersion > 2){
   1648                PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1V2ORV3);
   1649        }
   1650 
   1651        *pVersion = myVersion;
   1652 
   1653 cleanup:
   1654        PKIX_RETURN(CERT);
   1655 }
   1656 
   1657 /*
   1658 * FUNCTION: PKIX_PL_Cert_GetSerialNumber (see comments in pkix_pl_pki.h)
   1659 */
   1660 PKIX_Error *
   1661 PKIX_PL_Cert_GetSerialNumber(
   1662        PKIX_PL_Cert *cert,
   1663        PKIX_PL_BigInt **pSerialNumber,
   1664        void *plContext)
   1665 {
   1666        CERTCertificate *nssCert = NULL;
   1667        SECItem serialNumItem;
   1668        PKIX_PL_BigInt *serialNumber = NULL;
   1669        char *bytes = NULL;
   1670        PKIX_UInt32 length;
   1671 
   1672        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSerialNumber");
   1673        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSerialNumber);
   1674 
   1675        if (cert->serialNumber == NULL){
   1676 
   1677                PKIX_OBJECT_LOCK(cert);
   1678 
   1679                if (cert->serialNumber == NULL){
   1680 
   1681                        nssCert = cert->nssCert;
   1682                        serialNumItem = nssCert->serialNumber;
   1683 
   1684                        length = serialNumItem.len;
   1685                        bytes = (char *)serialNumItem.data;
   1686 
   1687                        PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
   1688                                    (bytes, length, &serialNumber, plContext),
   1689                                    PKIX_BIGINTCREATEWITHBYTESFAILED);
   1690 
   1691                        /* save a cached copy in case it is asked for again */
   1692                        cert->serialNumber = serialNumber;
   1693                }
   1694 
   1695                PKIX_OBJECT_UNLOCK(cert);
   1696        }
   1697 
   1698        PKIX_INCREF(cert->serialNumber);
   1699        *pSerialNumber = cert->serialNumber;
   1700 
   1701 cleanup:
   1702 PKIX_OBJECT_UNLOCK(lockedObject);
   1703        PKIX_RETURN(CERT);
   1704 }
   1705 
   1706 /*
   1707 * FUNCTION: PKIX_PL_Cert_GetSubject (see comments in pkix_pl_pki.h)
   1708 */
   1709 PKIX_Error *
   1710 PKIX_PL_Cert_GetSubject(
   1711        PKIX_PL_Cert *cert,
   1712        PKIX_PL_X500Name **pCertSubject,
   1713        void *plContext)
   1714 {
   1715        PKIX_PL_X500Name *pkixSubject = NULL;
   1716        CERTName *subjName = NULL;
   1717        SECItem  *derSubjName = NULL;
   1718 
   1719        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubject");
   1720        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertSubject);
   1721 
   1722        /* if we don't have a cached copy from before, we create one */
   1723        if (cert->subject == NULL){
   1724 
   1725                PKIX_OBJECT_LOCK(cert);
   1726 
   1727                if (cert->subject == NULL){
   1728 
   1729                        subjName = &cert->nssCert->subject;
   1730                        derSubjName = &cert->nssCert->derSubject;
   1731 
   1732                        /* if there is no subject name */
   1733                        if (derSubjName->data == NULL) {
   1734 
   1735                                pkixSubject = NULL;
   1736 
   1737                        } else {
   1738                                PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
   1739                                    (derSubjName, subjName, &pkixSubject,
   1740                                     plContext),
   1741                                    PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
   1742 
   1743                        }
   1744                        /* save a cached copy in case it is asked for again */
   1745                        cert->subject = pkixSubject;
   1746                }
   1747 
   1748                PKIX_OBJECT_UNLOCK(cert);
   1749        }
   1750 
   1751        PKIX_INCREF(cert->subject);
   1752        *pCertSubject = cert->subject;
   1753 
   1754 cleanup:
   1755 PKIX_OBJECT_UNLOCK(lockedObject);
   1756        PKIX_RETURN(CERT);
   1757 }
   1758 
   1759 /*
   1760 * FUNCTION: PKIX_PL_Cert_GetIssuer (see comments in pkix_pl_pki.h)
   1761 */
   1762 PKIX_Error *
   1763 PKIX_PL_Cert_GetIssuer(
   1764        PKIX_PL_Cert *cert,
   1765        PKIX_PL_X500Name **pCertIssuer,
   1766        void *plContext)
   1767 {
   1768        PKIX_PL_X500Name *pkixIssuer = NULL;
   1769        SECItem  *derIssuerName = NULL;
   1770        CERTName *issuerName = NULL;
   1771 
   1772        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetIssuer");
   1773        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pCertIssuer);
   1774 
   1775        /* if we don't have a cached copy from before, we create one */
   1776        if (cert->issuer == NULL){
   1777 
   1778                PKIX_OBJECT_LOCK(cert);
   1779 
   1780                if (cert->issuer == NULL){
   1781 
   1782                        issuerName = &cert->nssCert->issuer;
   1783                        derIssuerName = &cert->nssCert->derIssuer;
   1784 
   1785                        /* if there is no subject name */
   1786                        PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName
   1787                                    (derIssuerName, issuerName,
   1788                                     &pkixIssuer, plContext),
   1789                                    PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
   1790 
   1791                        /* save a cached copy in case it is asked for again */
   1792                        cert->issuer = pkixIssuer;
   1793                }
   1794 
   1795                PKIX_OBJECT_UNLOCK(cert);
   1796        }
   1797 
   1798        PKIX_INCREF(cert->issuer);
   1799        *pCertIssuer = cert->issuer;
   1800 
   1801 cleanup:
   1802        PKIX_RETURN(CERT);
   1803 }
   1804 
   1805 /*
   1806 * FUNCTION: PKIX_PL_Cert_GetSubjectAltNames (see comments in pkix_pl_pki.h)
   1807 */
   1808 PKIX_Error *
   1809 PKIX_PL_Cert_GetSubjectAltNames(
   1810        PKIX_PL_Cert *cert,
   1811        PKIX_List **pSubjectAltNames,  /* list of PKIX_PL_GeneralName */
   1812        void *plContext)
   1813 {
   1814        PKIX_PL_GeneralName *pkixAltName = NULL;
   1815        PKIX_List *altNamesList = NULL;
   1816 
   1817        CERTGeneralName *nssOriginalAltName = NULL;
   1818        CERTGeneralName *nssTempAltName = NULL;
   1819 
   1820        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectAltNames");
   1821        PKIX_NULLCHECK_TWO(cert, pSubjectAltNames);
   1822 
   1823        /* if we don't have a cached copy from before, we create one */
   1824        if ((cert->subjAltNames == NULL) && (!cert->subjAltNamesAbsent)){
   1825 
   1826                PKIX_OBJECT_LOCK(cert);
   1827 
   1828                if ((cert->subjAltNames == NULL) &&
   1829                    (!cert->subjAltNamesAbsent)){
   1830 
   1831                        PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
   1832                                (cert,
   1833                                PKIX_TRUE,
   1834                                &nssOriginalAltName,
   1835                                plContext),
   1836                                PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
   1837 
   1838                        if (nssOriginalAltName == NULL) {
   1839                                cert->subjAltNamesAbsent = PKIX_TRUE;
   1840                                pSubjectAltNames = NULL;
   1841                                goto cleanup;
   1842                        }
   1843 
   1844                        nssTempAltName = nssOriginalAltName;
   1845 
   1846                        PKIX_CHECK(PKIX_List_Create(&altNamesList, plContext),
   1847                                PKIX_LISTCREATEFAILED);
   1848 
   1849                        do {
   1850                            PKIX_CHECK(pkix_pl_GeneralName_Create
   1851                                (nssTempAltName, &pkixAltName, plContext),
   1852                                PKIX_GENERALNAMECREATEFAILED);
   1853 
   1854                            PKIX_CHECK(PKIX_List_AppendItem
   1855                                (altNamesList,
   1856                                (PKIX_PL_Object *)pkixAltName,
   1857                                plContext),
   1858                                PKIX_LISTAPPENDITEMFAILED);
   1859 
   1860                            PKIX_DECREF(pkixAltName);
   1861 
   1862                            PKIX_CERT_DEBUG
   1863                                ("\t\tCalling CERT_GetNextGeneralName).\n");
   1864                            nssTempAltName = CERT_GetNextGeneralName
   1865                                (nssTempAltName);
   1866 
   1867                        } while (nssTempAltName != nssOriginalAltName);
   1868 
   1869                        /* save a cached copy in case it is asked for again */
   1870                        cert->subjAltNames = altNamesList;
   1871                        PKIX_CHECK(PKIX_List_SetImmutable
   1872                                (cert->subjAltNames, plContext),
   1873                                PKIX_LISTSETIMMUTABLEFAILED);
   1874 
   1875                }
   1876 
   1877                PKIX_OBJECT_UNLOCK(cert);
   1878        }
   1879 
   1880        PKIX_INCREF(cert->subjAltNames);
   1881 
   1882        *pSubjectAltNames = cert->subjAltNames;
   1883 
   1884 cleanup:
   1885        PKIX_DECREF(pkixAltName);
   1886        if (PKIX_ERROR_RECEIVED){
   1887                PKIX_DECREF(altNamesList);
   1888        }
   1889        PKIX_RETURN(CERT);
   1890 }
   1891 
   1892 /*
   1893 * FUNCTION: PKIX_PL_Cert_GetAllSubjectNames (see comments in pkix_pl_pki.h)
   1894 */
   1895 PKIX_Error *
   1896 PKIX_PL_Cert_GetAllSubjectNames(
   1897        PKIX_PL_Cert *cert,
   1898        PKIX_List **pAllSubjectNames,  /* list of PKIX_PL_GeneralName */
   1899        void *plContext)
   1900 {
   1901        CERTGeneralName *nssOriginalSubjectName = NULL;
   1902        CERTGeneralName *nssTempSubjectName = NULL;
   1903        PKIX_List *allSubjectNames = NULL;
   1904        PKIX_PL_GeneralName *pkixSubjectName = NULL;
   1905        PLArenaPool *arena = NULL;
   1906 
   1907        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAllSubjectNames");
   1908        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAllSubjectNames);
   1909 
   1910 
   1911        if (cert->nssCert->subjectName == NULL){
   1912                /* if there is no subject DN, just get altnames */
   1913 
   1914                PKIX_CHECK(pkix_pl_Cert_GetNssSubjectAltNames
   1915                            (cert,
   1916                            PKIX_FALSE, /* hasLock */
   1917                            &nssOriginalSubjectName,
   1918                            plContext),
   1919                            PKIX_CERTGETNSSSUBJECTALTNAMESFAILED);
   1920 
   1921        } else { /* get subject DN and altnames */
   1922 
   1923                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1924                if (arena == NULL) {
   1925                        PKIX_ERROR(PKIX_OUTOFMEMORY);
   1926                }
   1927 
   1928                /* This NSS call returns both Subject and  Subject Alt Names */
   1929                PKIX_CERT_DEBUG("\t\tCalling CERT_GetCertificateNames\n");
   1930                nssOriginalSubjectName =
   1931                        CERT_GetCertificateNames(cert->nssCert, arena);
   1932        }
   1933 
   1934        if (nssOriginalSubjectName == NULL) {
   1935                pAllSubjectNames = NULL;
   1936                goto cleanup;
   1937        }
   1938 
   1939        nssTempSubjectName = nssOriginalSubjectName;
   1940 
   1941        PKIX_CHECK(PKIX_List_Create(&allSubjectNames, plContext),
   1942                    PKIX_LISTCREATEFAILED);
   1943 
   1944        do {
   1945                PKIX_CHECK(pkix_pl_GeneralName_Create
   1946                            (nssTempSubjectName, &pkixSubjectName, plContext),
   1947                            PKIX_GENERALNAMECREATEFAILED);
   1948 
   1949                PKIX_CHECK(PKIX_List_AppendItem
   1950                            (allSubjectNames,
   1951                            (PKIX_PL_Object *)pkixSubjectName,
   1952                            plContext),
   1953                            PKIX_LISTAPPENDITEMFAILED);
   1954 
   1955                PKIX_DECREF(pkixSubjectName);
   1956 
   1957                PKIX_CERT_DEBUG
   1958                        ("\t\tCalling CERT_GetNextGeneralName).\n");
   1959                nssTempSubjectName = CERT_GetNextGeneralName
   1960                        (nssTempSubjectName);
   1961        } while (nssTempSubjectName != nssOriginalSubjectName);
   1962 
   1963        *pAllSubjectNames = allSubjectNames;
   1964 
   1965 cleanup:
   1966        if (PKIX_ERROR_RECEIVED){
   1967                PKIX_DECREF(allSubjectNames);
   1968        }
   1969 
   1970        if (arena){
   1971                PORT_FreeArena(arena, PR_FALSE);
   1972        }
   1973        PKIX_DECREF(pkixSubjectName);
   1974        PKIX_RETURN(CERT);
   1975 }
   1976 
   1977 /*
   1978 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKeyAlgId
   1979 *      (see comments in pkix_pl_pki.h)
   1980 */
   1981 PKIX_Error *
   1982 PKIX_PL_Cert_GetSubjectPublicKeyAlgId(
   1983        PKIX_PL_Cert *cert,
   1984        PKIX_PL_OID **pSubjKeyAlgId,
   1985        void *plContext)
   1986 {
   1987        PKIX_PL_OID *pubKeyAlgId = NULL;
   1988 
   1989        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
   1990        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyAlgId);
   1991 
   1992        /* if we don't have a cached copy from before, we create one */
   1993        if (cert->publicKeyAlgId == NULL){
   1994                PKIX_OBJECT_LOCK(cert);
   1995                if (cert->publicKeyAlgId == NULL){
   1996                        CERTCertificate *nssCert = cert->nssCert;
   1997                        SECAlgorithmID *algorithm;
   1998                        SECItem *algBytes;
   1999 
   2000                        algorithm = &nssCert->subjectPublicKeyInfo.algorithm;
   2001                        algBytes = &algorithm->algorithm;
   2002                        if (!algBytes->data || !algBytes->len) {
   2003                            PKIX_ERROR_FATAL(PKIX_ALGORITHMBYTESLENGTH0);
   2004                        }
   2005                        PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
   2006                                    (algBytes, &pubKeyAlgId, plContext),
   2007                                    PKIX_OIDCREATEFAILED);
   2008 
   2009                        /* save a cached copy in case it is asked for again */
   2010                        cert->publicKeyAlgId = pubKeyAlgId;
   2011                        pubKeyAlgId = NULL;
   2012                }
   2013                PKIX_OBJECT_UNLOCK(cert);
   2014        }
   2015 
   2016        PKIX_INCREF(cert->publicKeyAlgId);
   2017        *pSubjKeyAlgId = cert->publicKeyAlgId;
   2018 
   2019 cleanup:
   2020        PKIX_DECREF(pubKeyAlgId);
   2021        PKIX_RETURN(CERT);
   2022 }
   2023 
   2024 /*
   2025 * FUNCTION: PKIX_PL_Cert_GetSubjectPublicKey (see comments in pkix_pl_pki.h)
   2026 */
   2027 PKIX_Error *
   2028 PKIX_PL_Cert_GetSubjectPublicKey(
   2029        PKIX_PL_Cert *cert,
   2030        PKIX_PL_PublicKey **pPublicKey,
   2031        void *plContext)
   2032 {
   2033        PKIX_PL_PublicKey *pkixPubKey = NULL;
   2034        SECStatus rv;
   2035 
   2036        CERTSubjectPublicKeyInfo *from = NULL;
   2037        CERTSubjectPublicKeyInfo *to = NULL;
   2038        SECItem *fromItem = NULL;
   2039        SECItem *toItem = NULL;
   2040 
   2041        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectPublicKey");
   2042        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPublicKey);
   2043 
   2044        /* if we don't have a cached copy from before, we create one */
   2045        if (cert->publicKey == NULL){
   2046 
   2047                PKIX_OBJECT_LOCK(cert);
   2048 
   2049                if (cert->publicKey == NULL){
   2050 
   2051                        /* create a PKIX_PL_PublicKey object */
   2052                        PKIX_CHECK(PKIX_PL_Object_Alloc
   2053                                    (PKIX_PUBLICKEY_TYPE,
   2054                                    sizeof (PKIX_PL_PublicKey),
   2055                                    (PKIX_PL_Object **)&pkixPubKey,
   2056                                    plContext),
   2057                                    PKIX_COULDNOTCREATEOBJECT);
   2058 
   2059                        /* initialize fields */
   2060                        pkixPubKey->nssSPKI = NULL;
   2061 
   2062                        /* populate the SPKI field */
   2063                        PKIX_CHECK(PKIX_PL_Malloc
   2064                                    (sizeof (CERTSubjectPublicKeyInfo),
   2065                                    (void **)&pkixPubKey->nssSPKI,
   2066                                    plContext),
   2067                                    PKIX_MALLOCFAILED);
   2068 
   2069                        to = pkixPubKey->nssSPKI;
   2070                        from  = &cert->nssCert->subjectPublicKeyInfo;
   2071 
   2072                        PKIX_NULLCHECK_TWO(to, from);
   2073 
   2074                        PKIX_CERT_DEBUG
   2075                                ("\t\tCalling SECOID_CopyAlgorithmID).\n");
   2076                        rv = SECOID_CopyAlgorithmID
   2077                                (NULL, &to->algorithm, &from->algorithm);
   2078                        if (rv != SECSuccess) {
   2079                                PKIX_ERROR(PKIX_SECOIDCOPYALGORITHMIDFAILED);
   2080                        }
   2081 
   2082                        /*
   2083                         * NSS stores the length of subjectPublicKey in bits.
   2084                         * Therefore, we use that length converted to bytes
   2085                         * using ((length+7)>>3) before calling PORT_Memcpy
   2086                         * in order to avoid "read from uninitialized memory"
   2087                         * errors.
   2088                         */
   2089 
   2090                        toItem = &to->subjectPublicKey;
   2091                        fromItem = &from->subjectPublicKey;
   2092 
   2093                        PKIX_NULLCHECK_TWO(toItem, fromItem);
   2094 
   2095                        toItem->type = fromItem->type;
   2096 
   2097                        toItem->data =
   2098                                (unsigned char*) PORT_ZAlloc(fromItem->len);
   2099                        if (!toItem->data){
   2100                                PKIX_ERROR(PKIX_OUTOFMEMORY);
   2101                        }
   2102 
   2103                        (void) PORT_Memcpy(toItem->data,
   2104                                    fromItem->data,
   2105                                    (fromItem->len + 7)>>3);
   2106                        toItem->len = fromItem->len;
   2107 
   2108                        /* save a cached copy in case it is asked for again */
   2109                        cert->publicKey = pkixPubKey;
   2110                }
   2111 
   2112                PKIX_OBJECT_UNLOCK(cert);
   2113        }
   2114 
   2115        PKIX_INCREF(cert->publicKey);
   2116        *pPublicKey = cert->publicKey;
   2117 
   2118 cleanup:
   2119 
   2120        if (PKIX_ERROR_RECEIVED && pkixPubKey){
   2121                PKIX_DECREF(pkixPubKey);
   2122                cert->publicKey = NULL;
   2123        }
   2124        PKIX_RETURN(CERT);
   2125 }
   2126 
   2127 /*
   2128 * FUNCTION: PKIX_PL_Cert_GetCriticalExtensionOIDs
   2129 *      (see comments in pkix_pl_pki.h)
   2130 */
   2131 PKIX_Error *
   2132 PKIX_PL_Cert_GetCriticalExtensionOIDs(
   2133        PKIX_PL_Cert *cert,
   2134        PKIX_List **pList,  /* list of PKIX_PL_OID */
   2135        void *plContext)
   2136 {
   2137        PKIX_List *oidsList = NULL;
   2138        CERTCertExtension **extensions = NULL;
   2139        CERTCertificate *nssCert = NULL;
   2140 
   2141        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCriticalExtensionOIDs");
   2142        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pList);
   2143 
   2144        /* if we don't have a cached copy from before, we create one */
   2145        if (cert->critExtOids == NULL) {
   2146 
   2147            PKIX_OBJECT_LOCK(cert);
   2148 
   2149            if (cert->critExtOids == NULL) {
   2150 
   2151                nssCert = cert->nssCert;
   2152 
   2153                /*
   2154                 * ASN.1 for Extension
   2155                 *
   2156                 * Extension  ::=  SEQUENCE  {
   2157                 *      extnID          OBJECT IDENTIFIER,
   2158                 *      critical        BOOLEAN DEFAULT FALSE,
   2159                 *      extnValue       OCTET STRING  }
   2160                 *
   2161                 */
   2162 
   2163                extensions = nssCert->extensions;
   2164 
   2165                PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
   2166                            (extensions, &oidsList, plContext),
   2167                            PKIX_GETCRITICALEXTENSIONOIDSFAILED);
   2168 
   2169                /* save a cached copy in case it is asked for again */
   2170                cert->critExtOids = oidsList;
   2171            }
   2172 
   2173            PKIX_OBJECT_UNLOCK(cert);
   2174        }
   2175 
   2176        /* We should return a copy of the List since this list changes */
   2177        PKIX_DUPLICATE(cert->critExtOids, pList, plContext,
   2178                PKIX_OBJECTDUPLICATELISTFAILED);
   2179 
   2180 cleanup:
   2181 PKIX_OBJECT_UNLOCK(lockedObject);
   2182        PKIX_RETURN(CERT);
   2183 }
   2184 
   2185 /*
   2186 * FUNCTION: PKIX_PL_Cert_GetAuthorityKeyIdentifier
   2187 *      (see comments in pkix_pl_pki.h)
   2188 */
   2189 PKIX_Error *
   2190 PKIX_PL_Cert_GetAuthorityKeyIdentifier(
   2191        PKIX_PL_Cert *cert,
   2192        PKIX_PL_ByteArray **pAuthKeyId,
   2193        void *plContext)
   2194 {
   2195        PKIX_PL_ByteArray *authKeyId = NULL;
   2196        CERTCertificate *nssCert = NULL;
   2197        CERTAuthKeyID *authKeyIdExtension = NULL;
   2198        PLArenaPool *arena = NULL;
   2199        SECItem retItem;
   2200 
   2201        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityKeyIdentifier");
   2202        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAuthKeyId);
   2203 
   2204        /* if we don't have a cached copy from before, we create one */
   2205        if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
   2206 
   2207                PKIX_OBJECT_LOCK(cert);
   2208 
   2209                if ((cert->authKeyId == NULL) && (!cert->authKeyIdAbsent)){
   2210 
   2211                        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2212                        if (arena == NULL) {
   2213                                PKIX_ERROR(PKIX_OUTOFMEMORY);
   2214                        }
   2215 
   2216                        nssCert = cert->nssCert;
   2217 
   2218                        authKeyIdExtension =
   2219                                CERT_FindAuthKeyIDExten(arena, nssCert);
   2220                        if (authKeyIdExtension == NULL){
   2221                                cert->authKeyIdAbsent = PKIX_TRUE;
   2222                                *pAuthKeyId = NULL;
   2223                                goto cleanup;
   2224                        }
   2225 
   2226                        retItem = authKeyIdExtension->keyID;
   2227 
   2228                        if (retItem.len == 0){
   2229                                cert->authKeyIdAbsent = PKIX_TRUE;
   2230                                *pAuthKeyId = NULL;
   2231                                goto cleanup;
   2232                        }
   2233 
   2234                        PKIX_CHECK(PKIX_PL_ByteArray_Create
   2235                                    (retItem.data,
   2236                                    retItem.len,
   2237                                    &authKeyId,
   2238                                    plContext),
   2239                                    PKIX_BYTEARRAYCREATEFAILED);
   2240 
   2241                        /* save a cached copy in case it is asked for again */
   2242                        cert->authKeyId = authKeyId;
   2243                }
   2244 
   2245                PKIX_OBJECT_UNLOCK(cert);
   2246        }
   2247 
   2248        PKIX_INCREF(cert->authKeyId);
   2249        *pAuthKeyId = cert->authKeyId;
   2250 
   2251 cleanup:
   2252 PKIX_OBJECT_UNLOCK(lockedObject);
   2253        if (arena){
   2254                PORT_FreeArena(arena, PR_FALSE);
   2255        }
   2256        PKIX_RETURN(CERT);
   2257 }
   2258 
   2259 /*
   2260 * FUNCTION: PKIX_PL_Cert_GetSubjectKeyIdentifier
   2261 *      (see comments in pkix_pl_pki.h)
   2262 */
   2263 PKIX_Error *
   2264 PKIX_PL_Cert_GetSubjectKeyIdentifier(
   2265        PKIX_PL_Cert *cert,
   2266        PKIX_PL_ByteArray **pSubjKeyId,
   2267        void *plContext)
   2268 {
   2269        PKIX_PL_ByteArray *subjKeyId = NULL;
   2270        CERTCertificate *nssCert = NULL;
   2271        SECItem *retItem = NULL;
   2272        SECStatus status;
   2273 
   2274        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectKeyIdentifier");
   2275        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSubjKeyId);
   2276 
   2277        /* if we don't have a cached copy from before, we create one */
   2278        if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
   2279 
   2280                PKIX_OBJECT_LOCK(cert);
   2281 
   2282                if ((cert->subjKeyId == NULL) && (!cert->subjKeyIdAbsent)){
   2283 
   2284                        retItem = SECITEM_AllocItem(NULL, NULL, 0);
   2285                        if (retItem == NULL){
   2286                                PKIX_ERROR(PKIX_OUTOFMEMORY);
   2287                        }
   2288 
   2289                        nssCert = cert->nssCert;
   2290 
   2291                        status = CERT_FindSubjectKeyIDExtension
   2292                                (nssCert, retItem);
   2293                        if (status != SECSuccess) {
   2294                                cert->subjKeyIdAbsent = PKIX_TRUE;
   2295                                *pSubjKeyId = NULL;
   2296                                goto cleanup;
   2297                        }
   2298 
   2299                        PKIX_CHECK(PKIX_PL_ByteArray_Create
   2300                                    (retItem->data,
   2301                                    retItem->len,
   2302                                    &subjKeyId,
   2303                                    plContext),
   2304                                    PKIX_BYTEARRAYCREATEFAILED);
   2305 
   2306                        /* save a cached copy in case it is asked for again */
   2307                        cert->subjKeyId = subjKeyId;
   2308                }
   2309 
   2310                PKIX_OBJECT_UNLOCK(cert);
   2311        }
   2312 
   2313        PKIX_INCREF(cert->subjKeyId);
   2314        *pSubjKeyId = cert->subjKeyId;
   2315 
   2316 cleanup:
   2317 PKIX_OBJECT_UNLOCK(lockedObject);
   2318        if (retItem){
   2319                SECITEM_FreeItem(retItem, PKIX_TRUE);
   2320        }
   2321        PKIX_RETURN(CERT);
   2322 }
   2323 
   2324 /*
   2325 * FUNCTION: PKIX_PL_Cert_GetExtendedKeyUsage (see comments in pkix_pl_pki.h)
   2326 */
   2327 PKIX_Error *
   2328 PKIX_PL_Cert_GetExtendedKeyUsage(
   2329        PKIX_PL_Cert *cert,
   2330        PKIX_List **pKeyUsage,  /* list of PKIX_PL_OID */
   2331        void *plContext)
   2332 {
   2333        CERTOidSequence *extKeyUsage = NULL;
   2334        CERTCertificate *nssCert = NULL;
   2335        PKIX_PL_OID *pkixOID = NULL;
   2336        PKIX_List *oidsList = NULL;
   2337        SECItem **oids = NULL;
   2338        SECItem encodedExtKeyUsage;
   2339        SECStatus rv;
   2340 
   2341        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetExtendedKeyUsage");
   2342        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pKeyUsage);
   2343 
   2344        /* if we don't have a cached copy from before, we create one */
   2345        if ((cert->extKeyUsages == NULL) && (!cert->extKeyUsagesAbsent)){
   2346 
   2347                PKIX_OBJECT_LOCK(cert);
   2348 
   2349                if ((cert->extKeyUsages == NULL) &&
   2350                    (!cert->extKeyUsagesAbsent)){
   2351 
   2352                        nssCert = cert->nssCert;
   2353 
   2354                        rv = CERT_FindCertExtension
   2355                                (nssCert, SEC_OID_X509_EXT_KEY_USAGE,
   2356                                &encodedExtKeyUsage);
   2357                        if (rv != SECSuccess){
   2358                                cert->extKeyUsagesAbsent = PKIX_TRUE;
   2359                                *pKeyUsage = NULL;
   2360                                goto cleanup;
   2361                        }
   2362 
   2363                        extKeyUsage =
   2364                                CERT_DecodeOidSequence(&encodedExtKeyUsage);
   2365                        if (extKeyUsage == NULL){
   2366                                PKIX_ERROR(PKIX_CERTDECODEOIDSEQUENCEFAILED);
   2367                        }
   2368 
   2369                        PORT_Free(encodedExtKeyUsage.data);
   2370 
   2371                        oids = extKeyUsage->oids;
   2372 
   2373                        if (!oids){
   2374                                /* no extended key usage extensions found */
   2375                                cert->extKeyUsagesAbsent = PKIX_TRUE;
   2376                                *pKeyUsage = NULL;
   2377                                goto cleanup;
   2378                        }
   2379 
   2380                        PKIX_CHECK(PKIX_List_Create(&oidsList, plContext),
   2381                                    PKIX_LISTCREATEFAILED);
   2382 
   2383                        while (*oids){
   2384                                SECItem *oid = *oids++;
   2385 
   2386                                PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
   2387                                            (oid, &pkixOID, plContext),
   2388                                            PKIX_OIDCREATEFAILED);
   2389 
   2390                                PKIX_CHECK(PKIX_List_AppendItem
   2391                                            (oidsList,
   2392                                            (PKIX_PL_Object *)pkixOID,
   2393                                            plContext),
   2394                                            PKIX_LISTAPPENDITEMFAILED);
   2395                                PKIX_DECREF(pkixOID);
   2396                        }
   2397 
   2398                        PKIX_CHECK(PKIX_List_SetImmutable
   2399                                    (oidsList, plContext),
   2400                                    PKIX_LISTSETIMMUTABLEFAILED);
   2401 
   2402                        /* save a cached copy in case it is asked for again */
   2403                        cert->extKeyUsages = oidsList;
   2404                        oidsList = NULL;
   2405                }
   2406 
   2407                PKIX_OBJECT_UNLOCK(cert);
   2408        }
   2409 
   2410        PKIX_INCREF(cert->extKeyUsages);
   2411        *pKeyUsage = cert->extKeyUsages;
   2412 
   2413 cleanup:
   2414 PKIX_OBJECT_UNLOCK(lockedObject);
   2415 
   2416        PKIX_DECREF(pkixOID);
   2417        PKIX_DECREF(oidsList);
   2418        CERT_DestroyOidSequence(extKeyUsage);
   2419 
   2420        PKIX_RETURN(CERT);
   2421 }
   2422 
   2423 /*
   2424 * FUNCTION: PKIX_PL_Cert_GetBasicConstraints
   2425 * (see comments in pkix_pl_pki.h)
   2426 */
   2427 PKIX_Error *
   2428 PKIX_PL_Cert_GetBasicConstraints(
   2429        PKIX_PL_Cert *cert,
   2430        PKIX_PL_CertBasicConstraints **pBasicConstraints,
   2431        void *plContext)
   2432 {
   2433        CERTCertificate *nssCert = NULL;
   2434        CERTBasicConstraints nssBasicConstraint;
   2435        SECStatus rv;
   2436        PKIX_PL_CertBasicConstraints *basic;
   2437        PKIX_Int32 pathLen = 0;
   2438        PKIX_Boolean isCA = PKIX_FALSE;
   2439        enum {
   2440          realBC, synthBC, absentBC
   2441        } constraintSource = absentBC;
   2442 
   2443        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetBasicConstraints");
   2444        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pBasicConstraints);
   2445 
   2446        /* if we don't have a cached copy from before, we create one */
   2447        if ((cert->certBasicConstraints == NULL) &&
   2448                (!cert->basicConstraintsAbsent)) {
   2449 
   2450                PKIX_OBJECT_LOCK(cert);
   2451 
   2452                if ((cert->certBasicConstraints == NULL) &&
   2453                    (!cert->basicConstraintsAbsent)) {
   2454 
   2455                        nssCert = cert->nssCert;
   2456 
   2457                        PKIX_CERT_DEBUG(
   2458                            "\t\tCalling Cert_FindBasicConstraintExten\n");
   2459                        rv = CERT_FindBasicConstraintExten
   2460                                (nssCert, &nssBasicConstraint);
   2461                        if (rv == SECSuccess) {
   2462                            constraintSource = realBC;
   2463                        }
   2464 
   2465                        if (constraintSource == absentBC) {
   2466                            /* can we deduce it's a CA and create a 
   2467                               synthetic constraint?
   2468                            */
   2469                            CERTCertTrust trust;
   2470                            rv = CERT_GetCertTrust(nssCert, &trust);
   2471                            if (rv == SECSuccess) {
   2472                                int anyWantedFlag = CERTDB_TRUSTED_CA | CERTDB_VALID_CA;
   2473                                if ((trust.sslFlags & anyWantedFlag) 
   2474                                    || (trust.emailFlags & anyWantedFlag) 
   2475                                    || (trust.objectSigningFlags & anyWantedFlag)) {
   2476 
   2477                                    constraintSource = synthBC;
   2478                                }
   2479                            }
   2480                        }
   2481 
   2482                        if (constraintSource == absentBC) {
   2483                            cert->basicConstraintsAbsent = PKIX_TRUE;
   2484                            *pBasicConstraints = NULL;
   2485                            goto cleanup;
   2486                        }
   2487                }
   2488 
   2489                if (constraintSource == synthBC) {
   2490                    isCA = PKIX_TRUE;
   2491                    pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
   2492                } else {
   2493                    isCA = (nssBasicConstraint.isCA)?PKIX_TRUE:PKIX_FALSE;
   2494    
   2495                    /* The pathLen has meaning only for CAs */
   2496                    if (isCA) {
   2497                        if (CERT_UNLIMITED_PATH_CONSTRAINT ==
   2498                            nssBasicConstraint.pathLenConstraint) {
   2499                            pathLen = PKIX_UNLIMITED_PATH_CONSTRAINT;
   2500                        } else {
   2501                            pathLen = nssBasicConstraint.pathLenConstraint;
   2502                        }
   2503                    }
   2504                }
   2505 
   2506                PKIX_CHECK(pkix_pl_CertBasicConstraints_Create
   2507                            (isCA, pathLen, &basic, plContext),
   2508                            PKIX_CERTBASICCONSTRAINTSCREATEFAILED);
   2509 
   2510                /* save a cached copy in case it is asked for again */
   2511                cert->certBasicConstraints = basic;
   2512        }
   2513 
   2514        PKIX_INCREF(cert->certBasicConstraints);
   2515        *pBasicConstraints = cert->certBasicConstraints;
   2516 
   2517 cleanup:
   2518 PKIX_OBJECT_UNLOCK(lockedObject);
   2519        PKIX_RETURN(CERT);
   2520 }
   2521 
   2522 /*
   2523 * FUNCTION: PKIX_PL_Cert_GetPolicyInformation
   2524 * (see comments in pkix_pl_pki.h)
   2525 */
   2526 PKIX_Error *
   2527 PKIX_PL_Cert_GetPolicyInformation(
   2528        PKIX_PL_Cert *cert,
   2529        PKIX_List **pPolicyInfo,
   2530        void *plContext)
   2531 {
   2532        PKIX_List *policyList = NULL;
   2533 
   2534        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyInformation");
   2535        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyInfo);
   2536 
   2537        /* if we don't have a cached copy from before, we create one */
   2538        if ((cert->certPolicyInfos == NULL) &&
   2539                (!cert->policyInfoAbsent)) {
   2540 
   2541                PKIX_OBJECT_LOCK(cert);
   2542 
   2543                if ((cert->certPolicyInfos == NULL) &&
   2544                    (!cert->policyInfoAbsent)) {
   2545 
   2546                        PKIX_CHECK(pkix_pl_Cert_DecodePolicyInfo
   2547                                (cert->nssCert, &policyList, plContext),
   2548                                PKIX_CERTDECODEPOLICYINFOFAILED);
   2549 
   2550                        if (!policyList) {
   2551                                cert->policyInfoAbsent = PKIX_TRUE;
   2552                                *pPolicyInfo = NULL;
   2553                                goto cleanup;
   2554                        }
   2555                }
   2556 
   2557                PKIX_OBJECT_UNLOCK(cert);
   2558 
   2559                /* save a cached copy in case it is asked for again */
   2560                cert->certPolicyInfos = policyList;
   2561                policyList = NULL;
   2562        }
   2563 
   2564        PKIX_INCREF(cert->certPolicyInfos);
   2565        *pPolicyInfo = cert->certPolicyInfos;
   2566 
   2567 cleanup:
   2568 PKIX_OBJECT_UNLOCK(lockedObject);
   2569 
   2570        PKIX_DECREF(policyList);
   2571        PKIX_RETURN(CERT);
   2572 }
   2573 
   2574 /*
   2575 * FUNCTION: PKIX_PL_Cert_GetPolicyMappings (see comments in pkix_pl_pki.h)
   2576 */
   2577 PKIX_Error *
   2578 PKIX_PL_Cert_GetPolicyMappings(
   2579        PKIX_PL_Cert *cert,
   2580        PKIX_List **pPolicyMappings, /* list of PKIX_PL_CertPolicyMap */
   2581        void *plContext)
   2582 {
   2583        PKIX_List *policyMappings = NULL; /* list of PKIX_PL_CertPolicyMap */
   2584 
   2585        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappings");
   2586        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pPolicyMappings);
   2587 
   2588        /* if we don't have a cached copy from before, we create one */
   2589        if (!(cert->certPolicyMappings) && !(cert->policyMappingsAbsent)) {
   2590 
   2591                PKIX_OBJECT_LOCK(cert);
   2592 
   2593                if (!(cert->certPolicyMappings) &&
   2594                    !(cert->policyMappingsAbsent)) {
   2595 
   2596                        PKIX_CHECK(pkix_pl_Cert_DecodePolicyMapping
   2597                                (cert->nssCert, &policyMappings, plContext),
   2598                                PKIX_CERTDECODEPOLICYMAPPINGFAILED);
   2599 
   2600                        if (!policyMappings) {
   2601                                cert->policyMappingsAbsent = PKIX_TRUE;
   2602                                *pPolicyMappings = NULL;
   2603                                goto cleanup;
   2604                        }
   2605                }
   2606 
   2607                PKIX_OBJECT_UNLOCK(cert);
   2608 
   2609                /* save a cached copy in case it is asked for again */
   2610                cert->certPolicyMappings = policyMappings; 
   2611                policyMappings = NULL;
   2612        }
   2613 
   2614        PKIX_INCREF(cert->certPolicyMappings);
   2615        *pPolicyMappings = cert->certPolicyMappings;
   2616        
   2617 cleanup:
   2618 PKIX_OBJECT_UNLOCK(lockedObject);
   2619 
   2620        PKIX_DECREF(policyMappings);
   2621        PKIX_RETURN(CERT);
   2622 }
   2623 
   2624 /*
   2625 * FUNCTION: PKIX_PL_Cert_GetRequireExplicitPolicy
   2626 * (see comments in pkix_pl_pki.h)
   2627 */
   2628 PKIX_Error *
   2629 PKIX_PL_Cert_GetRequireExplicitPolicy(
   2630        PKIX_PL_Cert *cert,
   2631        PKIX_Int32 *pSkipCerts,
   2632        void *plContext)
   2633 {
   2634        PKIX_Int32 explicitPolicySkipCerts = 0;
   2635        PKIX_Int32 inhibitMappingSkipCerts = 0;
   2636 
   2637        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetRequireExplicitPolicy");
   2638        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
   2639 
   2640        if (!(cert->policyConstraintsProcessed)) {
   2641                PKIX_OBJECT_LOCK(cert);
   2642 
   2643                if (!(cert->policyConstraintsProcessed)) {
   2644 
   2645                        /*
   2646                         * If we can't process it now, we probably will be
   2647                         * unable to process it later. Set the default value.
   2648                         */
   2649                        cert->policyConstraintsProcessed = PKIX_TRUE;
   2650                        cert->policyConstraintsExplicitPolicySkipCerts = -1;
   2651                        cert->policyConstraintsInhibitMappingSkipCerts = -1;
   2652 
   2653                        PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
   2654                                (cert->nssCert,
   2655                                &explicitPolicySkipCerts,
   2656                                &inhibitMappingSkipCerts,
   2657                                plContext),
   2658                                PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
   2659 
   2660                        cert->policyConstraintsExplicitPolicySkipCerts =
   2661                                explicitPolicySkipCerts;
   2662                        cert->policyConstraintsInhibitMappingSkipCerts =
   2663                                inhibitMappingSkipCerts;
   2664                }
   2665 
   2666                PKIX_OBJECT_UNLOCK(cert);
   2667        }
   2668 
   2669        *pSkipCerts = cert->policyConstraintsExplicitPolicySkipCerts;
   2670 
   2671 cleanup:
   2672 PKIX_OBJECT_UNLOCK(lockedObject);
   2673        PKIX_RETURN(CERT);
   2674 }
   2675 
   2676 /*
   2677 * FUNCTION: PKIX_PL_Cert_GetPolicyMappingInhibited
   2678 * (see comments in pkix_pl_pki.h)
   2679 */
   2680 PKIX_Error *
   2681 PKIX_PL_Cert_GetPolicyMappingInhibited(
   2682        PKIX_PL_Cert *cert,
   2683        PKIX_Int32 *pSkipCerts,
   2684        void *plContext)
   2685 {
   2686        PKIX_Int32 explicitPolicySkipCerts = 0;
   2687        PKIX_Int32 inhibitMappingSkipCerts = 0;
   2688 
   2689        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetPolicyMappingInhibited");
   2690        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
   2691 
   2692        if (!(cert->policyConstraintsProcessed)) {
   2693                PKIX_OBJECT_LOCK(cert);
   2694 
   2695                if (!(cert->policyConstraintsProcessed)) {
   2696 
   2697                        /*
   2698                         * If we can't process it now, we probably will be
   2699                         * unable to process it later. Set the default value.
   2700                         */
   2701                        cert->policyConstraintsProcessed = PKIX_TRUE;
   2702                        cert->policyConstraintsExplicitPolicySkipCerts = -1;
   2703                        cert->policyConstraintsInhibitMappingSkipCerts = -1;
   2704 
   2705                        PKIX_CHECK(pkix_pl_Cert_DecodePolicyConstraints
   2706                                (cert->nssCert,
   2707                                &explicitPolicySkipCerts,
   2708                                &inhibitMappingSkipCerts,
   2709                                plContext),
   2710                                PKIX_CERTDECODEPOLICYCONSTRAINTSFAILED);
   2711 
   2712                        cert->policyConstraintsExplicitPolicySkipCerts =
   2713                                explicitPolicySkipCerts;
   2714                        cert->policyConstraintsInhibitMappingSkipCerts =
   2715                                inhibitMappingSkipCerts;
   2716                }
   2717 
   2718                PKIX_OBJECT_UNLOCK(cert);
   2719        }
   2720 
   2721        *pSkipCerts = cert->policyConstraintsInhibitMappingSkipCerts;
   2722 
   2723 cleanup:
   2724 PKIX_OBJECT_UNLOCK(lockedObject);
   2725        PKIX_RETURN(CERT);
   2726 }
   2727 
   2728 /*
   2729 * FUNCTION: PKIX_PL_Cert_GetInhibitAnyPolicy (see comments in pkix_pl_pki.h)
   2730 */
   2731 PKIX_Error *
   2732 PKIX_PL_Cert_GetInhibitAnyPolicy(
   2733        PKIX_PL_Cert *cert,
   2734        PKIX_Int32 *pSkipCerts,
   2735        void *plContext)
   2736 {
   2737        PKIX_Int32 skipCerts = 0;
   2738 
   2739        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetInhibitAnyPolicy");
   2740        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSkipCerts);
   2741 
   2742        if (!(cert->inhibitAnyPolicyProcessed)) {
   2743 
   2744                PKIX_OBJECT_LOCK(cert);
   2745 
   2746                if (!(cert->inhibitAnyPolicyProcessed)) {
   2747 
   2748                        /*
   2749                         * If we can't process it now, we probably will be
   2750                         * unable to process it later. Set the default value.
   2751                         */
   2752                        cert->inhibitAnyPolicyProcessed = PKIX_TRUE;
   2753                        cert->inhibitAnySkipCerts = -1;
   2754 
   2755                        PKIX_CHECK(pkix_pl_Cert_DecodeInhibitAnyPolicy
   2756                                (cert->nssCert, &skipCerts, plContext),
   2757                                PKIX_CERTDECODEINHIBITANYPOLICYFAILED);
   2758 
   2759                        cert->inhibitAnySkipCerts = skipCerts;
   2760                }
   2761 
   2762                PKIX_OBJECT_UNLOCK(cert);
   2763        }
   2764 
   2765 cleanup:
   2766 PKIX_OBJECT_UNLOCK(lockedObject);
   2767        *pSkipCerts = cert->inhibitAnySkipCerts;
   2768        PKIX_RETURN(CERT);
   2769 }
   2770 
   2771 /*
   2772 * FUNCTION: PKIX_PL_Cert_AreCertPoliciesCritical
   2773 * (see comments in pkix_pl_pki.h)
   2774 */
   2775 PKIX_Error *
   2776 PKIX_PL_Cert_AreCertPoliciesCritical(
   2777        PKIX_PL_Cert *cert,
   2778        PKIX_Boolean *pCritical,
   2779        void *plContext)
   2780 {
   2781        PKIX_Boolean criticality = PKIX_FALSE;
   2782 
   2783        PKIX_ENTER(CERT, "PKIX_PL_Cert_AreCertPoliciesCritical");
   2784        PKIX_NULLCHECK_TWO(cert, pCritical);
   2785 
   2786        PKIX_CHECK(pkix_pl_Cert_IsExtensionCritical(
   2787                cert,
   2788                SEC_OID_X509_CERTIFICATE_POLICIES,
   2789                &criticality,
   2790                plContext),
   2791                PKIX_CERTISEXTENSIONCRITICALFAILED);
   2792 
   2793        *pCritical = criticality;
   2794 
   2795 cleanup:
   2796        PKIX_RETURN(CERT);
   2797 }
   2798 
   2799 /*
   2800 * FUNCTION: PKIX_PL_Cert_VerifySignature (see comments in pkix_pl_pki.h)
   2801 */
   2802 PKIX_Error *
   2803 PKIX_PL_Cert_VerifySignature(
   2804        PKIX_PL_Cert *cert,
   2805        PKIX_PL_PublicKey *pubKey,
   2806        void *plContext)
   2807 {
   2808        CERTCertificate *nssCert = NULL;
   2809        SECKEYPublicKey *nssPubKey = NULL;
   2810        CERTSignedData *tbsCert = NULL;
   2811        PKIX_PL_Cert *cachedCert = NULL;
   2812        PKIX_Error *verifySig = NULL;
   2813        PKIX_Error *cachedSig = NULL;
   2814        PKIX_Error *checkSig = NULL;
   2815        SECStatus status;
   2816        PKIX_Boolean certEqual = PKIX_FALSE;
   2817        PKIX_Boolean certInHash = PKIX_FALSE;
   2818        PKIX_Boolean checkCertSig = PKIX_TRUE;
   2819        void* wincx = NULL;
   2820 
   2821        PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifySignature");
   2822        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pubKey);
   2823 
   2824        /* if the cert check flag is off, skip the check */
   2825        checkSig = pkix_pl_NssContext_GetCertSignatureCheck(
   2826                   (PKIX_PL_NssContext *)plContext, &checkCertSig);
   2827        if ((checkCertSig == PKIX_FALSE) && (checkSig == NULL)) {
   2828            goto cleanup;
   2829        }
   2830 
   2831        verifySig = PKIX_PL_HashTable_Lookup
   2832                        (cachedCertSigTable,
   2833                        (PKIX_PL_Object *) pubKey,
   2834                        (PKIX_PL_Object **) &cachedCert,
   2835                        plContext);
   2836 
   2837        if (cachedCert != NULL && verifySig == NULL) {
   2838                /* Cached Signature Table lookup succeed */
   2839                PKIX_EQUALS(cert, cachedCert, &certEqual, plContext,
   2840                            PKIX_OBJECTEQUALSFAILED);
   2841                if (certEqual == PKIX_TRUE) {
   2842                        goto cleanup;
   2843                }
   2844                /* Different PubKey may hash to same value, skip add */
   2845                certInHash = PKIX_TRUE;
   2846        }
   2847 
   2848        nssCert = cert->nssCert;
   2849        tbsCert = &nssCert->signatureWrap;
   2850 
   2851        PKIX_CERT_DEBUG("\t\tCalling SECKEY_ExtractPublicKey).\n");
   2852        nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
   2853        if (!nssPubKey){
   2854                PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
   2855        }
   2856 
   2857        PKIX_CERT_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey).\n");
   2858 
   2859        PKIX_CHECK(pkix_pl_NssContext_GetWincx
   2860                   ((PKIX_PL_NssContext *)plContext, &wincx),
   2861                   PKIX_NSSCONTEXTGETWINCXFAILED);
   2862 
   2863        status = CERT_VerifySignedDataWithPublicKey(tbsCert, nssPubKey, wincx);
   2864 
   2865        if (status != SECSuccess) {
   2866                if (PORT_GetError() != SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
   2867                        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   2868                }
   2869                PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
   2870        }
   2871 
   2872        if (certInHash == PKIX_FALSE) {
   2873                cachedSig = PKIX_PL_HashTable_Add
   2874                        (cachedCertSigTable,
   2875                        (PKIX_PL_Object *) pubKey,
   2876                        (PKIX_PL_Object *) cert,
   2877                        plContext);
   2878 
   2879                if (cachedSig != NULL) {
   2880                        PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
   2881                }
   2882        }
   2883 
   2884 cleanup:
   2885        if (nssPubKey){
   2886                PKIX_CERT_DEBUG("\t\tCalling SECKEY_DestroyPublicKey).\n");
   2887                SECKEY_DestroyPublicKey(nssPubKey);
   2888        }
   2889 
   2890        PKIX_DECREF(cachedCert);
   2891        PKIX_DECREF(checkSig);
   2892        PKIX_DECREF(verifySig);
   2893        PKIX_DECREF(cachedSig);
   2894 
   2895        PKIX_RETURN(CERT);
   2896 }
   2897 
   2898 /*
   2899 * FUNCTION: PKIX_PL_Cert_CheckValidity (see comments in pkix_pl_pki.h)
   2900 */
   2901 PKIX_Error *
   2902 PKIX_PL_Cert_CheckValidity(
   2903        PKIX_PL_Cert *cert,
   2904        PKIX_PL_Date *date,
   2905        void *plContext)
   2906 {
   2907        SECCertTimeValidity val;
   2908        PRTime timeToCheck;
   2909        PKIX_Boolean allowOverride;
   2910        SECCertificateUsage requiredUsages;
   2911 
   2912        PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckValidity");
   2913        PKIX_NULLCHECK_ONE(cert);
   2914 
   2915        /* if the caller supplies a date, we use it; else, use current time */
   2916        if (date != NULL){
   2917                PKIX_CHECK(pkix_pl_Date_GetPRTime
   2918                        (date, &timeToCheck, plContext),
   2919                        PKIX_DATEGETPRTIMEFAILED);
   2920        } else {
   2921                timeToCheck = PR_Now();
   2922        }
   2923 
   2924        requiredUsages = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
   2925        allowOverride =
   2926            (PRBool)((requiredUsages & certificateUsageSSLServer) ||
   2927                     (requiredUsages & certificateUsageSSLServerWithStepUp) ||
   2928                     (requiredUsages & certificateUsageIPsec));
   2929        val = CERT_CheckCertValidTimes(cert->nssCert, timeToCheck, allowOverride);
   2930        if (val != secCertTimeValid){
   2931                PKIX_ERROR(PKIX_CERTCHECKCERTVALIDTIMESFAILED);
   2932        }
   2933 
   2934 cleanup:
   2935        PKIX_RETURN(CERT);
   2936 }
   2937 
   2938 /*
   2939 * FUNCTION: PKIX_PL_Cert_GetValidityNotAfter (see comments in pkix_pl_pki.h)
   2940 */
   2941 PKIX_Error *
   2942 PKIX_PL_Cert_GetValidityNotAfter(
   2943        PKIX_PL_Cert *cert,
   2944        PKIX_PL_Date **pDate,
   2945        void *plContext)
   2946 {
   2947        PRTime prtime;
   2948        SECStatus rv = SECFailure;
   2949 
   2950        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetValidityNotAfter");
   2951        PKIX_NULLCHECK_TWO(cert, pDate);
   2952 
   2953        PKIX_DATE_DEBUG("\t\tCalling DER_DecodeTimeChoice).\n");
   2954        rv = DER_DecodeTimeChoice(&prtime, &(cert->nssCert->validity.notAfter));
   2955        if (rv != SECSuccess){
   2956                PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
   2957        }
   2958 
   2959        PKIX_CHECK(pkix_pl_Date_CreateFromPRTime
   2960                    (prtime, pDate, plContext),
   2961                    PKIX_DATECREATEFROMPRTIMEFAILED);
   2962 
   2963 cleanup:
   2964        PKIX_RETURN(CERT);
   2965 }
   2966 
   2967 /*
   2968 * FUNCTION: PKIX_PL_Cert_VerifyCertAndKeyType (see comments in pkix_pl_pki.h)
   2969 */
   2970 PKIX_Error *
   2971 PKIX_PL_Cert_VerifyCertAndKeyType(
   2972        PKIX_PL_Cert *cert,
   2973        PKIX_Boolean isChainCert,
   2974        void *plContext)
   2975 {
   2976    PKIX_PL_CertBasicConstraints *basicConstraints = NULL;
   2977    SECCertificateUsage certificateUsage;
   2978    SECCertUsage certUsage = 0;
   2979    unsigned int requiredKeyUsage;
   2980    unsigned int requiredCertType;
   2981    unsigned int certType;
   2982    SECStatus rv = SECSuccess;
   2983    
   2984    PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyCertType");
   2985    PKIX_NULLCHECK_TWO(cert, plContext);
   2986    
   2987    certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
   2988    
   2989    /* ensure we obtained a single usage bit only */
   2990    PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
   2991    
   2992    /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
   2993    while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
   2994 
   2995    /* check key usage and netscape cert type */
   2996    cert_GetCertType(cert->nssCert);
   2997    certType = cert->nssCert->nsCertType;
   2998    if (isChainCert ||
   2999        (certUsage != certUsageVerifyCA && certUsage != certUsageAnyCA)) {
   3000 rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, isChainCert,
   3001 				      &requiredKeyUsage,
   3002 				      &requiredCertType);
   3003        if (rv == SECFailure) {
   3004            PKIX_ERROR(PKIX_UNSUPPORTEDCERTUSAGE);
   3005        }
   3006    } else {
   3007        /* use this key usage and cert type for certUsageAnyCA and
   3008         * certUsageVerifyCA. */
   3009 requiredKeyUsage = KU_KEY_CERT_SIGN;
   3010 requiredCertType = NS_CERT_TYPE_CA;
   3011    }
   3012    if (CERT_CheckKeyUsage(cert->nssCert, requiredKeyUsage) != SECSuccess) {
   3013        PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
   3014    }
   3015    if (!(certType & requiredCertType)) {
   3016        PKIX_ERROR(PKIX_CERTCHECKCERTTYPEFAILED);
   3017    }
   3018 cleanup:
   3019    PKIX_DECREF(basicConstraints);
   3020    PKIX_RETURN(CERT);
   3021 }
   3022 
   3023 /*
   3024 * FUNCTION: PKIX_PL_Cert_VerifyKeyUsage (see comments in pkix_pl_pki.h)
   3025 */
   3026 PKIX_Error *
   3027 PKIX_PL_Cert_VerifyKeyUsage(
   3028        PKIX_PL_Cert *cert,
   3029        PKIX_UInt32 keyUsage,
   3030        void *plContext)
   3031 {
   3032        CERTCertificate *nssCert = NULL;
   3033        PKIX_UInt32 nssKeyUsage = 0;
   3034        SECStatus status;
   3035 
   3036        PKIX_ENTER(CERT, "PKIX_PL_Cert_VerifyKeyUsage");
   3037        PKIX_NULLCHECK_TWO(cert, cert->nssCert);
   3038 
   3039        nssCert = cert->nssCert;
   3040 
   3041        /* if cert doesn't have keyUsage extension, all keyUsages are valid */
   3042        if (!nssCert->keyUsagePresent){
   3043                goto cleanup;
   3044        }
   3045 
   3046        if (keyUsage & PKIX_DIGITAL_SIGNATURE){
   3047                nssKeyUsage = nssKeyUsage | KU_DIGITAL_SIGNATURE;
   3048        }
   3049 
   3050        if (keyUsage & PKIX_NON_REPUDIATION){
   3051                nssKeyUsage = nssKeyUsage | KU_NON_REPUDIATION;
   3052        }
   3053 
   3054        if (keyUsage & PKIX_KEY_ENCIPHERMENT){
   3055                nssKeyUsage = nssKeyUsage | KU_KEY_ENCIPHERMENT;
   3056        }
   3057 
   3058        if (keyUsage & PKIX_DATA_ENCIPHERMENT){
   3059                nssKeyUsage = nssKeyUsage | KU_DATA_ENCIPHERMENT;
   3060        }
   3061 
   3062        if (keyUsage & PKIX_KEY_AGREEMENT){
   3063                nssKeyUsage = nssKeyUsage | KU_KEY_AGREEMENT;
   3064        }
   3065 
   3066        if (keyUsage & PKIX_KEY_CERT_SIGN){
   3067                nssKeyUsage = nssKeyUsage | KU_KEY_CERT_SIGN;
   3068        }
   3069 
   3070        if (keyUsage & PKIX_CRL_SIGN){
   3071                nssKeyUsage = nssKeyUsage | KU_CRL_SIGN;
   3072        }
   3073 
   3074        if (keyUsage & PKIX_ENCIPHER_ONLY){
   3075                nssKeyUsage = nssKeyUsage | 0x01;
   3076        }
   3077 
   3078        if (keyUsage & PKIX_DECIPHER_ONLY){
   3079                /* XXX we should support this once it is fixed in NSS */
   3080                PKIX_ERROR(PKIX_DECIPHERONLYKEYUSAGENOTSUPPORTED);
   3081        }
   3082 
   3083        status = CERT_CheckKeyUsage(nssCert, nssKeyUsage);
   3084        if (status != SECSuccess) {
   3085                PKIX_ERROR(PKIX_CERTCHECKKEYUSAGEFAILED);
   3086        }
   3087 
   3088 cleanup:
   3089        PKIX_RETURN(CERT);
   3090 }
   3091 
   3092 /*
   3093 * FUNCTION: PKIX_PL_Cert_GetNameConstraints
   3094 * (see comments in pkix_pl_pki.h)
   3095 */
   3096 PKIX_Error *
   3097 PKIX_PL_Cert_GetNameConstraints(
   3098        PKIX_PL_Cert *cert,
   3099        PKIX_PL_CertNameConstraints **pNameConstraints,
   3100        void *plContext)
   3101 {
   3102        PKIX_PL_CertNameConstraints *nameConstraints = NULL;
   3103 
   3104        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNameConstraints");
   3105        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pNameConstraints);
   3106 
   3107        /* if we don't have a cached copy from before, we create one */
   3108        if (cert->nameConstraints == NULL && !cert->nameConstraintsAbsent) {
   3109 
   3110                PKIX_OBJECT_LOCK(cert);
   3111 
   3112                if (cert->nameConstraints == NULL &&
   3113                    !cert->nameConstraintsAbsent) {
   3114 
   3115                        PKIX_CHECK(pkix_pl_CertNameConstraints_Create
   3116                                (cert->nssCert, &nameConstraints, plContext),
   3117                                PKIX_CERTNAMECONSTRAINTSCREATEFAILED);
   3118 
   3119                        if (nameConstraints == NULL) {
   3120                                cert->nameConstraintsAbsent = PKIX_TRUE;
   3121                        }
   3122 
   3123                        cert->nameConstraints = nameConstraints;
   3124                }
   3125 
   3126                PKIX_OBJECT_UNLOCK(cert);
   3127 
   3128        }
   3129 
   3130        PKIX_INCREF(cert->nameConstraints);
   3131 
   3132        *pNameConstraints = cert->nameConstraints;
   3133 
   3134 cleanup:
   3135 PKIX_OBJECT_UNLOCK(lockedObject);
   3136        PKIX_RETURN(CERT);
   3137 }
   3138 
   3139 /*
   3140 * FUNCTION: PKIX_PL_Cert_CheckNameConstraints
   3141 * (see comments in pkix_pl_pki.h)
   3142 */
   3143 PKIX_Error *
   3144 PKIX_PL_Cert_CheckNameConstraints(
   3145        PKIX_PL_Cert *cert,
   3146        PKIX_PL_CertNameConstraints *nameConstraints,
   3147        PKIX_Boolean treatCommonNameAsDNSName,
   3148        void *plContext)
   3149 {
   3150        PKIX_Boolean checkPass = PKIX_TRUE;
   3151        CERTGeneralName *nssSubjectNames = NULL;
   3152        PLArenaPool *arena = NULL;
   3153 
   3154        PKIX_ENTER(CERT, "PKIX_PL_Cert_CheckNameConstraints");
   3155        PKIX_NULLCHECK_ONE(cert);
   3156 
   3157        if (nameConstraints != NULL) {
   3158 
   3159                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   3160                if (arena == NULL) {
   3161                        PKIX_ERROR(PKIX_OUTOFMEMORY);
   3162                }
   3163                /* only check common Name if the usage requires it */
   3164                if (treatCommonNameAsDNSName) {
   3165                    SECCertificateUsage certificateUsage;
   3166                    certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
   3167                    if ((certificateUsage != certificateUsageSSLServer) &&
   3168                        (certificateUsage != certificateUsageIPsec)) {
   3169                        treatCommonNameAsDNSName = PKIX_FALSE;
   3170                    }
   3171                }
   3172 
   3173                /* This NSS call returns Subject Alt Names. If
   3174                 * treatCommonNameAsDNSName is true, it also returns the
   3175                 * Subject Common Name
   3176                 */
   3177                PKIX_CERT_DEBUG
   3178                    ("\t\tCalling CERT_GetConstrainedCertificateNames\n");
   3179                nssSubjectNames = CERT_GetConstrainedCertificateNames
   3180                        (cert->nssCert, arena, treatCommonNameAsDNSName);
   3181 
   3182                PKIX_CHECK(pkix_pl_CertNameConstraints_CheckNameSpaceNssNames
   3183                        (nssSubjectNames,
   3184                        nameConstraints,
   3185                        &checkPass,
   3186                        plContext),
   3187                        PKIX_CERTNAMECONSTRAINTSCHECKNAMESPACENSSNAMESFAILED);
   3188 
   3189                if (checkPass != PKIX_TRUE) {
   3190                        PKIX_ERROR(PKIX_CERTFAILEDNAMECONSTRAINTSCHECKING);
   3191                }
   3192        }
   3193 
   3194 cleanup:
   3195        if (arena){
   3196                PORT_FreeArena(arena, PR_FALSE);
   3197        }
   3198 
   3199        PKIX_RETURN(CERT);
   3200 }
   3201 
   3202 /*
   3203 * FUNCTION: PKIX_PL_Cert_MergeNameConstraints
   3204 * (see comments in pkix_pl_pki.h)
   3205 */
   3206 PKIX_Error *
   3207 PKIX_PL_Cert_MergeNameConstraints(
   3208        PKIX_PL_CertNameConstraints *firstNC,
   3209        PKIX_PL_CertNameConstraints *secondNC,
   3210        PKIX_PL_CertNameConstraints **pResultNC,
   3211        void *plContext)
   3212 {
   3213        PKIX_PL_CertNameConstraints *mergedNC = NULL;
   3214 
   3215        PKIX_ENTER(CERT, "PKIX_PL_Cert_MergeNameConstraints");
   3216        PKIX_NULLCHECK_TWO(firstNC, pResultNC);
   3217 
   3218        if (secondNC == NULL) {
   3219 
   3220                PKIX_INCREF(firstNC);
   3221                *pResultNC = firstNC;
   3222 
   3223                goto cleanup;
   3224        }
   3225 
   3226        PKIX_CHECK(pkix_pl_CertNameConstraints_Merge
   3227                (firstNC, secondNC, &mergedNC, plContext),
   3228                PKIX_CERTNAMECONSTRAINTSMERGEFAILED);
   3229 
   3230        *pResultNC = mergedNC;
   3231 
   3232 cleanup:
   3233        PKIX_RETURN(CERT);
   3234 }
   3235 
   3236 /*
   3237 * Find out the state of the NSS trust bits for the requested usage.
   3238 * Returns SECFailure if the cert is explicitly distrusted.
   3239 * Returns SECSuccess if the cert can be used to form a chain (normal case),
   3240 *   or it is explicitly trusted. The trusted bool is set to true if it is
   3241 *   explicitly trusted.
   3242 */
   3243 static SECStatus
   3244 pkix_pl_Cert_GetTrusted(void *plContext,
   3245                        PKIX_PL_Cert *cert,
   3246                        PKIX_Boolean *trusted,
   3247                        PKIX_Boolean isCA)
   3248 {
   3249        SECStatus rv;
   3250        CERTCertificate *nssCert = NULL;
   3251        SECCertUsage certUsage = 0;
   3252        SECCertificateUsage certificateUsage;
   3253        SECTrustType trustType;
   3254        unsigned int trustFlags;
   3255        unsigned int requiredFlags;
   3256        CERTCertTrust trust;
   3257 
   3258        *trusted = PKIX_FALSE;
   3259 
   3260        /* no key usage information  */
   3261        if (plContext == NULL) {
   3262                return SECSuccess;
   3263        }
   3264 
   3265        certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
   3266 
   3267        /* ensure we obtained a single usage bit only */
   3268        PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
   3269 
   3270        /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
   3271        while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
   3272 
   3273        nssCert = cert->nssCert;
   3274 
   3275        if (!isCA) {
   3276                PRBool prTrusted;
   3277                unsigned int failedFlags;
   3278                rv = cert_CheckLeafTrust(nssCert, certUsage,
   3279                                         &failedFlags, &prTrusted);
   3280                *trusted = (PKIX_Boolean) prTrusted;
   3281                return rv;
   3282        }
   3283        rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
   3284                                           &trustType);
   3285        if (rv != SECSuccess) {
   3286                return SECSuccess;
   3287        }
   3288 
   3289        rv = CERT_GetCertTrust(nssCert, &trust);
   3290        if (rv != SECSuccess) {
   3291                return SECSuccess;
   3292        }
   3293        trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
   3294        /* normally trustTypeNone usages accept any of the given trust bits
   3295         * being on as acceptable. If any are distrusted (and none are trusted),
   3296         * then we will also distrust the cert */
   3297        if ((trustFlags == 0) && (trustType == trustTypeNone)) {
   3298                trustFlags = trust.sslFlags | trust.emailFlags |
   3299                             trust.objectSigningFlags;
   3300        }
   3301        if ((trustFlags & requiredFlags) == requiredFlags) {
   3302                *trusted = PKIX_TRUE;
   3303                return SECSuccess;
   3304        }
   3305        if ((trustFlags & CERTDB_TERMINAL_RECORD) &&
   3306            ((trustFlags & (CERTDB_VALID_CA|CERTDB_TRUSTED)) == 0)) {
   3307                return SECFailure;
   3308        }
   3309        return SECSuccess;
   3310 }
   3311 
   3312 /*
   3313 * FUNCTION: PKIX_PL_Cert_IsCertTrusted
   3314 * (see comments in pkix_pl_pki.h)
   3315 */
   3316 PKIX_Error *
   3317 PKIX_PL_Cert_IsCertTrusted(
   3318        PKIX_PL_Cert *cert,
   3319        PKIX_PL_TrustAnchorMode trustAnchorMode,
   3320        PKIX_Boolean *pTrusted,
   3321        void *plContext)
   3322 {
   3323        PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
   3324        PKIX_Boolean trusted = PKIX_FALSE;
   3325        SECStatus rv = SECFailure;
   3326 
   3327        PKIX_ENTER(CERT, "PKIX_PL_Cert_IsCertTrusted");
   3328        PKIX_NULLCHECK_TWO(cert, pTrusted);
   3329 
   3330        /* Call GetTrusted first to see if we are going to distrust the
   3331         * certificate */
   3332        rv = pkix_pl_Cert_GetTrusted(plContext, cert, &trusted, PKIX_TRUE);
   3333        if (rv != SECSuccess) {
   3334                /* Failure means the cert is explicitly distrusted,
   3335                 * let the next level know not to use it. */
   3336                *pTrusted = PKIX_FALSE;
   3337                PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
   3338        }
   3339 
   3340        if (trustAnchorMode == PKIX_PL_TrustAnchorMode_Exclusive ||
   3341            (trustAnchorMode == PKIX_PL_TrustAnchorMode_Additive &&
   3342             cert->isUserTrustAnchor)) {
   3343            /* Use the trust anchor's |trusted| value */
   3344            *pTrusted = cert->isUserTrustAnchor;
   3345            goto cleanup;
   3346        }
   3347 
   3348        /* no key usage information or store is not trusted */
   3349        if (plContext == NULL || cert->store == NULL) {
   3350                *pTrusted = PKIX_FALSE;
   3351                goto cleanup;
   3352        }
   3353 
   3354        PKIX_CHECK(PKIX_CertStore_GetTrustCallback
   3355                (cert->store, &trustCallback, plContext),
   3356                PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
   3357 
   3358        PKIX_CHECK_ONLY_FATAL(trustCallback
   3359                (cert->store, cert, &trusted, plContext),
   3360                PKIX_CHECKTRUSTCALLBACKFAILED);
   3361 
   3362        /* allow trust store to override if we can trust the trust
   3363         * bits */
   3364        if (PKIX_ERROR_RECEIVED || (trusted == PKIX_FALSE)) {
   3365                *pTrusted = PKIX_FALSE;
   3366                goto cleanup;
   3367        }
   3368 
   3369        *pTrusted = trusted;
   3370 
   3371 cleanup:
   3372        PKIX_RETURN(CERT);
   3373 }
   3374 
   3375 /*
   3376 * FUNCTION: PKIX_PL_Cert_IsLeafCertTrusted
   3377 * (see comments in pkix_pl_pki.h)
   3378 */
   3379 PKIX_Error *
   3380 PKIX_PL_Cert_IsLeafCertTrusted(
   3381        PKIX_PL_Cert *cert,
   3382        PKIX_Boolean *pTrusted,
   3383        void *plContext)
   3384 {
   3385        SECStatus rv;
   3386 
   3387        PKIX_ENTER(CERT, "PKIX_PL_Cert_IsLeafCertTrusted");
   3388        PKIX_NULLCHECK_TWO(cert, pTrusted);
   3389 
   3390        *pTrusted = PKIX_FALSE;
   3391 
   3392        rv = pkix_pl_Cert_GetTrusted(plContext, cert, pTrusted, PKIX_FALSE);
   3393        if (rv != SECSuccess) {
   3394                /* Failure means the cert is explicitly distrusted,
   3395                 * let the next level know not to use it. */
   3396                *pTrusted = PKIX_FALSE;
   3397                PKIX_ERROR(PKIX_CERTISCERTTRUSTEDFAILED);
   3398        }
   3399 
   3400 cleanup:
   3401        PKIX_RETURN(CERT);
   3402 }
   3403 
   3404 /* FUNCTION: PKIX_PL_Cert_SetAsTrustAnchor */
   3405 PKIX_Error*
   3406 PKIX_PL_Cert_SetAsTrustAnchor(PKIX_PL_Cert *cert, 
   3407                              void *plContext)
   3408 {
   3409    PKIX_ENTER(CERT, "PKIX_PL_Cert_SetAsTrustAnchor");
   3410    PKIX_NULLCHECK_ONE(cert);
   3411    
   3412    cert->isUserTrustAnchor = PKIX_TRUE;
   3413    
   3414    PKIX_RETURN(CERT);
   3415 }
   3416 
   3417 /*
   3418 * FUNCTION: PKIX_PL_Cert_GetCacheFlag (see comments in pkix_pl_pki.h)
   3419 */
   3420 PKIX_Error *
   3421 PKIX_PL_Cert_GetCacheFlag(
   3422        PKIX_PL_Cert *cert,
   3423        PKIX_Boolean *pCacheFlag,
   3424        void *plContext)
   3425 {
   3426        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCacheFlag");
   3427        PKIX_NULLCHECK_TWO(cert, pCacheFlag);
   3428 
   3429        *pCacheFlag = cert->cacheFlag;
   3430 
   3431        PKIX_RETURN(CERT);
   3432 }
   3433 
   3434 /*
   3435 * FUNCTION: PKIX_PL_Cert_SetCacheFlag (see comments in pkix_pl_pki.h)
   3436 */
   3437 PKIX_Error *
   3438 PKIX_PL_Cert_SetCacheFlag(
   3439        PKIX_PL_Cert *cert,
   3440        PKIX_Boolean cacheFlag,
   3441        void *plContext)
   3442 {
   3443        PKIX_ENTER(CERT, "PKIX_PL_Cert_SetCacheFlag");
   3444        PKIX_NULLCHECK_ONE(cert);
   3445 
   3446        cert->cacheFlag = cacheFlag;
   3447 
   3448        PKIX_RETURN(CERT);
   3449 }
   3450 
   3451 /*
   3452 * FUNCTION: PKIX_PL_Cert_GetTrustCertStore (see comments in pkix_pl_pki.h)
   3453 */
   3454 PKIX_Error *
   3455 PKIX_PL_Cert_GetTrustCertStore(
   3456        PKIX_PL_Cert *cert,
   3457        PKIX_CertStore **pTrustCertStore,
   3458        void *plContext)
   3459 {
   3460        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetTrustCertStore");
   3461        PKIX_NULLCHECK_TWO(cert, pTrustCertStore);
   3462 
   3463        PKIX_INCREF(cert->store);
   3464        *pTrustCertStore = cert->store;
   3465 
   3466 cleanup:
   3467        PKIX_RETURN(CERT);
   3468 }
   3469 
   3470 /*
   3471 * FUNCTION: PKIX_PL_Cert_SetTrustCertStore (see comments in pkix_pl_pki.h)
   3472 */
   3473 PKIX_Error *
   3474 PKIX_PL_Cert_SetTrustCertStore(
   3475        PKIX_PL_Cert *cert,
   3476        PKIX_CertStore *trustCertStore,
   3477        void *plContext)
   3478 {
   3479        PKIX_ENTER(CERT, "PKIX_PL_Cert_SetTrustCertStore");
   3480        PKIX_NULLCHECK_TWO(cert, trustCertStore);
   3481 
   3482        PKIX_INCREF(trustCertStore);
   3483        cert->store = trustCertStore;
   3484 
   3485 cleanup:
   3486        PKIX_RETURN(CERT);
   3487 }
   3488 
   3489 /*
   3490 * FUNCTION: PKIX_PL_Cert_GetAuthorityInfoAccess
   3491 * (see comments in pkix_pl_pki.h)
   3492 */
   3493 PKIX_Error *
   3494 PKIX_PL_Cert_GetAuthorityInfoAccess(
   3495        PKIX_PL_Cert *cert,
   3496        PKIX_List **pAiaList, /* of PKIX_PL_InfoAccess */
   3497        void *plContext)
   3498 {
   3499        PKIX_List *aiaList = NULL; /* of PKIX_PL_InfoAccess */
   3500        SECItem *encodedAIA = NULL;
   3501        CERTAuthInfoAccess **aia = NULL;
   3502        PLArenaPool *arena = NULL;
   3503        SECStatus rv;
   3504 
   3505        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetAuthorityInfoAccess");
   3506        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pAiaList);
   3507 
   3508        /* if we don't have a cached copy from before, we create one */
   3509        if (cert->authorityInfoAccess == NULL) {
   3510 
   3511                PKIX_OBJECT_LOCK(cert);
   3512 
   3513                if (cert->authorityInfoAccess == NULL) {
   3514 
   3515                    PKIX_PL_NSSCALLRV(CERT, encodedAIA, SECITEM_AllocItem,
   3516                        (NULL, NULL, 0));
   3517 
   3518                    if (encodedAIA == NULL) {
   3519                        PKIX_ERROR(PKIX_OUTOFMEMORY);
   3520                    }
   3521 
   3522                    PKIX_PL_NSSCALLRV(CERT, rv, CERT_FindCertExtension,
   3523                        (cert->nssCert,
   3524                        SEC_OID_X509_AUTH_INFO_ACCESS,
   3525                        encodedAIA));
   3526 
   3527                    if (rv == SECFailure) {
   3528                        goto cleanup;
   3529                    }
   3530 
   3531                    PKIX_PL_NSSCALLRV(CERT, arena, PORT_NewArena,
   3532                        (DER_DEFAULT_CHUNKSIZE));
   3533 
   3534                    if (arena == NULL) {
   3535                        PKIX_ERROR(PKIX_OUTOFMEMORY);
   3536                    }
   3537 
   3538                    PKIX_PL_NSSCALLRV
   3539                        (CERT, aia, CERT_DecodeAuthInfoAccessExtension,
   3540                        (arena, encodedAIA));
   3541 
   3542                    PKIX_CHECK(pkix_pl_InfoAccess_CreateList
   3543                        (aia, &aiaList, plContext),
   3544                        PKIX_INFOACCESSCREATELISTFAILED);
   3545 
   3546                    cert->authorityInfoAccess = aiaList;
   3547                }
   3548 
   3549                PKIX_OBJECT_UNLOCK(cert);
   3550        }
   3551 
   3552        PKIX_INCREF(cert->authorityInfoAccess);
   3553 
   3554        *pAiaList = cert->authorityInfoAccess;
   3555 
   3556 cleanup:
   3557 PKIX_OBJECT_UNLOCK(lockedObject);
   3558        if (arena != NULL) {
   3559                PORT_FreeArena(arena, PR_FALSE);
   3560        }
   3561 
   3562        if (encodedAIA != NULL) {
   3563                SECITEM_FreeItem(encodedAIA, PR_TRUE);
   3564        }
   3565 
   3566        PKIX_RETURN(CERT);
   3567 }
   3568 
   3569 /* XXX Following defines belongs to NSS */
   3570 static const unsigned char siaOIDString[] = {0x2b, 0x06, 0x01, 0x05, 0x05,
   3571                                0x07, 0x01, 0x0b};
   3572 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
   3573 
   3574 /*
   3575 * FUNCTION: PKIX_PL_Cert_GetSubjectInfoAccess
   3576 * (see comments in pkix_pl_pki.h)
   3577 */
   3578 PKIX_Error *
   3579 PKIX_PL_Cert_GetSubjectInfoAccess(
   3580        PKIX_PL_Cert *cert,
   3581        PKIX_List **pSiaList, /* of PKIX_PL_InfoAccess */
   3582        void *plContext)
   3583 {
   3584        PKIX_List *siaList; /* of PKIX_PL_InfoAccess */
   3585        SECItem siaOID = OI(siaOIDString);
   3586        SECItem *encodedSubjInfoAccess = NULL;
   3587        CERTAuthInfoAccess **subjInfoAccess = NULL;
   3588        PLArenaPool *arena = NULL;
   3589        SECStatus rv;
   3590 
   3591        PKIX_ENTER(CERT, "PKIX_PL_Cert_GetSubjectInfoAccess");
   3592        PKIX_NULLCHECK_THREE(cert, cert->nssCert, pSiaList);
   3593 
   3594        /* XXX
   3595         * Codes to deal with SubjectInfoAccess OID should be moved to
   3596         * NSS soon. I implemented them here so we don't touch NSS
   3597         * source tree, from JP's suggestion.
   3598         */
   3599 
   3600        /* if we don't have a cached copy from before, we create one */
   3601        if (cert->subjectInfoAccess == NULL) {
   3602 
   3603                PKIX_OBJECT_LOCK(cert);
   3604 
   3605                if (cert->subjectInfoAccess == NULL) {
   3606 
   3607                    encodedSubjInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
   3608                    if (encodedSubjInfoAccess == NULL) {
   3609                        PKIX_ERROR(PKIX_OUTOFMEMORY);
   3610                    }
   3611 
   3612                    PKIX_CERT_DEBUG
   3613                        ("\t\tCalling CERT_FindCertExtensionByOID).\n");
   3614                    rv = CERT_FindCertExtensionByOID
   3615                                (cert->nssCert, &siaOID, encodedSubjInfoAccess);
   3616 
   3617                    if (rv == SECFailure) {
   3618                        goto cleanup;
   3619                    }
   3620 
   3621                    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   3622                    if (arena == NULL) {
   3623                        PKIX_ERROR(PKIX_OUTOFMEMORY);
   3624                    }
   3625 
   3626                    /* XXX
   3627                     * Decode Subject Information Access -
   3628                     * since its type is the same as Authority Information
   3629                     * Access, reuse the call. NSS- change name to avoid
   3630                     * confusion.
   3631                     */
   3632                    PKIX_CERT_DEBUG
   3633                        ("\t\tCalling CERT_DecodeAuthInfoAccessExtension).\n");
   3634                    subjInfoAccess = CERT_DecodeAuthInfoAccessExtension
   3635                        (arena, encodedSubjInfoAccess);
   3636 
   3637                    PKIX_CHECK(pkix_pl_InfoAccess_CreateList
   3638                            (subjInfoAccess, &siaList, plContext),
   3639                            PKIX_INFOACCESSCREATELISTFAILED);
   3640 
   3641                    cert->subjectInfoAccess = siaList;
   3642 
   3643                }
   3644 
   3645                PKIX_OBJECT_UNLOCK(cert);
   3646        }
   3647 
   3648        PKIX_INCREF(cert->subjectInfoAccess);
   3649        *pSiaList = cert->subjectInfoAccess;
   3650 
   3651 cleanup:
   3652 PKIX_OBJECT_UNLOCK(lockedObject);
   3653        if (arena != NULL) {
   3654                PORT_FreeArena(arena, PR_FALSE);
   3655        }
   3656 
   3657        if (encodedSubjInfoAccess != NULL) {
   3658                SECITEM_FreeItem(encodedSubjInfoAccess, PR_TRUE);
   3659        }
   3660        PKIX_RETURN(CERT);
   3661 }
   3662 
   3663 /*
   3664 * FUNCTION: PKIX_PL_Cert_GetCrlDp
   3665 * (see comments in pkix_pl_pki.h)
   3666 */
   3667 PKIX_Error *
   3668 PKIX_PL_Cert_GetCrlDp(
   3669    PKIX_PL_Cert *cert,
   3670    PKIX_List **pDpList,
   3671    void *plContext)
   3672 {
   3673    PKIX_UInt32 dpIndex = 0;
   3674    pkix_pl_CrlDp *dp = NULL; 
   3675    CERTCrlDistributionPoints *dpoints = NULL;
   3676 
   3677    PKIX_ENTER(CERT, "PKIX_PL_Cert_GetCrlDp");
   3678    PKIX_NULLCHECK_THREE(cert, cert->nssCert, pDpList);
   3679                
   3680    /* if we don't have a cached copy from before, we create one */
   3681    if (cert->crldpList == NULL) {
   3682        PKIX_OBJECT_LOCK(cert);
   3683        if (cert->crldpList != NULL) {
   3684            goto cleanup;
   3685        }
   3686        PKIX_CHECK(PKIX_List_Create(&cert->crldpList, plContext),
   3687                   PKIX_LISTCREATEFAILED);
   3688        dpoints = CERT_FindCRLDistributionPoints(cert->nssCert);
   3689        if (!dpoints || !dpoints->distPoints) {
   3690            goto cleanup;
   3691        }
   3692        for (;dpoints->distPoints[dpIndex];dpIndex++) {
   3693            PKIX_CHECK(
   3694                pkix_pl_CrlDp_Create(dpoints->distPoints[dpIndex],
   3695                                     &cert->nssCert->issuer,
   3696                                     &dp, plContext),
   3697                PKIX_CRLDPCREATEFAILED);
   3698            /* Create crldp list in reverse order in attempt to get
   3699             * to the whole crl first. */
   3700            PKIX_CHECK(
   3701                PKIX_List_InsertItem(cert->crldpList, 0,
   3702                                     (PKIX_PL_Object*)dp,
   3703                                     plContext),
   3704                PKIX_LISTAPPENDITEMFAILED);
   3705            PKIX_DECREF(dp);
   3706        }
   3707    }
   3708 cleanup:
   3709    PKIX_INCREF(cert->crldpList);
   3710    *pDpList = cert->crldpList;
   3711 
   3712    PKIX_OBJECT_UNLOCK(lockedObject);
   3713    PKIX_DECREF(dp);
   3714 
   3715    PKIX_RETURN(CERT);
   3716 }
   3717 
   3718 /*
   3719 * FUNCTION: PKIX_PL_Cert_GetCERTCertificate
   3720 * (see comments in pkix_pl_pki.h)
   3721 */
   3722 PKIX_Error *
   3723 PKIX_PL_Cert_GetCERTCertificate(
   3724        PKIX_PL_Cert *cert,
   3725        CERTCertificate **pnssCert, 
   3726        void *plContext)
   3727 {
   3728    PKIX_ENTER(CERT, "PKIX_PL_Cert_GetNssCert");
   3729    PKIX_NULLCHECK_TWO(cert, pnssCert);
   3730 
   3731    *pnssCert = CERT_DupCertificate(cert->nssCert);
   3732 
   3733    PKIX_RETURN(CERT);
   3734 }