tor-browser

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

certvfy.c (77253B)


      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 #include "nspr.h"
      5 #include "secerr.h"
      6 #include "secport.h"
      7 #include "seccomon.h"
      8 #include "secoid.h"
      9 #include "genname.h"
     10 #include "keyhi.h"
     11 #include "cert.h"
     12 #include "certdb.h"
     13 #include "certi.h"
     14 #include "cryptohi.h"
     15 
     16 #ifndef NSS_DISABLE_LIBPKIX
     17 #include "pkix.h"
     18 #include "pkix_pl_cert.h"
     19 #else
     20 #include "nss.h"
     21 #endif /* NSS_DISABLE_LIBPKIX */
     22 
     23 #include "nsspki.h"
     24 #include "pkitm.h"
     25 #include "pkim.h"
     26 #include "pki3hack.h"
     27 #include "base.h"
     28 #include "keyi.h"
     29 
     30 /*
     31 * Check the validity times of a certificate
     32 */
     33 SECStatus
     34 CERT_CertTimesValid(CERTCertificate *c)
     35 {
     36    SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE);
     37    return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
     38 }
     39 
     40 static SECStatus
     41 checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
     42 {
     43    SECStatus rv;
     44    SECOidTag sigAlg;
     45    SECOidTag curve;
     46    PRUint32 policyFlags = 0;
     47    PRInt32 minLen, len, optFlags;
     48 
     49    sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
     50 
     51    switch (sigAlg) {
     52        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
     53        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
     54        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
     55        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
     56        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
     57            if (key->keyType != ecKey) {
     58                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
     59                return SECFailure;
     60            }
     61 
     62            curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams);
     63            if (curve != 0) {
     64                if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure ||
     65                    !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
     66                    PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
     67                    return SECFailure;
     68                }
     69                return SECSuccess;
     70            }
     71            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
     72            return SECFailure;
     73 
     74        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: {
     75            PORTCheapArenaPool tmpArena;
     76            SECOidTag hashAlg;
     77            SECOidTag maskHashAlg;
     78 
     79            PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
     80            rv = sec_DecodeRSAPSSParams(&tmpArena.arena,
     81                                        &sigAlgorithm->parameters,
     82                                        &hashAlg, &maskHashAlg, NULL);
     83            PORT_DestroyCheapArena(&tmpArena);
     84            if (rv != SECSuccess) {
     85                return SECFailure;
     86            }
     87 
     88            if (NSS_GetAlgorithmPolicy(hashAlg, &policyFlags) == SECSuccess &&
     89                !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
     90                PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
     91                return SECFailure;
     92            }
     93            if (NSS_GetAlgorithmPolicy(maskHashAlg, &policyFlags) == SECSuccess &&
     94                !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
     95                PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
     96                return SECFailure;
     97            }
     98        }
     99        /* fall through to RSA key checking */
    100        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
    101        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
    102        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
    103        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
    104        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
    105        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
    106        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
    107            if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
    108                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    109                return SECFailure;
    110            }
    111 
    112            if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
    113                return SECSuccess;
    114            }
    115            if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
    116                return SECSuccess;
    117            }
    118 
    119            len = 8 * key->u.rsa.modulus.len;
    120 
    121            rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen);
    122            if (rv != SECSuccess) {
    123                return SECFailure;
    124            }
    125 
    126            if (len < minLen) {
    127                return SECFailure;
    128            }
    129 
    130            return SECSuccess;
    131        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    132        case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
    133        case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
    134        case SEC_OID_SDN702_DSA_SIGNATURE:
    135        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
    136        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
    137            if (key->keyType != dsaKey) {
    138                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    139                return SECFailure;
    140            }
    141            if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) == SECFailure) {
    142                return SECSuccess;
    143            }
    144            if ((optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) == 0) {
    145                return SECSuccess;
    146            }
    147 
    148            len = 8 * key->u.dsa.params.prime.len;
    149 
    150            rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen);
    151            if (rv != SECSuccess) {
    152                return SECFailure;
    153            }
    154 
    155            if (len < minLen) {
    156                return SECFailure;
    157            }
    158 
    159            return SECSuccess;
    160        case SEC_OID_ML_DSA_44:
    161        case SEC_OID_ML_DSA_65:
    162        case SEC_OID_ML_DSA_87:
    163            if (key->keyType != mldsaKey) {
    164                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    165                return SECFailure;
    166            }
    167            if (key->u.mldsa.paramSet != sigAlg) {
    168                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
    169                return SECFailure;
    170            }
    171        default:
    172            return SECSuccess;
    173    }
    174 }
    175 
    176 /*
    177 * verify the signature of a signed data object with the given DER publickey
    178 */
    179 SECStatus
    180 CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
    181                                   SECKEYPublicKey *pubKey,
    182                                   void *wincx)
    183 {
    184    SECStatus rv;
    185    SECItem sig;
    186    SECOidTag sigAlg;
    187    SECOidTag encAlg;
    188    SECOidTag hashAlg;
    189    CK_MECHANISM_TYPE mech;
    190    PRUint32 policyFlags;
    191 
    192    if (!pubKey || !sd) {
    193        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
    194        return SECFailure;
    195    }
    196 
    197    /* Can we use this algorithm for signature verification?  */
    198    sigAlg = SECOID_GetAlgorithmTag(&sd->signatureAlgorithm);
    199    rv = sec_DecodeSigAlg(pubKey, sigAlg,
    200                          &sd->signatureAlgorithm.parameters,
    201                          &encAlg, &hashAlg, &mech, NULL);
    202    if (rv != SECSuccess) {
    203        return SECFailure; /* error is set */
    204    }
    205    rv = NSS_GetAlgorithmPolicy(encAlg, &policyFlags);
    206    if (rv == SECSuccess &&
    207        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
    208        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
    209        return SECFailure;
    210    }
    211    rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
    212    if (rv == SECSuccess &&
    213        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
    214        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
    215        return SECFailure;
    216    }
    217    rv = checkKeyParams(&sd->signatureAlgorithm, pubKey);
    218    if (rv != SECSuccess) {
    219        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
    220        return SECFailure;
    221    }
    222 
    223    /* check the signature */
    224    sig = sd->signature;
    225    /* convert sig->len from bit counts to byte count. */
    226    DER_ConvertBitString(&sig);
    227 
    228    rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
    229                                       &sig, &sd->signatureAlgorithm,
    230                                       &hashAlg, wincx);
    231    if (rv != SECSuccess) {
    232        return SECFailure; /* error is set */
    233    }
    234 
    235    /* for some algorithms, hash algorithm is only known after verification */
    236    rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
    237    if (rv == SECSuccess &&
    238        !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
    239        PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
    240        return SECFailure;
    241    }
    242    return SECSuccess;
    243 }
    244 
    245 /*
    246 * verify the signature of a signed data object with the given DER publickey
    247 */
    248 SECStatus
    249 CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd,
    250                                       CERTSubjectPublicKeyInfo *pubKeyInfo,
    251                                       void *wincx)
    252 {
    253    SECKEYPublicKey *pubKey;
    254    SECStatus rv = SECFailure;
    255 
    256    /* get cert's public key */
    257    pubKey = SECKEY_ExtractPublicKey(pubKeyInfo);
    258    if (pubKey) {
    259        rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
    260        SECKEY_DestroyPublicKey(pubKey);
    261    }
    262    return rv;
    263 }
    264 
    265 /*
    266 * verify the signature of a signed data object with the given certificate
    267 */
    268 SECStatus
    269 CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
    270                      PRTime t, void *wincx)
    271 {
    272    SECKEYPublicKey *pubKey = 0;
    273    SECStatus rv = SECFailure;
    274    SECCertTimeValidity validity;
    275 
    276    /* check the certificate's validity */
    277    validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
    278    if (validity != secCertTimeValid) {
    279        return rv;
    280    }
    281 
    282    /* get cert's public key */
    283    pubKey = CERT_ExtractPublicKey(cert);
    284    if (pubKey) {
    285        rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
    286        SECKEY_DestroyPublicKey(pubKey);
    287    }
    288    return rv;
    289 }
    290 
    291 SECStatus
    292 SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert,
    293             CERTCertificate *caCert, PRTime t, void *wincx)
    294 {
    295    return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
    296 }
    297 
    298 /*
    299 * Find the issuer of a cert.  Use the authorityKeyID if it exists.
    300 */
    301 CERTCertificate *
    302 CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage)
    303 {
    304    NSSCertificate *me;
    305    NSSTime *nssTime;
    306    NSSTrustDomain *td;
    307    NSSCryptoContext *cc;
    308    NSSCertificate *chain[3];
    309    NSSUsage nssUsage;
    310    PRStatus status;
    311 
    312    me = STAN_GetNSSCertificate(cert);
    313    if (!me) {
    314        PORT_SetError(SEC_ERROR_NO_MEMORY);
    315        return NULL;
    316    }
    317    nssTime = NSSTime_SetPRTime(NULL, validTime);
    318    nssUsage.anyUsage = PR_FALSE;
    319    nssUsage.nss3usage = usage;
    320    nssUsage.nss3lookingForCA = PR_TRUE;
    321    memset(chain, 0, 3 * sizeof(NSSCertificate *));
    322    td = STAN_GetDefaultTrustDomain();
    323    cc = STAN_GetDefaultCryptoContext();
    324    (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL,
    325                                    chain, 2, NULL, &status, td, cc);
    326    nss_ZFreeIf(nssTime);
    327    if (status == PR_SUCCESS) {
    328        PORT_Assert(me == chain[0]);
    329        /* if it's a root, the chain will only have one cert */
    330        if (!chain[1]) {
    331            /* already has a reference from the call to BuildChain */
    332            return cert;
    333        }
    334        NSSCertificate_Destroy(chain[0]);         /* the first cert in the chain */
    335        return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */
    336    }
    337    if (chain[0]) {
    338        PORT_Assert(me == chain[0]);
    339        NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
    340    }
    341    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
    342    return NULL;
    343 }
    344 
    345 /*
    346 * return required trust flags for various cert usages for CAs
    347 */
    348 SECStatus
    349 CERT_TrustFlagsForCACertUsage(SECCertUsage usage,
    350                              unsigned int *retFlags,
    351                              SECTrustType *retTrustType)
    352 {
    353    unsigned int requiredFlags;
    354    SECTrustType trustType;
    355 
    356    switch (usage) {
    357        case certUsageSSLClient:
    358            requiredFlags = CERTDB_TRUSTED_CLIENT_CA;
    359            trustType = trustSSL;
    360            break;
    361        case certUsageSSLServer:
    362        case certUsageSSLCA:
    363            requiredFlags = CERTDB_TRUSTED_CA;
    364            trustType = trustSSL;
    365            break;
    366        case certUsageIPsec:
    367            requiredFlags = CERTDB_TRUSTED_CA;
    368            trustType = trustSSL;
    369            break;
    370        case certUsageSSLServerWithStepUp:
    371            requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA;
    372            trustType = trustSSL;
    373            break;
    374        case certUsageEmailSigner:
    375        case certUsageEmailRecipient:
    376            requiredFlags = CERTDB_TRUSTED_CA;
    377            trustType = trustEmail;
    378            break;
    379        case certUsageObjectSigner:
    380            requiredFlags = CERTDB_TRUSTED_CA;
    381            trustType = trustObjectSigning;
    382            break;
    383        case certUsageVerifyCA:
    384        case certUsageAnyCA:
    385        case certUsageStatusResponder:
    386            requiredFlags = CERTDB_TRUSTED_CA;
    387            trustType = trustTypeNone;
    388            break;
    389        default:
    390            PORT_Assert(0);
    391            goto loser;
    392    }
    393    if (retFlags != NULL) {
    394        *retFlags = requiredFlags;
    395    }
    396    if (retTrustType != NULL) {
    397        *retTrustType = trustType;
    398    }
    399 
    400    return (SECSuccess);
    401 loser:
    402    return (SECFailure);
    403 }
    404 
    405 void
    406 cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
    407                    unsigned int depth, void *arg)
    408 {
    409    CERTVerifyLogNode *node, *tnode;
    410 
    411    PORT_Assert(log != NULL);
    412 
    413    node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena,
    414                                                sizeof(CERTVerifyLogNode));
    415    if (node != NULL) {
    416        node->cert = CERT_DupCertificate(cert);
    417        node->error = error;
    418        node->depth = depth;
    419        node->arg = arg;
    420 
    421        if (log->tail == NULL) {
    422            /* empty list */
    423            log->head = log->tail = node;
    424            node->prev = NULL;
    425            node->next = NULL;
    426        } else if (depth >= log->tail->depth) {
    427            /* add to tail */
    428            node->prev = log->tail;
    429            log->tail->next = node;
    430            log->tail = node;
    431            node->next = NULL;
    432        } else if (depth < log->head->depth) {
    433            /* add at head */
    434            node->prev = NULL;
    435            node->next = log->head;
    436            log->head->prev = node;
    437            log->head = node;
    438        } else {
    439            /* add in middle */
    440            tnode = log->tail;
    441            while (tnode != NULL) {
    442                if (depth >= tnode->depth) {
    443                    /* insert after tnode */
    444                    node->prev = tnode;
    445                    node->next = tnode->next;
    446                    tnode->next->prev = node;
    447                    tnode->next = node;
    448                    break;
    449                }
    450 
    451                tnode = tnode->prev;
    452            }
    453        }
    454 
    455        log->count++;
    456    }
    457    return;
    458 }
    459 
    460 #define EXIT_IF_NOT_LOGGING(log) \
    461    if (log == NULL) {           \
    462        goto loser;              \
    463    }
    464 
    465 #define LOG_ERROR_OR_EXIT(log, cert, depth, arg)               \
    466    if (log != NULL) {                                         \
    467        cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
    468                            (void *)(PRWord)arg);              \
    469    } else {                                                   \
    470        goto loser;                                            \
    471    }
    472 
    473 #define LOG_ERROR(log, cert, depth, arg)                       \
    474    if (log != NULL) {                                         \
    475        cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
    476                            (void *)(PRWord)arg);              \
    477    }
    478 
    479 /* /C=CN/O=WoSign CA Limited/CN=CA \xE6\xB2\x83\xE9\x80\x9A\xE6\xA0\xB9\xE8\xAF\x81\xE4\xB9\xA6
    480 * Using a consistent naming convention, this would actually be called
    481 * 'CA沃通根证书DN', but since GCC 6.2.1 apparently can't handle UTF-8
    482 * identifiers, this will have to do.
    483 */
    484 static const unsigned char CAWoSignRootDN[72] = {
    485    0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    486    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
    487    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
    488    0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03,
    489    0x0C, 0x12, 0x43, 0x41, 0x20, 0xE6, 0xB2, 0x83, 0xE9, 0x80, 0x9A, 0xE6, 0xA0,
    490    0xB9, 0xE8, 0xAF, 0x81, 0xE4, 0xB9, 0xA6
    491 };
    492 
    493 /* /C=CN/O=WoSign CA Limited/CN=CA WoSign ECC Root */
    494 static const unsigned char CAWoSignECCRootDN[72] = {
    495    0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    496    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
    497    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
    498    0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03,
    499    0x13, 0x12, 0x43, 0x41, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45,
    500    0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74
    501 };
    502 
    503 /* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign */
    504 static const unsigned char CertificationAuthorityofWoSignDN[87] = {
    505    0x30, 0x55, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    506    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
    507    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
    508    0x69, 0x74, 0x65, 0x64, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03,
    509    0x13, 0x21, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
    510    0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20,
    511    0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E
    512 };
    513 
    514 /* /C=CN/O=WoSign CA Limited/CN=Certification Authority of WoSign G2 */
    515 static const unsigned char CertificationAuthorityofWoSignG2DN[90] = {
    516    0x30, 0x58, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    517    0x43, 0x4E, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x11,
    518    0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x41, 0x20, 0x4C, 0x69, 0x6D,
    519    0x69, 0x74, 0x65, 0x64, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03,
    520    0x13, 0x24, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
    521    0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20,
    522    0x6F, 0x66, 0x20, 0x57, 0x6F, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47, 0x32
    523 };
    524 
    525 /* /C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority */
    526 static const unsigned char StartComCertificationAuthorityDN[127] = {
    527    0x30, 0x7D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    528    0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D,
    529    0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E,
    530    0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x22, 0x53, 0x65,
    531    0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20,
    532    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53,
    533    0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55,
    534    0x04, 0x03, 0x13, 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20,
    535    0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
    536    0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
    537 };
    538 
    539 /* /C=IL/O=StartCom Ltd./CN=StartCom Certification Authority G2 */
    540 static const unsigned char StartComCertificationAuthorityG2DN[85] = {
    541    0x30, 0x53, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    542    0x49, 0x4C, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D,
    543    0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x4C, 0x74, 0x64, 0x2E,
    544    0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x53, 0x74,
    545    0x61, 0x72, 0x74, 0x43, 0x6F, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
    546    0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
    547    0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32
    548 };
    549 
    550 struct DataAndLength {
    551    const unsigned char *data;
    552    PRUint32 len;
    553 };
    554 
    555 static const struct DataAndLength StartComAndWoSignDNs[] = {
    556    { CAWoSignRootDN,
    557      sizeof(CAWoSignRootDN) },
    558    { CAWoSignECCRootDN,
    559      sizeof(CAWoSignECCRootDN) },
    560    { CertificationAuthorityofWoSignDN,
    561      sizeof(CertificationAuthorityofWoSignDN) },
    562    { CertificationAuthorityofWoSignG2DN,
    563      sizeof(CertificationAuthorityofWoSignG2DN) },
    564    { StartComCertificationAuthorityDN,
    565      sizeof(StartComCertificationAuthorityDN) },
    566    { StartComCertificationAuthorityG2DN,
    567      sizeof(StartComCertificationAuthorityG2DN) },
    568 };
    569 
    570 static PRBool
    571 CertIsStartComOrWoSign(const CERTCertificate *cert)
    572 {
    573    int i;
    574    const struct DataAndLength *dn = StartComAndWoSignDNs;
    575 
    576    for (i = 0; i < sizeof(StartComAndWoSignDNs) / sizeof(struct DataAndLength); ++i, dn++) {
    577        if (cert->derSubject.len == dn->len &&
    578            memcmp(cert->derSubject.data, dn->data, dn->len) == 0) {
    579            return PR_TRUE;
    580        }
    581    }
    582    return PR_FALSE;
    583 }
    584 
    585 SECStatus
    586 isIssuerCertAllowedAtCertIssuanceTime(CERTCertificate *issuerCert,
    587                                      CERTCertificate *referenceCert)
    588 {
    589    if (!issuerCert || !referenceCert) {
    590        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    591        return SECFailure;
    592    }
    593 
    594    if (CertIsStartComOrWoSign(issuerCert)) {
    595        /* PRTime is microseconds since the epoch, whereas JS time is milliseconds.
    596         * (new Date("2016-10-21T00:00:00Z")).getTime() * 1000
    597         */
    598        static const PRTime OCTOBER_21_2016 = 1477008000000000;
    599 
    600        PRTime notBefore, notAfter;
    601        SECStatus rv;
    602 
    603        rv = CERT_GetCertTimes(referenceCert, &notBefore, &notAfter);
    604        if (rv != SECSuccess)
    605            return rv;
    606 
    607        if (notBefore > OCTOBER_21_2016) {
    608            return SECFailure;
    609        }
    610    }
    611 
    612    return SECSuccess;
    613 }
    614 
    615 static SECStatus
    616 cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert,
    617                        PRBool checkSig, PRBool *sigerror,
    618                        SECCertUsage certUsage, PRTime t, void *wincx,
    619                        CERTVerifyLog *log, PRBool *revoked)
    620 {
    621    SECTrustType trustType;
    622    CERTBasicConstraints basicConstraint;
    623    CERTCertificate *issuerCert = NULL;
    624    CERTCertificate *subjectCert = NULL;
    625    CERTCertificate *badCert = NULL;
    626    PRBool isca;
    627    SECStatus rv;
    628    SECStatus rvFinal = SECSuccess;
    629    int count;
    630    int currentPathLen = 0;
    631    int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
    632    unsigned int caCertType;
    633    unsigned int requiredCAKeyUsage;
    634    unsigned int requiredFlags;
    635    PLArenaPool *arena = NULL;
    636    CERTGeneralName *namesList = NULL;
    637    CERTCertificate **certsList = NULL;
    638    int certsListLen = 16;
    639    int namesCount = 0;
    640    PRBool subjectCertIsSelfIssued;
    641    CERTCertTrust issuerTrust;
    642 
    643    if (revoked) {
    644        *revoked = PR_FALSE;
    645    }
    646 
    647    if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
    648                                         &requiredCAKeyUsage,
    649                                         &caCertType) !=
    650        SECSuccess) {
    651        PORT_Assert(0);
    652        EXIT_IF_NOT_LOGGING(log);
    653        requiredCAKeyUsage = 0;
    654        caCertType = 0;
    655    }
    656 
    657    switch (certUsage) {
    658        case certUsageSSLClient:
    659        case certUsageSSLServer:
    660        case certUsageIPsec:
    661        case certUsageSSLCA:
    662        case certUsageSSLServerWithStepUp:
    663        case certUsageEmailSigner:
    664        case certUsageEmailRecipient:
    665        case certUsageObjectSigner:
    666        case certUsageVerifyCA:
    667        case certUsageAnyCA:
    668        case certUsageStatusResponder:
    669            if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
    670                                              &trustType) != SECSuccess) {
    671                PORT_Assert(0);
    672                EXIT_IF_NOT_LOGGING(log);
    673                /* XXX continuing with requiredFlags = 0 seems wrong.  It'll
    674                 * cause the following test to be true incorrectly:
    675                 *   flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType);
    676                 *   if (( flags & requiredFlags ) == requiredFlags) {
    677                 *       rv = rvFinal;
    678                 *       goto done;
    679                 *   }
    680                 * There are three other instances of this problem.
    681                 */
    682                requiredFlags = 0;
    683                trustType = trustSSL;
    684            }
    685            break;
    686        default:
    687            PORT_Assert(0);
    688            EXIT_IF_NOT_LOGGING(log);
    689            requiredFlags = 0;
    690            trustType = trustSSL; /* This used to be 0, but we need something
    691                                   * that matches the enumeration type.
    692                                   */
    693            caCertType = 0;
    694    }
    695 
    696    subjectCert = CERT_DupCertificate(cert);
    697    if (subjectCert == NULL) {
    698        goto loser;
    699    }
    700 
    701    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    702    if (arena == NULL) {
    703        goto loser;
    704    }
    705 
    706    certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
    707    if (certsList == NULL)
    708        goto loser;
    709 
    710    /* RFC 3280 says that the name constraints will apply to the names
    711    ** in the leaf (EE) cert, whether it is self issued or not, so
    712    ** we pretend that it is not.
    713    */
    714    subjectCertIsSelfIssued = PR_FALSE;
    715    for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) {
    716        PRBool validCAOverride = PR_FALSE;
    717 
    718        /* Construct a list of names for the current and all previous
    719         * certifcates (except leaf (EE) certs, root CAs, and self-issued
    720         * intermediate CAs) to be verified against the name constraints
    721         * extension of the issuer certificate.
    722         */
    723        if (subjectCertIsSelfIssued == PR_FALSE) {
    724            CERTGeneralName *subjectNameList;
    725            int subjectNameListLen;
    726            int i;
    727            PRBool getSubjectCN = (!count &&
    728                                   (certUsage == certUsageSSLServer || certUsage == certUsageIPsec));
    729            subjectNameList =
    730                CERT_GetConstrainedCertificateNames(subjectCert, arena,
    731                                                    getSubjectCN);
    732            if (!subjectNameList)
    733                goto loser;
    734            subjectNameListLen = CERT_GetNamesLength(subjectNameList);
    735            if (!subjectNameListLen)
    736                goto loser;
    737            if (certsListLen <= namesCount + subjectNameListLen) {
    738                CERTCertificate **tmpCertsList;
    739                certsListLen = (namesCount + subjectNameListLen) * 2;
    740                tmpCertsList =
    741                    (CERTCertificate **)PORT_Realloc(certsList,
    742                                                     certsListLen *
    743                                                         sizeof(CERTCertificate *));
    744                if (tmpCertsList == NULL) {
    745                    goto loser;
    746                }
    747                certsList = tmpCertsList;
    748            }
    749            for (i = 0; i < subjectNameListLen; i++) {
    750                certsList[namesCount + i] = subjectCert;
    751            }
    752            namesCount += subjectNameListLen;
    753            namesList = cert_CombineNamesLists(namesList, subjectNameList);
    754        }
    755 
    756        /* check if the cert has an unsupported critical extension */
    757        if (subjectCert->options.bits.hasUnsupportedCriticalExt) {
    758            PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
    759            LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
    760        }
    761 
    762        /* check that the signatureAlgorithm field of the certificate
    763         * matches the signature field of the tbsCertificate */
    764        if (SECOID_CompareAlgorithmID(
    765                &subjectCert->signatureWrap.signatureAlgorithm,
    766                &subjectCert->signature)) {
    767            PORT_SetError(SEC_ERROR_ALGORITHM_MISMATCH);
    768            LOG_ERROR(log, subjectCert, count, 0);
    769            goto loser;
    770        }
    771 
    772        /* find the certificate of the issuer */
    773        issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage);
    774        if (!issuerCert) {
    775            PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
    776            LOG_ERROR(log, subjectCert, count, 0);
    777            goto loser;
    778        }
    779 
    780        /* verify the signature on the cert */
    781        if (checkSig) {
    782            rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
    783                                       issuerCert, t, wincx);
    784 
    785            if (rv != SECSuccess) {
    786                if (sigerror) {
    787                    *sigerror = PR_TRUE;
    788                }
    789                if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) {
    790                    PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
    791                    LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
    792                } else {
    793                    if (PORT_GetError() !=
    794                        SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
    795                        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    796                    }
    797                    LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
    798                }
    799            }
    800        }
    801 
    802        /* If the basicConstraint extension is included in an immediate CA
    803         * certificate, make sure that the isCA flag is on.  If the
    804         * pathLenConstraint component exists, it must be greater than the
    805         * number of CA certificates we have seen so far.  If the extension
    806         * is omitted, we will assume that this is a CA certificate with
    807         * an unlimited pathLenConstraint (since it already passes the
    808         * netscape-cert-type extension checking).
    809         */
    810 
    811        rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint);
    812        if (rv != SECSuccess) {
    813            if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
    814                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
    815            }
    816            pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
    817            /* no basic constraints found, we aren't (yet) a CA. */
    818            isca = PR_FALSE;
    819        } else {
    820            if (basicConstraint.isCA == PR_FALSE) {
    821                PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
    822                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
    823            }
    824            pathLengthLimit = basicConstraint.pathLenConstraint;
    825            isca = PR_TRUE;
    826        }
    827        /* make sure that the path len constraint is properly set.*/
    828        if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) {
    829            PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
    830            LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit);
    831        }
    832 
    833        /* make sure that the entire chain is within the name space of the
    834         * current issuer certificate.
    835         */
    836        rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
    837                                   arena, &badCert);
    838        if (rv != SECSuccess || badCert != NULL) {
    839            PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
    840            LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
    841            goto loser;
    842        }
    843 
    844        rv = isIssuerCertAllowedAtCertIssuanceTime(issuerCert, cert);
    845        if (rv != SECSuccess) {
    846            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
    847            LOG_ERROR(log, issuerCert, count + 1, 0);
    848            goto loser;
    849        }
    850 
    851        /* XXX - the error logging may need to go down into CRL stuff at some
    852         * point
    853         */
    854        /* check revoked list (issuer) */
    855        rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
    856        if (rv == SECFailure) {
    857            if (revoked) {
    858                *revoked = PR_TRUE;
    859            }
    860            LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
    861        } else if (rv == SECWouldBlock) {
    862            /* We found something fishy, so we intend to issue an
    863             * error to the user, but the user may wish to continue
    864             * processing, in which case we better make sure nothing
    865             * worse has happened... so keep cranking the loop */
    866            rvFinal = SECFailure;
    867            if (revoked) {
    868                *revoked = PR_TRUE;
    869            }
    870            LOG_ERROR(log, subjectCert, count, 0);
    871        }
    872 
    873        if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) {
    874            /* we have some trust info, but this does NOT imply that this
    875             * cert is actually trusted for any purpose.  The cert may be
    876             * explicitly UNtrusted.  We won't know until we examine the
    877             * trust bits.
    878             */
    879            unsigned int flags;
    880 
    881            if (certUsage != certUsageAnyCA &&
    882                certUsage != certUsageStatusResponder) {
    883 
    884                /*
    885                 * XXX This choice of trustType seems arbitrary.
    886                 */
    887                if (certUsage == certUsageVerifyCA) {
    888                    if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
    889                        trustType = trustEmail;
    890                    } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
    891                        trustType = trustSSL;
    892                    } else {
    893                        trustType = trustObjectSigning;
    894                    }
    895                }
    896 
    897                flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
    898                if ((flags & requiredFlags) == requiredFlags) {
    899                    /* we found a trusted one, so return */
    900                    rv = rvFinal;
    901                    goto done;
    902                }
    903                if (flags & CERTDB_VALID_CA) {
    904                    validCAOverride = PR_TRUE;
    905                }
    906                /* is it explicitly distrusted? */
    907                if ((flags & CERTDB_TERMINAL_RECORD) &&
    908                    ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
    909                    /* untrusted -- the cert is explicitly untrusted, not
    910                     * just that it doesn't chain to a trusted cert */
    911                    PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
    912                    LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
    913                }
    914            } else {
    915                /* Check if we have any valid trust when cheching for
    916                 * certUsageAnyCA or certUsageStatusResponder. */
    917                for (trustType = trustSSL; trustType < trustTypeNone;
    918                     trustType++) {
    919                    flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
    920                    if ((flags & requiredFlags) == requiredFlags) {
    921                        rv = rvFinal;
    922                        goto done;
    923                    }
    924                    if (flags & CERTDB_VALID_CA)
    925                        validCAOverride = PR_TRUE;
    926                }
    927                /* We have 2 separate loops because we want any single trust
    928                 * bit to allow this usage to return trusted. Only if none of
    929                 * the trust bits are on do we check to see if the cert is
    930                 * untrusted */
    931                for (trustType = trustSSL; trustType < trustTypeNone;
    932                     trustType++) {
    933                    flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
    934                    /* is it explicitly distrusted? */
    935                    if ((flags & CERTDB_TERMINAL_RECORD) &&
    936                        ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
    937                        /* untrusted -- the cert is explicitly untrusted, not
    938                         * just that it doesn't chain to a trusted cert */
    939                        PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
    940                        LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
    941                    }
    942                }
    943            }
    944        }
    945 
    946        if (!validCAOverride) {
    947            /*
    948             * Make sure that if this is an intermediate CA in the chain that
    949             * it was given permission by its signer to be a CA.
    950             */
    951            /*
    952             * if basicConstraints says it is a ca, then we check the
    953             * nsCertType.  If the nsCertType has any CA bits set, then
    954             * it must have the right one.
    955             */
    956            if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
    957                isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
    958            }
    959 
    960            if (!isca) {
    961                PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
    962                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
    963            }
    964 
    965            /* make sure key usage allows cert signing */
    966            if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) {
    967                PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
    968                LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage);
    969            }
    970        }
    971 
    972        /* make sure that the issuer is not self signed.  If it is, then
    973         * stop here to prevent looping.
    974         */
    975        if (issuerCert->isRoot) {
    976            PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
    977            LOG_ERROR(log, issuerCert, count + 1, 0);
    978            goto loser;
    979        }
    980        /* The issuer cert will be the subject cert in the next loop.
    981         * A cert is self-issued if its subject and issuer are equal and
    982         * both are of non-zero length.
    983         */
    984        subjectCertIsSelfIssued = (PRBool)
    985                                      SECITEM_ItemsAreEqual(&issuerCert->derIssuer,
    986                                                            &issuerCert->derSubject) &&
    987                                  issuerCert->derSubject.len >
    988                                      0;
    989        if (subjectCertIsSelfIssued == PR_FALSE) {
    990            /* RFC 3280 says only non-self-issued intermediate CA certs
    991             * count in path length.
    992             */
    993            ++currentPathLen;
    994        }
    995 
    996        CERT_DestroyCertificate(subjectCert);
    997        subjectCert = issuerCert;
    998        issuerCert = NULL;
    999    }
   1000 
   1001    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
   1002    LOG_ERROR(log, subjectCert, count, 0);
   1003 loser:
   1004    rv = SECFailure;
   1005 done:
   1006    if (certsList != NULL) {
   1007        PORT_Free(certsList);
   1008    }
   1009    if (issuerCert) {
   1010        CERT_DestroyCertificate(issuerCert);
   1011    }
   1012 
   1013    if (subjectCert) {
   1014        CERT_DestroyCertificate(subjectCert);
   1015    }
   1016 
   1017    if (arena != NULL) {
   1018        PORT_FreeArena(arena, PR_FALSE);
   1019    }
   1020    return rv;
   1021 }
   1022 
   1023 SECStatus
   1024 cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
   1025                     PRBool checkSig, PRBool *sigerror,
   1026                     SECCertUsage certUsage, PRTime t, void *wincx,
   1027                     CERTVerifyLog *log, PRBool *revoked)
   1028 {
   1029    if (CERT_GetUsePKIXForValidation()) {
   1030        return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t,
   1031                                        wincx, log, sigerror, revoked);
   1032    }
   1033    return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror,
   1034                                   certUsage, t, wincx, log, revoked);
   1035 }
   1036 
   1037 SECStatus
   1038 CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
   1039                     PRBool checkSig, SECCertUsage certUsage, PRTime t,
   1040                     void *wincx, CERTVerifyLog *log)
   1041 {
   1042    return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t,
   1043                                wincx, log, NULL);
   1044 }
   1045 
   1046 /*
   1047 * verify that a CA can sign a certificate with the requested usage.
   1048 */
   1049 SECStatus
   1050 CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert,
   1051                          PRBool checkSig, SECCertUsage certUsage, PRTime t,
   1052                          void *wincx, CERTVerifyLog *log)
   1053 {
   1054    SECTrustType trustType;
   1055    CERTBasicConstraints basicConstraint;
   1056    PRBool isca;
   1057    PRBool validCAOverride = PR_FALSE;
   1058    SECStatus rv;
   1059    SECStatus rvFinal = SECSuccess;
   1060    unsigned int flags;
   1061    unsigned int caCertType;
   1062    unsigned int requiredCAKeyUsage;
   1063    unsigned int requiredFlags;
   1064    CERTCertificate *issuerCert;
   1065    CERTCertTrust certTrust;
   1066 
   1067    if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
   1068                                         &requiredCAKeyUsage,
   1069                                         &caCertType) != SECSuccess) {
   1070        PORT_Assert(0);
   1071        EXIT_IF_NOT_LOGGING(log);
   1072        requiredCAKeyUsage = 0;
   1073        caCertType = 0;
   1074    }
   1075 
   1076    switch (certUsage) {
   1077        case certUsageSSLClient:
   1078        case certUsageSSLServer:
   1079        case certUsageIPsec:
   1080        case certUsageSSLCA:
   1081        case certUsageSSLServerWithStepUp:
   1082        case certUsageEmailSigner:
   1083        case certUsageEmailRecipient:
   1084        case certUsageObjectSigner:
   1085        case certUsageVerifyCA:
   1086        case certUsageStatusResponder:
   1087            if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
   1088                                              &trustType) != SECSuccess) {
   1089                PORT_Assert(0);
   1090                EXIT_IF_NOT_LOGGING(log);
   1091                requiredFlags = 0;
   1092                trustType = trustSSL;
   1093            }
   1094            break;
   1095        default:
   1096            PORT_Assert(0);
   1097            EXIT_IF_NOT_LOGGING(log);
   1098            requiredFlags = 0;
   1099            trustType = trustSSL; /* This used to be 0, but we need something
   1100                                   * that matches the enumeration type.
   1101                                   */
   1102            caCertType = 0;
   1103    }
   1104 
   1105    /* If the basicConstraint extension is included in an intermmediate CA
   1106     * certificate, make sure that the isCA flag is on.  If the
   1107     * pathLenConstraint component exists, it must be greater than the
   1108     * number of CA certificates we have seen so far.  If the extension
   1109     * is omitted, we will assume that this is a CA certificate with
   1110     * an unlimited pathLenConstraint (since it already passes the
   1111     * netscape-cert-type extension checking).
   1112     */
   1113 
   1114    rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
   1115    if (rv != SECSuccess) {
   1116        if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
   1117            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
   1118        }
   1119        /* no basic constraints found, we aren't (yet) a CA. */
   1120        isca = PR_FALSE;
   1121    } else {
   1122        if (basicConstraint.isCA == PR_FALSE) {
   1123            PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
   1124            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
   1125        }
   1126 
   1127        /* can't check path length if we don't know the previous path */
   1128        isca = PR_TRUE;
   1129    }
   1130 
   1131    if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
   1132        /* we have some trust info, but this does NOT imply that this
   1133         * cert is actually trusted for any purpose.  The cert may be
   1134         * explicitly UNtrusted.  We won't know until we examine the
   1135         * trust bits.
   1136         */
   1137        if (certUsage == certUsageStatusResponder) {
   1138            /* Check the special case of certUsageStatusResponder */
   1139            issuerCert = CERT_FindCertIssuer(cert, t, certUsage);
   1140            if (issuerCert) {
   1141                if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) !=
   1142                    SECSuccess) {
   1143                    PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
   1144                    CERT_DestroyCertificate(issuerCert);
   1145                    goto loser;
   1146                }
   1147                CERT_DestroyCertificate(issuerCert);
   1148            }
   1149            /* XXX We have NOT determined that this cert is trusted.
   1150             * For years, NSS has treated this as trusted,
   1151             * but it seems incorrect.
   1152             */
   1153            rv = rvFinal;
   1154            goto done;
   1155        }
   1156 
   1157        /*
   1158         * check the trust params of the issuer
   1159         */
   1160        flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType);
   1161        if ((flags & requiredFlags) == requiredFlags) {
   1162            /* we found a trusted one, so return */
   1163            rv = rvFinal;
   1164            goto done;
   1165        }
   1166        if (flags & CERTDB_VALID_CA) {
   1167            validCAOverride = PR_TRUE;
   1168        }
   1169        /* is it explicitly distrusted? */
   1170        if ((flags & CERTDB_TERMINAL_RECORD) &&
   1171            ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
   1172            /* untrusted -- the cert is explicitly untrusted, not
   1173             * just that it doesn't chain to a trusted cert */
   1174            PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
   1175            LOG_ERROR_OR_EXIT(log, cert, 0, flags);
   1176        }
   1177    }
   1178    if (!validCAOverride) {
   1179        /*
   1180         * Make sure that if this is an intermediate CA in the chain that
   1181         * it was given permission by its signer to be a CA.
   1182         */
   1183        /*
   1184         * if basicConstraints says it is a ca, then we check the
   1185         * nsCertType.  If the nsCertType has any CA bits set, then
   1186         * it must have the right one.
   1187         */
   1188        if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) {
   1189            isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
   1190        }
   1191 
   1192        if (!isca) {
   1193            PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
   1194            LOG_ERROR_OR_EXIT(log, cert, 0, 0);
   1195        }
   1196 
   1197        /* make sure key usage allows cert signing */
   1198        if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) {
   1199            PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
   1200            LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage);
   1201        }
   1202    }
   1203    /* make sure that the issuer is not self signed.  If it is, then
   1204     * stop here to prevent looping.
   1205     */
   1206    if (cert->isRoot) {
   1207        PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
   1208        LOG_ERROR(log, cert, 0, 0);
   1209        goto loser;
   1210    }
   1211 
   1212    return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t,
   1213                                wincx, log);
   1214 loser:
   1215    rv = SECFailure;
   1216 done:
   1217    return rv;
   1218 }
   1219 
   1220 #define NEXT_USAGE() \
   1221    {                \
   1222        i *= 2;      \
   1223        certUsage++; \
   1224        continue;    \
   1225    }
   1226 
   1227 #define VALID_USAGE() \
   1228    {                 \
   1229        NEXT_USAGE(); \
   1230    }
   1231 
   1232 #define INVALID_USAGE()                 \
   1233    {                                   \
   1234        if (returnedUsages) {           \
   1235            *returnedUsages &= (~i);    \
   1236        }                               \
   1237        if (PR_TRUE == requiredUsage) { \
   1238            valid = SECFailure;         \
   1239        }                               \
   1240        NEXT_USAGE();                   \
   1241    }
   1242 
   1243 /*
   1244 * check the leaf cert against trust and usage.
   1245 *   returns success if the cert is not distrusted. If the cert is
   1246 *       trusted, then the trusted bool will be true.
   1247 *   returns failure if the cert is distrusted. If failure, flags
   1248 *       will return the flag bits that indicated distrust.
   1249 */
   1250 SECStatus
   1251 cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage,
   1252                    unsigned int *failedFlags, PRBool *trusted)
   1253 {
   1254    unsigned int flags;
   1255    CERTCertTrust trust;
   1256 
   1257    *failedFlags = 0;
   1258    *trusted = PR_FALSE;
   1259 
   1260    /* check trust flags to see if this cert is directly trusted */
   1261    if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
   1262        switch (certUsage) {
   1263            case certUsageSSLClient:
   1264            case certUsageSSLServer:
   1265            case certUsageIPsec:
   1266                flags = trust.sslFlags;
   1267 
   1268                /* is the cert directly trusted or not trusted ? */
   1269                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1270                                                       * authoritative */
   1271                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
   1272                        *trusted = PR_TRUE;
   1273                        return SECSuccess;
   1274                    } else { /* don't trust this cert */
   1275                        *failedFlags = flags;
   1276                        return SECFailure;
   1277                    }
   1278                }
   1279                break;
   1280            case certUsageSSLServerWithStepUp:
   1281                /* XXX - step up certs can't be directly trusted, only distrust */
   1282                flags = trust.sslFlags;
   1283                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1284                                                       * authoritative */
   1285                    if ((flags & CERTDB_TRUSTED) == 0) {
   1286                        /* don't trust this cert */
   1287                        *failedFlags = flags;
   1288                        return SECFailure;
   1289                    }
   1290                }
   1291                break;
   1292            case certUsageSSLCA:
   1293                flags = trust.sslFlags;
   1294                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1295                                                       * authoritative */
   1296                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
   1297                        /* don't trust this cert */
   1298                        *failedFlags = flags;
   1299                        return SECFailure;
   1300                    }
   1301                }
   1302                break;
   1303            case certUsageEmailSigner:
   1304            case certUsageEmailRecipient:
   1305                flags = trust.emailFlags;
   1306                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1307                                                       * authoritative */
   1308                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
   1309                        *trusted = PR_TRUE;
   1310                        return SECSuccess;
   1311                    } else { /* don't trust this cert */
   1312                        *failedFlags = flags;
   1313                        return SECFailure;
   1314                    }
   1315                }
   1316 
   1317                break;
   1318            case certUsageObjectSigner:
   1319                flags = trust.objectSigningFlags;
   1320 
   1321                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1322                                                       * authoritative */
   1323                    if (flags & CERTDB_TRUSTED) {     /* trust this cert */
   1324                        *trusted = PR_TRUE;
   1325                        return SECSuccess;
   1326                    } else { /* don't trust this cert */
   1327                        *failedFlags = flags;
   1328                        return SECFailure;
   1329                    }
   1330                }
   1331                break;
   1332            case certUsageVerifyCA:
   1333            case certUsageStatusResponder:
   1334                flags = trust.sslFlags;
   1335                /* is the cert directly trusted or not trusted ? */
   1336                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
   1337                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
   1338                    *trusted = PR_TRUE;
   1339                    return SECSuccess;
   1340                }
   1341                flags = trust.emailFlags;
   1342                /* is the cert directly trusted or not trusted ? */
   1343                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
   1344                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
   1345                    *trusted = PR_TRUE;
   1346                    return SECSuccess;
   1347                }
   1348                flags = trust.objectSigningFlags;
   1349                /* is the cert directly trusted or not trusted ? */
   1350                if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
   1351                    (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
   1352                    *trusted = PR_TRUE;
   1353                    return SECSuccess;
   1354                }
   1355            /* fall through to test distrust */
   1356            case certUsageAnyCA:
   1357            case certUsageUserCertImport:
   1358                /* do we distrust these certs explicitly */
   1359                flags = trust.sslFlags;
   1360                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1361                                                       * authoritative */
   1362                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
   1363                        *failedFlags = flags;
   1364                        return SECFailure;
   1365                    }
   1366                }
   1367                flags = trust.emailFlags;
   1368                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1369                                                       * authoritative */
   1370                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
   1371                        *failedFlags = flags;
   1372                        return SECFailure;
   1373                    }
   1374                }
   1375            /* fall through */
   1376            case certUsageProtectedObjectSigner:
   1377                flags = trust.objectSigningFlags;
   1378                if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
   1379                                                       * authoritative */
   1380                    if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
   1381                        *failedFlags = flags;
   1382                        return SECFailure;
   1383                    }
   1384                }
   1385                break;
   1386        }
   1387    }
   1388    return SECSuccess;
   1389 }
   1390 
   1391 /*
   1392 * verify a certificate by checking if it's valid and that we
   1393 * trust the issuer.
   1394 *
   1395 * certificateUsage contains a bitfield of all cert usages that are
   1396 * required for verification to succeed
   1397 *
   1398 * a bitfield of cert usages is returned in *returnedUsages
   1399 * if requiredUsages is non-zero, the returned bitmap is only
   1400 * for those required usages, otherwise it is for all usages
   1401 *
   1402 */
   1403 SECStatus
   1404 CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
   1405                       PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t,
   1406                       void *wincx, CERTVerifyLog *log, SECCertificateUsage *returnedUsages)
   1407 {
   1408    SECStatus rv;
   1409    SECStatus valid;
   1410    unsigned int requiredKeyUsage;
   1411    unsigned int requiredCertType;
   1412    unsigned int flags;
   1413    unsigned int certType;
   1414    PRBool allowOverride;
   1415    SECCertTimeValidity validity;
   1416    CERTStatusConfig *statusConfig;
   1417    PRInt32 i;
   1418    SECCertUsage certUsage = 0;
   1419    PRBool checkedOCSP = PR_FALSE;
   1420    PRBool checkAllUsages = PR_FALSE;
   1421    PRBool revoked = PR_FALSE;
   1422    PRBool sigerror = PR_FALSE;
   1423    PRBool trusted = PR_FALSE;
   1424 
   1425    if (!requiredUsages) {
   1426        /* there are no required usages, so the user probably wants to
   1427           get status for all usages */
   1428        checkAllUsages = PR_TRUE;
   1429    }
   1430 
   1431    if (returnedUsages) {
   1432        *returnedUsages = 0;
   1433    } else {
   1434        /* we don't have a place to return status for all usages,
   1435           so we can skip checks for usages that aren't required */
   1436        checkAllUsages = PR_FALSE;
   1437    }
   1438    valid = SECSuccess; /* start off assuming cert is valid */
   1439 
   1440    /* make sure that the cert is valid at time t */
   1441    allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) ||
   1442                             (requiredUsages & certificateUsageSSLServerWithStepUp) ||
   1443                             (requiredUsages & certificateUsageIPsec));
   1444    validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
   1445    if (validity != secCertTimeValid) {
   1446        valid = SECFailure;
   1447        LOG_ERROR_OR_EXIT(log, cert, 0, validity);
   1448    }
   1449 
   1450    /* check key usage and netscape cert type */
   1451    cert_GetCertType(cert);
   1452    certType = cert->nsCertType;
   1453 
   1454    for (i = 1; i <= certificateUsageHighest &&
   1455                (SECSuccess == valid || returnedUsages || log);) {
   1456        PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
   1457        if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
   1458            NEXT_USAGE();
   1459        }
   1460        if (returnedUsages) {
   1461            *returnedUsages |= i; /* start off assuming this usage is valid */
   1462        }
   1463        switch (certUsage) {
   1464            case certUsageSSLClient:
   1465            case certUsageSSLServer:
   1466            case certUsageSSLServerWithStepUp:
   1467            case certUsageSSLCA:
   1468            case certUsageEmailSigner:
   1469            case certUsageEmailRecipient:
   1470            case certUsageObjectSigner:
   1471            case certUsageStatusResponder:
   1472            case certUsageIPsec:
   1473                rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
   1474                                                      &requiredKeyUsage,
   1475                                                      &requiredCertType);
   1476                if (rv != SECSuccess) {
   1477                    PORT_Assert(0);
   1478                    /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
   1479                    requiredKeyUsage = 0;
   1480                    requiredCertType = 0;
   1481                    INVALID_USAGE();
   1482                }
   1483                break;
   1484 
   1485            case certUsageAnyCA:
   1486            case certUsageProtectedObjectSigner:
   1487            case certUsageUserCertImport:
   1488            case certUsageVerifyCA:
   1489                /* these usages cannot be verified */
   1490                NEXT_USAGE();
   1491 
   1492            default:
   1493                PORT_Assert(0);
   1494                requiredKeyUsage = 0;
   1495                requiredCertType = 0;
   1496                INVALID_USAGE();
   1497        }
   1498        if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
   1499            if (PR_TRUE == requiredUsage) {
   1500                PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
   1501            }
   1502            LOG_ERROR(log, cert, 0, requiredKeyUsage);
   1503            INVALID_USAGE();
   1504        }
   1505        if (!(certType & requiredCertType)) {
   1506            if (PR_TRUE == requiredUsage) {
   1507                PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
   1508            }
   1509            LOG_ERROR(log, cert, 0, requiredCertType);
   1510            INVALID_USAGE();
   1511        }
   1512 
   1513        rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
   1514        if (rv == SECFailure) {
   1515            if (PR_TRUE == requiredUsage) {
   1516                PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
   1517            }
   1518            LOG_ERROR(log, cert, 0, flags);
   1519            INVALID_USAGE();
   1520        } else if (trusted) {
   1521            VALID_USAGE();
   1522        }
   1523 
   1524        if (PR_TRUE == revoked || PR_TRUE == sigerror) {
   1525            INVALID_USAGE();
   1526        }
   1527 
   1528        rv = cert_VerifyCertChain(handle, cert,
   1529                                  checkSig, &sigerror,
   1530                                  certUsage, t, wincx, log,
   1531                                  &revoked);
   1532 
   1533        if (rv != SECSuccess) {
   1534            /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
   1535            INVALID_USAGE();
   1536        }
   1537 
   1538        /*
   1539         * Check OCSP revocation status, but only if the cert we are checking
   1540         * is not a status responder itself. We only do this in the case
   1541         * where we checked the cert chain (above); explicit trust "wins"
   1542         * (avoids status checking, just as it avoids CRL checking) by
   1543         * bypassing this code.
   1544         */
   1545 
   1546        if (PR_FALSE == checkedOCSP) {
   1547            checkedOCSP = PR_TRUE; /* only check OCSP once */
   1548            statusConfig = CERT_GetStatusConfig(handle);
   1549            if (requiredUsages != certificateUsageStatusResponder &&
   1550                statusConfig != NULL) {
   1551                if (statusConfig->statusChecker != NULL) {
   1552                    rv = (*statusConfig->statusChecker)(handle, cert,
   1553                                                        t, wincx);
   1554                    if (rv != SECSuccess) {
   1555                        LOG_ERROR(log, cert, 0, 0);
   1556                        revoked = PR_TRUE;
   1557                        INVALID_USAGE();
   1558                    }
   1559                }
   1560            }
   1561        }
   1562 
   1563        NEXT_USAGE();
   1564    }
   1565 
   1566 loser:
   1567    return (valid);
   1568 }
   1569 
   1570 SECStatus
   1571 CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
   1572                PRBool checkSig, SECCertUsage certUsage, PRTime t,
   1573                void *wincx, CERTVerifyLog *log)
   1574 {
   1575    return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
   1576                                    CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
   1577 }
   1578 
   1579 SECStatus
   1580 cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
   1581                         PRBool checkSig, SECCertUsage certUsage, PRTime t,
   1582                         PRUint32 flags, void *wincx, CERTVerifyLog *log)
   1583 {
   1584    SECStatus rv;
   1585    unsigned int requiredKeyUsage;
   1586    unsigned int requiredCertType;
   1587    unsigned int failedFlags;
   1588    unsigned int certType;
   1589    PRBool trusted;
   1590    PRBool allowOverride;
   1591    SECCertTimeValidity validity;
   1592    CERTStatusConfig *statusConfig;
   1593 
   1594 #ifdef notdef
   1595    /* check if this cert is in the Evil list */
   1596    rv = CERT_CheckForEvilCert(cert);
   1597    if (rv != SECSuccess) {
   1598        PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
   1599        LOG_ERROR_OR_EXIT(log, cert, 0, 0);
   1600    }
   1601 #endif
   1602 
   1603    /* make sure that the cert is valid at time t */
   1604    allowOverride = (PRBool)((certUsage == certUsageSSLServer) ||
   1605                             (certUsage == certUsageSSLServerWithStepUp) ||
   1606                             (certUsage == certUsageIPsec));
   1607    validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
   1608    if (validity != secCertTimeValid) {
   1609        LOG_ERROR_OR_EXIT(log, cert, 0, validity);
   1610    }
   1611 
   1612    /* check key usage and netscape cert type */
   1613    cert_GetCertType(cert);
   1614    certType = cert->nsCertType;
   1615    switch (certUsage) {
   1616        case certUsageSSLClient:
   1617        case certUsageSSLServer:
   1618        case certUsageSSLServerWithStepUp:
   1619        case certUsageIPsec:
   1620        case certUsageSSLCA:
   1621        case certUsageEmailSigner:
   1622        case certUsageEmailRecipient:
   1623        case certUsageObjectSigner:
   1624        case certUsageStatusResponder:
   1625            rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
   1626                                                  &requiredKeyUsage,
   1627                                                  &requiredCertType);
   1628            if (rv != SECSuccess) {
   1629                PORT_Assert(0);
   1630                EXIT_IF_NOT_LOGGING(log);
   1631                requiredKeyUsage = 0;
   1632                requiredCertType = 0;
   1633            }
   1634            break;
   1635        case certUsageVerifyCA:
   1636        case certUsageAnyCA:
   1637            requiredKeyUsage = KU_KEY_CERT_SIGN;
   1638            requiredCertType = NS_CERT_TYPE_CA;
   1639            if (!(certType & NS_CERT_TYPE_CA)) {
   1640                certType |= NS_CERT_TYPE_CA;
   1641            }
   1642            break;
   1643        default:
   1644            PORT_Assert(0);
   1645            EXIT_IF_NOT_LOGGING(log);
   1646            requiredKeyUsage = 0;
   1647            requiredCertType = 0;
   1648    }
   1649    if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
   1650        PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
   1651        LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage);
   1652    }
   1653    if (!(certType & requiredCertType)) {
   1654        PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
   1655        LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType);
   1656    }
   1657 
   1658    rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
   1659    if (rv == SECFailure) {
   1660        PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
   1661        LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
   1662    } else if (trusted) {
   1663        goto done;
   1664    }
   1665 
   1666    rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
   1667                              t, wincx, log);
   1668    if (rv != SECSuccess) {
   1669        EXIT_IF_NOT_LOGGING(log);
   1670    }
   1671 
   1672    /*
   1673     * Check revocation status, but only if the cert we are checking is not a
   1674     * status responder itself and the caller did not ask us to skip the check.
   1675     * We only do this in the case where we checked the cert chain (above);
   1676     * explicit trust "wins" (avoids status checking, just as it avoids CRL
   1677     * checking, which is all done inside VerifyCertChain) by bypassing this
   1678     * code.
   1679     */
   1680    if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
   1681        certUsage != certUsageStatusResponder) {
   1682        statusConfig = CERT_GetStatusConfig(handle);
   1683        if (statusConfig && statusConfig->statusChecker) {
   1684            rv = (*statusConfig->statusChecker)(handle, cert,
   1685                                                t, wincx);
   1686            if (rv != SECSuccess) {
   1687                LOG_ERROR_OR_EXIT(log, cert, 0, 0);
   1688            }
   1689        }
   1690    }
   1691 
   1692 done:
   1693    if (log && log->head) {
   1694        return SECFailure;
   1695    }
   1696    return (SECSuccess);
   1697 
   1698 loser:
   1699    rv = SECFailure;
   1700 
   1701    return (rv);
   1702 }
   1703 
   1704 /*
   1705 * verify a certificate by checking if its valid and that we
   1706 * trust the issuer.  Verify time against now.
   1707 */
   1708 SECStatus
   1709 CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert,
   1710                          PRBool checkSig, SECCertificateUsage requiredUsages,
   1711                          void *wincx, SECCertificateUsage *returnedUsages)
   1712 {
   1713    return (CERT_VerifyCertificate(handle, cert, checkSig,
   1714                                   requiredUsages, PR_Now(), wincx, NULL, returnedUsages));
   1715 }
   1716 
   1717 /* obsolete, do not use for new code */
   1718 SECStatus
   1719 CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
   1720                   PRBool checkSig, SECCertUsage certUsage, void *wincx)
   1721 {
   1722    return (CERT_VerifyCert(handle, cert, checkSig,
   1723                            certUsage, PR_Now(), wincx, NULL));
   1724 }
   1725 
   1726 /* [ FROM pcertdb.c ] */
   1727 /*
   1728 * Supported usage values and types:
   1729 *  certUsageSSLClient
   1730 *  certUsageSSLServer
   1731 *  certUsageSSLServerWithStepUp
   1732 *  certUsageIPsec
   1733 *  certUsageEmailSigner
   1734 *  certUsageEmailRecipient
   1735 *  certUsageObjectSigner
   1736 */
   1737 
   1738 CERTCertificate *
   1739 CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
   1740                      CERTCertOwner owner, SECCertUsage usage,
   1741                      PRBool preferTrusted, PRTime validTime, PRBool validOnly)
   1742 {
   1743    CERTCertList *certList = NULL;
   1744    CERTCertificate *cert = NULL;
   1745    CERTCertTrust certTrust;
   1746    unsigned int requiredTrustFlags;
   1747    SECTrustType requiredTrustType;
   1748    unsigned int flags;
   1749 
   1750    PRBool lookingForCA = PR_FALSE;
   1751    SECStatus rv;
   1752    CERTCertListNode *node;
   1753    CERTCertificate *saveUntrustedCA = NULL;
   1754 
   1755    /* if preferTrusted is set, must be a CA cert */
   1756    PORT_Assert(!(preferTrusted && (owner != certOwnerCA)));
   1757 
   1758    if (owner == certOwnerCA) {
   1759        lookingForCA = PR_TRUE;
   1760        if (preferTrusted) {
   1761            rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags,
   1762                                               &requiredTrustType);
   1763            if (rv != SECSuccess) {
   1764                goto loser;
   1765            }
   1766            requiredTrustFlags |= CERTDB_VALID_CA;
   1767        }
   1768    }
   1769 
   1770    certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime,
   1771                                          validOnly);
   1772    if (certList != NULL) {
   1773        rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA);
   1774        if (rv != SECSuccess) {
   1775            goto loser;
   1776        }
   1777 
   1778        node = CERT_LIST_HEAD(certList);
   1779 
   1780        while (!CERT_LIST_END(node, certList)) {
   1781            cert = node->cert;
   1782 
   1783            /* looking for a trusted CA cert */
   1784            if ((owner == certOwnerCA) && preferTrusted &&
   1785                (requiredTrustType != trustTypeNone)) {
   1786 
   1787                if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) {
   1788                    flags = 0;
   1789                } else {
   1790                    flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
   1791                }
   1792 
   1793                if ((flags & requiredTrustFlags) != requiredTrustFlags) {
   1794                    /* cert is not trusted */
   1795                    /* if this is the first cert to get this far, then save
   1796                     * it, so we can use it if we can't find a trusted one
   1797                     */
   1798                    if (saveUntrustedCA == NULL) {
   1799                        saveUntrustedCA = cert;
   1800                    }
   1801                    goto endloop;
   1802                }
   1803            }
   1804            /* if we got this far, then this cert meets all criteria */
   1805            break;
   1806 
   1807        endloop:
   1808            node = CERT_LIST_NEXT(node);
   1809            cert = NULL;
   1810        }
   1811 
   1812        /* use the saved one if we have it */
   1813        if (cert == NULL) {
   1814            cert = saveUntrustedCA;
   1815        }
   1816 
   1817        /* if we found one then bump the ref count before freeing the list */
   1818        if (cert != NULL) {
   1819            /* bump the ref count */
   1820            cert = CERT_DupCertificate(cert);
   1821        }
   1822 
   1823        CERT_DestroyCertList(certList);
   1824    }
   1825 
   1826    return (cert);
   1827 
   1828 loser:
   1829    if (certList != NULL) {
   1830        CERT_DestroyCertList(certList);
   1831    }
   1832 
   1833    return (NULL);
   1834 }
   1835 
   1836 /* [ From certdb.c ] */
   1837 /*
   1838 * Filter a list of certificates, removing those certs that do not have
   1839 * one of the named CA certs somewhere in their cert chain.
   1840 *
   1841 *  "certList" - the list of certificates to filter
   1842 *  "nCANames" - number of CA names
   1843 *  "caNames" - array of CA names in string(rfc 1485) form
   1844 *  "usage" - what use the certs are for, this is used when
   1845 *      selecting CA certs
   1846 */
   1847 SECStatus
   1848 CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
   1849                             char **caNames, SECCertUsage usage)
   1850 {
   1851    CERTCertificate *issuerCert = NULL;
   1852    CERTCertificate *subjectCert;
   1853    CERTCertListNode *node, *freenode;
   1854    CERTCertificate *cert;
   1855    int n;
   1856    char **names;
   1857    PRBool found;
   1858    PRTime time;
   1859 
   1860    if (nCANames <= 0) {
   1861        return (SECSuccess);
   1862    }
   1863 
   1864    time = PR_Now();
   1865 
   1866    node = CERT_LIST_HEAD(certList);
   1867 
   1868    while (!CERT_LIST_END(node, certList)) {
   1869        cert = node->cert;
   1870 
   1871        subjectCert = CERT_DupCertificate(cert);
   1872 
   1873        /* traverse the CA certs for this cert */
   1874        found = PR_FALSE;
   1875        while (subjectCert != NULL) {
   1876            n = nCANames;
   1877            names = caNames;
   1878 
   1879            if (subjectCert->issuerName != NULL) {
   1880                while (n > 0) {
   1881                    if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) {
   1882                        found = PR_TRUE;
   1883                        break;
   1884                    }
   1885 
   1886                    n--;
   1887                    names++;
   1888                }
   1889            }
   1890 
   1891            if (found) {
   1892                break;
   1893            }
   1894 
   1895            issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
   1896            if (issuerCert == subjectCert) {
   1897                CERT_DestroyCertificate(issuerCert);
   1898                issuerCert = NULL;
   1899                break;
   1900            }
   1901            CERT_DestroyCertificate(subjectCert);
   1902            subjectCert = issuerCert;
   1903        }
   1904        CERT_DestroyCertificate(subjectCert);
   1905        if (!found) {
   1906            /* CA was not found, so remove this cert from the list */
   1907            freenode = node;
   1908            node = CERT_LIST_NEXT(node);
   1909            CERT_RemoveCertListNode(freenode);
   1910        } else {
   1911            /* CA was found, so leave it in the list */
   1912            node = CERT_LIST_NEXT(node);
   1913        }
   1914    }
   1915 
   1916    return (SECSuccess);
   1917 }
   1918 
   1919 /*
   1920 * Given a certificate, return a string containing the nickname, and possibly
   1921 * one of the validity strings, based on the current validity state of the
   1922 * certificate.
   1923 *
   1924 * "arena" - arena to allocate returned string from.  If NULL, then heap
   1925 *  is used.
   1926 * "cert" - the cert to get nickname from
   1927 * "expiredString" - the string to append to the nickname if the cert is
   1928 *      expired.
   1929 * "notYetGoodString" - the string to append to the nickname if the cert is
   1930 *      not yet good.
   1931 */
   1932 char *
   1933 CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert,
   1934                                 char *expiredString, char *notYetGoodString)
   1935 {
   1936    SECCertTimeValidity validity;
   1937    char *nickname = NULL, *tmpstr = NULL;
   1938    const char *srcNickname = cert->nickname;
   1939    if (!srcNickname) {
   1940        srcNickname = "{???}";
   1941    }
   1942 
   1943    validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
   1944 
   1945    /* if the cert is good, then just use the nickname directly */
   1946    if (validity == secCertTimeValid) {
   1947        if (arena == NULL) {
   1948            nickname = PORT_Strdup(srcNickname);
   1949        } else {
   1950            nickname = PORT_ArenaStrdup(arena, srcNickname);
   1951        }
   1952 
   1953        if (nickname == NULL) {
   1954            goto loser;
   1955        }
   1956    } else {
   1957 
   1958        /* if the cert is not valid, then tack one of the strings on the
   1959         * end
   1960         */
   1961        if (validity == secCertTimeExpired) {
   1962            tmpstr = PR_smprintf("%s%s", srcNickname,
   1963                                 expiredString);
   1964        } else if (validity == secCertTimeNotValidYet) {
   1965            /* not yet valid */
   1966            tmpstr = PR_smprintf("%s%s", srcNickname,
   1967                                 notYetGoodString);
   1968        } else {
   1969            /* undetermined */
   1970            tmpstr = PR_smprintf("%s",
   1971                                 "(NULL) (Validity Unknown)");
   1972        }
   1973 
   1974        if (tmpstr == NULL) {
   1975            goto loser;
   1976        }
   1977 
   1978        if (arena) {
   1979            /* copy the string into the arena and free the malloc'd one */
   1980            nickname = PORT_ArenaStrdup(arena, tmpstr);
   1981            PORT_Free(tmpstr);
   1982        } else {
   1983            nickname = tmpstr;
   1984        }
   1985        if (nickname == NULL) {
   1986            goto loser;
   1987        }
   1988    }
   1989    return (nickname);
   1990 
   1991 loser:
   1992    return (NULL);
   1993 }
   1994 
   1995 /*
   1996 * Collect the nicknames from all certs in a CertList.  If the cert is not
   1997 * valid, append a string to that nickname.
   1998 *
   1999 * "certList" - the list of certificates
   2000 * "expiredString" - the string to append to the nickname of any expired cert
   2001 * "notYetGoodString" - the string to append to the nickname of any cert
   2002 *      that is not yet valid
   2003 */
   2004 CERTCertNicknames *
   2005 CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString,
   2006                                 char *notYetGoodString)
   2007 {
   2008    CERTCertNicknames *names;
   2009    PLArenaPool *arena;
   2010    CERTCertListNode *node;
   2011    char **nn;
   2012 
   2013    /* allocate an arena */
   2014    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2015    if (arena == NULL) {
   2016        return (NULL);
   2017    }
   2018 
   2019    /* allocate the structure */
   2020    names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
   2021    if (names == NULL) {
   2022        goto loser;
   2023    }
   2024 
   2025    /* init the structure */
   2026    names->arena = arena;
   2027    names->head = NULL;
   2028    names->numnicknames = 0;
   2029    names->nicknames = NULL;
   2030    names->totallen = 0;
   2031 
   2032    /* count the certs in the list */
   2033    node = CERT_LIST_HEAD(certList);
   2034    while (!CERT_LIST_END(node, certList)) {
   2035        names->numnicknames++;
   2036        node = CERT_LIST_NEXT(node);
   2037    }
   2038 
   2039    /* allocate nicknames array */
   2040    names->nicknames = PORT_ArenaAlloc(arena,
   2041                                       sizeof(char *) * names->numnicknames);
   2042    if (names->nicknames == NULL) {
   2043        goto loser;
   2044    }
   2045 
   2046    /* just in case printf can't deal with null strings */
   2047    if (expiredString == NULL) {
   2048        expiredString = "";
   2049    }
   2050 
   2051    if (notYetGoodString == NULL) {
   2052        notYetGoodString = "";
   2053    }
   2054 
   2055    /* traverse the list of certs and collect the nicknames */
   2056    nn = names->nicknames;
   2057    node = CERT_LIST_HEAD(certList);
   2058    while (!CERT_LIST_END(node, certList)) {
   2059        *nn = CERT_GetCertNicknameWithValidity(arena, node->cert,
   2060                                               expiredString,
   2061                                               notYetGoodString);
   2062        if (*nn == NULL) {
   2063            goto loser;
   2064        }
   2065 
   2066        names->totallen += PORT_Strlen(*nn);
   2067 
   2068        nn++;
   2069        node = CERT_LIST_NEXT(node);
   2070    }
   2071 
   2072    return (names);
   2073 
   2074 loser:
   2075    PORT_FreeArena(arena, PR_FALSE);
   2076    return (NULL);
   2077 }
   2078 
   2079 /*
   2080 * Extract the nickname from a nickmake string that may have either
   2081 * expiredString or notYetGoodString appended.
   2082 *
   2083 * Args:
   2084 *  "namestring" - the string containing the nickname, and possibly
   2085 *      one of the validity label strings
   2086 *  "expiredString" - the expired validity label string
   2087 *  "notYetGoodString" - the not yet good validity label string
   2088 *
   2089 * Returns the raw nickname
   2090 */
   2091 char *
   2092 CERT_ExtractNicknameString(char *namestring, char *expiredString,
   2093                           char *notYetGoodString)
   2094 {
   2095    int explen, nyglen, namelen;
   2096    int retlen;
   2097    char *retstr;
   2098 
   2099    namelen = PORT_Strlen(namestring);
   2100    explen = PORT_Strlen(expiredString);
   2101    nyglen = PORT_Strlen(notYetGoodString);
   2102 
   2103    if (namelen > explen) {
   2104        if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) {
   2105            retlen = namelen - explen;
   2106            retstr = (char *)PORT_Alloc(retlen + 1);
   2107            if (retstr == NULL) {
   2108                goto loser;
   2109            }
   2110 
   2111            PORT_Memcpy(retstr, namestring, retlen);
   2112            retstr[retlen] = '\0';
   2113            goto done;
   2114        }
   2115    }
   2116 
   2117    if (namelen > nyglen) {
   2118        if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) {
   2119            retlen = namelen - nyglen;
   2120            retstr = (char *)PORT_Alloc(retlen + 1);
   2121            if (retstr == NULL) {
   2122                goto loser;
   2123            }
   2124 
   2125            PORT_Memcpy(retstr, namestring, retlen);
   2126            retstr[retlen] = '\0';
   2127            goto done;
   2128        }
   2129    }
   2130 
   2131    /* if name string is shorter than either invalid string, then it must
   2132     * be a raw nickname
   2133     */
   2134    retstr = PORT_Strdup(namestring);
   2135 
   2136 done:
   2137    return (retstr);
   2138 
   2139 loser:
   2140    return (NULL);
   2141 }
   2142 
   2143 CERTCertList *
   2144 CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage)
   2145 {
   2146    CERTCertList *chain = NULL;
   2147    int count = 0;
   2148 
   2149    if (NULL == cert) {
   2150        return NULL;
   2151    }
   2152 
   2153    cert = CERT_DupCertificate(cert);
   2154    if (NULL == cert) {
   2155        PORT_SetError(SEC_ERROR_NO_MEMORY);
   2156        return NULL;
   2157    }
   2158 
   2159    chain = CERT_NewCertList();
   2160    if (NULL == chain) {
   2161        CERT_DestroyCertificate(cert);
   2162        PORT_SetError(SEC_ERROR_NO_MEMORY);
   2163        return NULL;
   2164    }
   2165 
   2166    while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) {
   2167        if (SECSuccess != CERT_AddCertToListTail(chain, cert)) {
   2168            /* return partial chain */
   2169            CERT_DestroyCertificate(cert);
   2170            PORT_SetError(SEC_ERROR_NO_MEMORY);
   2171            return chain;
   2172        }
   2173 
   2174        if (cert->isRoot) {
   2175            /* return complete chain */
   2176            return chain;
   2177        }
   2178 
   2179        cert = CERT_FindCertIssuer(cert, time, usage);
   2180    }
   2181 
   2182    /* return partial chain */
   2183    CERT_DestroyCertificate(cert);
   2184    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
   2185    return chain;
   2186 }