Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1211)

Unified Diff: nss/lib/certhigh/certvfy.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « nss/lib/certhigh/certreq.c ('k') | nss/lib/certhigh/certvfypkix.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: nss/lib/certhigh/certvfy.c
diff --git a/nss/lib/certhigh/certvfy.c b/nss/lib/certhigh/certvfy.c
deleted file mode 100644
index eff77fc500d1e232e64866cf683589d07340d38e..0000000000000000000000000000000000000000
--- a/nss/lib/certhigh/certvfy.c
+++ /dev/null
@@ -1,1978 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nspr.h"
-#include "secerr.h"
-#include "secport.h"
-#include "seccomon.h"
-#include "secoid.h"
-#include "genname.h"
-#include "keyhi.h"
-#include "cert.h"
-#include "certdb.h"
-#include "certi.h"
-#include "cryptohi.h"
-#ifndef NSS_DISABLE_LIBPKIX
-#include "pkix.h"
-/*#include "pkix_sample_modules.h" */
-#include "pkix_pl_cert.h"
-#endif /* NSS_DISABLE_LIBPKIX */
-
-#include "nsspki.h"
-#include "pkitm.h"
-#include "pkim.h"
-#include "pki3hack.h"
-#include "base.h"
-#include "keyhi.h"
-
-#ifdef NSS_DISABLE_LIBPKIX
-SECStatus
-cert_VerifyCertChainPkix(
- CERTCertificate *cert,
- PRBool checkSig,
- SECCertUsage requiredUsage,
- PRTime time,
- void *wincx,
- CERTVerifyLog *log,
- PRBool *pSigerror,
- PRBool *pRevoked)
-{
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
- return SECFailure;
-}
-
-SECStatus
-CERT_SetUsePKIXForValidation(PRBool enable)
-{
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
- return SECFailure;
-}
-
-PRBool
-CERT_GetUsePKIXForValidation()
-{
- return PR_FALSE;
-}
-
-SECStatus CERT_PKIXVerifyCert(
- CERTCertificate *cert,
- SECCertificateUsage usages,
- CERTValInParam *paramsIn,
- CERTValOutParam *paramsOut,
- void *wincx)
-{
- PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
- return SECFailure;
-}
-#endif /* NSS_DISABLE_LIBPKIX */
-
-/*
- * Check the validity times of a certificate
- */
-SECStatus
-CERT_CertTimesValid(CERTCertificate *c)
-{
- SECCertTimeValidity valid = CERT_CheckCertValidTimes(c, PR_Now(), PR_TRUE);
- return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
-}
-
-SECStatus
-checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
-{
- SECStatus rv;
- SECOidTag sigAlg;
- SECOidTag curve;
- PRUint32 policyFlags = 0;
- PRInt32 minLen, len;
-
- sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
-
- switch (sigAlg) {
- case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
- case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
- if (key->keyType != ecKey) {
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
- return SECFailure;
- }
-
- curve = SECKEY_GetECCOid(&key->u.ec.DEREncodedParams);
- if (curve != 0) {
- if (NSS_GetAlgorithmPolicy(curve, &policyFlags) == SECFailure ||
- !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
- PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
- return SECFailure;
- } else {
- return SECSuccess;
- }
- } else {
- PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
- return SECFailure;
- }
- return SECSuccess;
- case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
- case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
- case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
- case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
- if (key->keyType != rsaKey && key->keyType != rsaPssKey) {
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
- return SECFailure;
- }
-
- len = 8 * key->u.rsa.modulus.len;
-
- rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &minLen);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
- if (len < minLen) {
- return SECFailure;
- }
-
- return SECSuccess;
- case SEC_OID_ANSIX9_DSA_SIGNATURE:
- case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
- case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
- case SEC_OID_SDN702_DSA_SIGNATURE:
- case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
- case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
- if (key->keyType != dsaKey) {
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
- return SECFailure;
- }
-
- len = 8 * key->u.dsa.params.prime.len;
-
- rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &minLen);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
- if (len < minLen) {
- return SECFailure;
- }
-
- return SECSuccess;
- default:
- return SECSuccess;
- }
-}
-
-/*
- * verify the signature of a signed data object with the given DER publickey
- */
-SECStatus
-CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd,
- SECKEYPublicKey *pubKey,
- void *wincx)
-{
- SECStatus rv;
- SECItem sig;
- SECOidTag hashAlg = SEC_OID_UNKNOWN;
-
- if (!pubKey || !sd) {
- PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
- return SECFailure;
- }
- /* check the signature */
- sig = sd->signature;
- /* convert sig->len from bit counts to byte count. */
- DER_ConvertBitString(&sig);
-
- rv = VFY_VerifyDataWithAlgorithmID(sd->data.data, sd->data.len, pubKey,
- &sig, &sd->signatureAlgorithm, &hashAlg, wincx);
- if (rv == SECSuccess) {
- /* Are we honoring signatures for this algorithm? */
- PRUint32 policyFlags = 0;
- rv = checkKeyParams(&sd->signatureAlgorithm, pubKey);
- if (rv != SECSuccess) {
- PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
- return SECFailure;
- }
-
- rv = NSS_GetAlgorithmPolicy(hashAlg, &policyFlags);
- if (rv == SECSuccess &&
- !(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
- PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
- return SECFailure;
- }
- }
- return rv;
-}
-
-/*
- * verify the signature of a signed data object with the given DER publickey
- */
-SECStatus
-CERT_VerifySignedDataWithPublicKeyInfo(CERTSignedData *sd,
- CERTSubjectPublicKeyInfo *pubKeyInfo,
- void *wincx)
-{
- SECKEYPublicKey *pubKey;
- SECStatus rv = SECFailure;
-
- /* get cert's public key */
- pubKey = SECKEY_ExtractPublicKey(pubKeyInfo);
- if (pubKey) {
- rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
- SECKEY_DestroyPublicKey(pubKey);
- }
- return rv;
-}
-
-/*
- * verify the signature of a signed data object with the given certificate
- */
-SECStatus
-CERT_VerifySignedData(CERTSignedData *sd, CERTCertificate *cert,
- PRTime t, void *wincx)
-{
- SECKEYPublicKey *pubKey = 0;
- SECStatus rv = SECFailure;
- SECCertTimeValidity validity;
-
- /* check the certificate's validity */
- validity = CERT_CheckCertValidTimes(cert, t, PR_FALSE);
- if (validity != secCertTimeValid) {
- return rv;
- }
-
- /* get cert's public key */
- pubKey = CERT_ExtractPublicKey(cert);
- if (pubKey) {
- rv = CERT_VerifySignedDataWithPublicKey(sd, pubKey, wincx);
- SECKEY_DestroyPublicKey(pubKey);
- }
- return rv;
-}
-
-SECStatus
-SEC_CheckCRL(CERTCertDBHandle *handle, CERTCertificate *cert,
- CERTCertificate *caCert, PRTime t, void *wincx)
-{
- return CERT_CheckCRL(cert, caCert, NULL, t, wincx);
-}
-
-/*
- * Find the issuer of a cert. Use the authorityKeyID if it exists.
- */
-CERTCertificate *
-CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, SECCertUsage usage)
-{
- NSSCertificate *me;
- NSSTime *nssTime;
- NSSTrustDomain *td;
- NSSCryptoContext *cc;
- NSSCertificate *chain[3];
- NSSUsage nssUsage;
- PRStatus status;
-
- me = STAN_GetNSSCertificate(cert);
- if (!me) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return NULL;
- }
- nssTime = NSSTime_SetPRTime(NULL, validTime);
- nssUsage.anyUsage = PR_FALSE;
- nssUsage.nss3usage = usage;
- nssUsage.nss3lookingForCA = PR_TRUE;
- memset(chain, 0, 3 * sizeof(NSSCertificate *));
- td = STAN_GetDefaultTrustDomain();
- cc = STAN_GetDefaultCryptoContext();
- (void)NSSCertificate_BuildChain(me, nssTime, &nssUsage, NULL,
- chain, 2, NULL, &status, td, cc);
- nss_ZFreeIf(nssTime);
- if (status == PR_SUCCESS) {
- PORT_Assert(me == chain[0]);
- /* if it's a root, the chain will only have one cert */
- if (!chain[1]) {
- /* already has a reference from the call to BuildChain */
- return cert;
- }
- NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
- return STAN_GetCERTCertificate(chain[1]); /* return the 2nd */
- }
- if (chain[0]) {
- PORT_Assert(me == chain[0]);
- NSSCertificate_Destroy(chain[0]); /* the first cert in the chain */
- }
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- return NULL;
-}
-
-/*
- * return required trust flags for various cert usages for CAs
- */
-SECStatus
-CERT_TrustFlagsForCACertUsage(SECCertUsage usage,
- unsigned int *retFlags,
- SECTrustType *retTrustType)
-{
- unsigned int requiredFlags;
- SECTrustType trustType;
-
- switch (usage) {
- case certUsageSSLClient:
- requiredFlags = CERTDB_TRUSTED_CLIENT_CA;
- trustType = trustSSL;
- break;
- case certUsageSSLServer:
- case certUsageSSLCA:
- requiredFlags = CERTDB_TRUSTED_CA;
- trustType = trustSSL;
- break;
- case certUsageSSLServerWithStepUp:
- requiredFlags = CERTDB_TRUSTED_CA | CERTDB_GOVT_APPROVED_CA;
- trustType = trustSSL;
- break;
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- requiredFlags = CERTDB_TRUSTED_CA;
- trustType = trustEmail;
- break;
- case certUsageObjectSigner:
- requiredFlags = CERTDB_TRUSTED_CA;
- trustType = trustObjectSigning;
- break;
- case certUsageVerifyCA:
- case certUsageAnyCA:
- case certUsageStatusResponder:
- requiredFlags = CERTDB_TRUSTED_CA;
- trustType = trustTypeNone;
- break;
- default:
- PORT_Assert(0);
- goto loser;
- }
- if (retFlags != NULL) {
- *retFlags = requiredFlags;
- }
- if (retTrustType != NULL) {
- *retTrustType = trustType;
- }
-
- return (SECSuccess);
-loser:
- return (SECFailure);
-}
-
-void
-cert_AddToVerifyLog(CERTVerifyLog *log, CERTCertificate *cert, long error,
- unsigned int depth, void *arg)
-{
- CERTVerifyLogNode *node, *tnode;
-
- PORT_Assert(log != NULL);
-
- node = (CERTVerifyLogNode *)PORT_ArenaAlloc(log->arena,
- sizeof(CERTVerifyLogNode));
- if (node != NULL) {
- node->cert = CERT_DupCertificate(cert);
- node->error = error;
- node->depth = depth;
- node->arg = arg;
-
- if (log->tail == NULL) {
- /* empty list */
- log->head = log->tail = node;
- node->prev = NULL;
- node->next = NULL;
- } else if (depth >= log->tail->depth) {
- /* add to tail */
- node->prev = log->tail;
- log->tail->next = node;
- log->tail = node;
- node->next = NULL;
- } else if (depth < log->head->depth) {
- /* add at head */
- node->prev = NULL;
- node->next = log->head;
- log->head->prev = node;
- log->head = node;
- } else {
- /* add in middle */
- tnode = log->tail;
- while (tnode != NULL) {
- if (depth >= tnode->depth) {
- /* insert after tnode */
- node->prev = tnode;
- node->next = tnode->next;
- tnode->next->prev = node;
- tnode->next = node;
- break;
- }
-
- tnode = tnode->prev;
- }
- }
-
- log->count++;
- }
- return;
-}
-
-#define EXIT_IF_NOT_LOGGING(log) \
- if (log == NULL) { \
- goto loser; \
- }
-
-#define LOG_ERROR_OR_EXIT(log, cert, depth, arg) \
- if (log != NULL) { \
- cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
- (void *)(PRWord)arg); \
- } else { \
- goto loser; \
- }
-
-#define LOG_ERROR(log, cert, depth, arg) \
- if (log != NULL) { \
- cert_AddToVerifyLog(log, cert, PORT_GetError(), depth, \
- (void *)(PRWord)arg); \
- }
-
-static SECStatus
-cert_VerifyCertChainOld(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, PRBool *sigerror,
- SECCertUsage certUsage, PRTime t, void *wincx,
- CERTVerifyLog *log, PRBool *revoked)
-{
- SECTrustType trustType;
- CERTBasicConstraints basicConstraint;
- CERTCertificate *issuerCert = NULL;
- CERTCertificate *subjectCert = NULL;
- CERTCertificate *badCert = NULL;
- PRBool isca;
- SECStatus rv;
- SECStatus rvFinal = SECSuccess;
- int count;
- int currentPathLen = 0;
- int pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
- unsigned int caCertType;
- unsigned int requiredCAKeyUsage;
- unsigned int requiredFlags;
- PLArenaPool *arena = NULL;
- CERTGeneralName *namesList = NULL;
- CERTCertificate **certsList = NULL;
- int certsListLen = 16;
- int namesCount = 0;
- PRBool subjectCertIsSelfIssued;
- CERTCertTrust issuerTrust;
-
- if (revoked) {
- *revoked = PR_FALSE;
- }
-
- if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
- &requiredCAKeyUsage,
- &caCertType) !=
- SECSuccess) {
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredCAKeyUsage = 0;
- caCertType = 0;
- }
-
- switch (certUsage) {
- case certUsageSSLClient:
- case certUsageSSLServer:
- case certUsageSSLCA:
- case certUsageSSLServerWithStepUp:
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- case certUsageObjectSigner:
- case certUsageVerifyCA:
- case certUsageAnyCA:
- case certUsageStatusResponder:
- if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
- &trustType) != SECSuccess) {
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- /* XXX continuing with requiredFlags = 0 seems wrong. It'll
- * cause the following test to be true incorrectly:
- * flags = SEC_GET_TRUST_FLAGS(issuerCert->trust, trustType);
- * if (( flags & requiredFlags ) == requiredFlags) {
- * rv = rvFinal;
- * goto done;
- * }
- * There are three other instances of this problem.
- */
- requiredFlags = 0;
- trustType = trustSSL;
- }
- break;
- default:
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredFlags = 0;
- trustType = trustSSL; /* This used to be 0, but we need something
- * that matches the enumeration type.
- */
- caCertType = 0;
- }
-
- subjectCert = CERT_DupCertificate(cert);
- if (subjectCert == NULL) {
- goto loser;
- }
-
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- goto loser;
- }
-
- certsList = PORT_ZNewArray(CERTCertificate *, certsListLen);
- if (certsList == NULL)
- goto loser;
-
- /* RFC 3280 says that the name constraints will apply to the names
- ** in the leaf (EE) cert, whether it is self issued or not, so
- ** we pretend that it is not.
- */
- subjectCertIsSelfIssued = PR_FALSE;
- for (count = 0; count < CERT_MAX_CERT_CHAIN; count++) {
- PRBool validCAOverride = PR_FALSE;
-
- /* Construct a list of names for the current and all previous
- * certifcates (except leaf (EE) certs, root CAs, and self-issued
- * intermediate CAs) to be verified against the name constraints
- * extension of the issuer certificate.
- */
- if (subjectCertIsSelfIssued == PR_FALSE) {
- CERTGeneralName *subjectNameList;
- int subjectNameListLen;
- int i;
- PRBool getSubjectCN = (!count && certUsage == certUsageSSLServer);
- subjectNameList =
- CERT_GetConstrainedCertificateNames(subjectCert, arena,
- getSubjectCN);
- if (!subjectNameList)
- goto loser;
- subjectNameListLen = CERT_GetNamesLength(subjectNameList);
- if (!subjectNameListLen)
- goto loser;
- if (certsListLen <= namesCount + subjectNameListLen) {
- CERTCertificate **tmpCertsList;
- certsListLen = (namesCount + subjectNameListLen) * 2;
- tmpCertsList =
- (CERTCertificate **)PORT_Realloc(certsList,
- certsListLen *
- sizeof(CERTCertificate *));
- if (tmpCertsList == NULL) {
- goto loser;
- }
- certsList = tmpCertsList;
- }
- for (i = 0; i < subjectNameListLen; i++) {
- certsList[namesCount + i] = subjectCert;
- }
- namesCount += subjectNameListLen;
- namesList = cert_CombineNamesLists(namesList, subjectNameList);
- }
-
- /* check if the cert has an unsupported critical extension */
- if (subjectCert->options.bits.hasUnsupportedCriticalExt) {
- PORT_SetError(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
- LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
- }
-
- /* find the certificate of the issuer */
- issuerCert = CERT_FindCertIssuer(subjectCert, t, certUsage);
- if (!issuerCert) {
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- LOG_ERROR(log, subjectCert, count, 0);
- goto loser;
- }
-
- /* verify the signature on the cert */
- if (checkSig) {
- rv = CERT_VerifySignedData(&subjectCert->signatureWrap,
- issuerCert, t, wincx);
-
- if (rv != SECSuccess) {
- if (sigerror) {
- *sigerror = PR_TRUE;
- }
- if (PORT_GetError() == SEC_ERROR_EXPIRED_CERTIFICATE) {
- PORT_SetError(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
- } else {
- if (PORT_GetError() !=
- SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED) {
- PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
- }
- LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
- }
- }
- }
-
- /* If the basicConstraint extension is included in an immediate CA
- * certificate, make sure that the isCA flag is on. If the
- * pathLenConstraint component exists, it must be greater than the
- * number of CA certificates we have seen so far. If the extension
- * is omitted, we will assume that this is a CA certificate with
- * an unlimited pathLenConstraint (since it already passes the
- * netscape-cert-type extension checking).
- */
-
- rv = CERT_FindBasicConstraintExten(issuerCert, &basicConstraint);
- if (rv != SECSuccess) {
- if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
- }
- pathLengthLimit = CERT_UNLIMITED_PATH_CONSTRAINT;
- /* no basic constraints found, we aren't (yet) a CA. */
- isca = PR_FALSE;
- } else {
- if (basicConstraint.isCA == PR_FALSE) {
- PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
- }
- pathLengthLimit = basicConstraint.pathLenConstraint;
- isca = PR_TRUE;
- }
- /* make sure that the path len constraint is properly set.*/
- if (pathLengthLimit >= 0 && currentPathLen > pathLengthLimit) {
- PORT_SetError(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, pathLengthLimit);
- }
-
- /* make sure that the entire chain is within the name space of the
- * current issuer certificate.
- */
- rv = CERT_CompareNameSpace(issuerCert, namesList, certsList,
- arena, &badCert);
- if (rv != SECSuccess || badCert != NULL) {
- PORT_SetError(SEC_ERROR_CERT_NOT_IN_NAME_SPACE);
- LOG_ERROR_OR_EXIT(log, badCert, count + 1, 0);
- goto loser;
- }
-
- /* XXX - the error logging may need to go down into CRL stuff at some
- * point
- */
- /* check revoked list (issuer) */
- rv = SEC_CheckCRL(handle, subjectCert, issuerCert, t, wincx);
- if (rv == SECFailure) {
- if (revoked) {
- *revoked = PR_TRUE;
- }
- LOG_ERROR_OR_EXIT(log, subjectCert, count, 0);
- } else if (rv == SECWouldBlock) {
- /* We found something fishy, so we intend to issue an
- * error to the user, but the user may wish to continue
- * processing, in which case we better make sure nothing
- * worse has happened... so keep cranking the loop */
- rvFinal = SECFailure;
- if (revoked) {
- *revoked = PR_TRUE;
- }
- LOG_ERROR(log, subjectCert, count, 0);
- }
-
- if (CERT_GetCertTrust(issuerCert, &issuerTrust) == SECSuccess) {
- /* we have some trust info, but this does NOT imply that this
- * cert is actually trusted for any purpose. The cert may be
- * explicitly UNtrusted. We won't know until we examine the
- * trust bits.
- */
- unsigned int flags;
-
- if (certUsage != certUsageAnyCA &&
- certUsage != certUsageStatusResponder) {
-
- /*
- * XXX This choice of trustType seems arbitrary.
- */
- if (certUsage == certUsageVerifyCA) {
- if (subjectCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
- trustType = trustEmail;
- } else if (subjectCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
- trustType = trustSSL;
- } else {
- trustType = trustObjectSigning;
- }
- }
-
- flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
- if ((flags & requiredFlags) == requiredFlags) {
- /* we found a trusted one, so return */
- rv = rvFinal;
- goto done;
- }
- if (flags & CERTDB_VALID_CA) {
- validCAOverride = PR_TRUE;
- }
- /* is it explicitly distrusted? */
- if ((flags & CERTDB_TERMINAL_RECORD) &&
- ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
- /* untrusted -- the cert is explicitly untrusted, not
- * just that it doesn't chain to a trusted cert */
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
- }
- } else {
- /* Check if we have any valid trust when cheching for
- * certUsageAnyCA or certUsageStatusResponder. */
- for (trustType = trustSSL; trustType < trustTypeNone;
- trustType++) {
- flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
- if ((flags & requiredFlags) == requiredFlags) {
- rv = rvFinal;
- goto done;
- }
- if (flags & CERTDB_VALID_CA)
- validCAOverride = PR_TRUE;
- }
- /* We have 2 separate loops because we want any single trust
- * bit to allow this usage to return trusted. Only if none of
- * the trust bits are on do we check to see if the cert is
- * untrusted */
- for (trustType = trustSSL; trustType < trustTypeNone;
- trustType++) {
- flags = SEC_GET_TRUST_FLAGS(&issuerTrust, trustType);
- /* is it explicitly distrusted? */
- if ((flags & CERTDB_TERMINAL_RECORD) &&
- ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
- /* untrusted -- the cert is explicitly untrusted, not
- * just that it doesn't chain to a trusted cert */
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, flags);
- }
- }
- }
- }
-
- if (!validCAOverride) {
- /*
- * Make sure that if this is an intermediate CA in the chain that
- * it was given permission by its signer to be a CA.
- */
- /*
- * if basicConstraints says it is a ca, then we check the
- * nsCertType. If the nsCertType has any CA bits set, then
- * it must have the right one.
- */
- if (!isca || (issuerCert->nsCertType & NS_CERT_TYPE_CA)) {
- isca = (issuerCert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
- }
-
- if (!isca) {
- PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, 0);
- }
-
- /* make sure key usage allows cert signing */
- if (CERT_CheckKeyUsage(issuerCert, requiredCAKeyUsage) != SECSuccess) {
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
- LOG_ERROR_OR_EXIT(log, issuerCert, count + 1, requiredCAKeyUsage);
- }
- }
-
- /* make sure that the issuer is not self signed. If it is, then
- * stop here to prevent looping.
- */
- if (issuerCert->isRoot) {
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
- LOG_ERROR(log, issuerCert, count + 1, 0);
- goto loser;
- }
- /* The issuer cert will be the subject cert in the next loop.
- * A cert is self-issued if its subject and issuer are equal and
- * both are of non-zero length.
- */
- subjectCertIsSelfIssued = (PRBool)
- SECITEM_ItemsAreEqual(&issuerCert->derIssuer,
- &issuerCert->derSubject) &&
- issuerCert->derSubject.len >
- 0;
- if (subjectCertIsSelfIssued == PR_FALSE) {
- /* RFC 3280 says only non-self-issued intermediate CA certs
- * count in path length.
- */
- ++currentPathLen;
- }
-
- CERT_DestroyCertificate(subjectCert);
- subjectCert = issuerCert;
- issuerCert = NULL;
- }
-
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- LOG_ERROR(log, subjectCert, count, 0);
-loser:
- rv = SECFailure;
-done:
- if (certsList != NULL) {
- PORT_Free(certsList);
- }
- if (issuerCert) {
- CERT_DestroyCertificate(issuerCert);
- }
-
- if (subjectCert) {
- CERT_DestroyCertificate(subjectCert);
- }
-
- if (arena != NULL) {
- PORT_FreeArena(arena, PR_FALSE);
- }
- return rv;
-}
-
-SECStatus
-cert_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, PRBool *sigerror,
- SECCertUsage certUsage, PRTime t, void *wincx,
- CERTVerifyLog *log, PRBool *revoked)
-{
- if (CERT_GetUsePKIXForValidation()) {
- return cert_VerifyCertChainPkix(cert, checkSig, certUsage, t,
- wincx, log, sigerror, revoked);
- }
- return cert_VerifyCertChainOld(handle, cert, checkSig, sigerror,
- certUsage, t, wincx, log, revoked);
-}
-
-SECStatus
-CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, PRTime t,
- void *wincx, CERTVerifyLog *log)
-{
- return cert_VerifyCertChain(handle, cert, checkSig, NULL, certUsage, t,
- wincx, log, NULL);
-}
-
-/*
- * verify that a CA can sign a certificate with the requested usage.
- */
-SECStatus
-CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, PRTime t,
- void *wincx, CERTVerifyLog *log)
-{
- SECTrustType trustType;
- CERTBasicConstraints basicConstraint;
- PRBool isca;
- PRBool validCAOverride = PR_FALSE;
- SECStatus rv;
- SECStatus rvFinal = SECSuccess;
- unsigned int flags;
- unsigned int caCertType;
- unsigned int requiredCAKeyUsage;
- unsigned int requiredFlags;
- CERTCertificate *issuerCert;
- CERTCertTrust certTrust;
-
- if (CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_TRUE,
- &requiredCAKeyUsage,
- &caCertType) != SECSuccess) {
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredCAKeyUsage = 0;
- caCertType = 0;
- }
-
- switch (certUsage) {
- case certUsageSSLClient:
- case certUsageSSLServer:
- case certUsageSSLCA:
- case certUsageSSLServerWithStepUp:
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- case certUsageObjectSigner:
- case certUsageVerifyCA:
- case certUsageStatusResponder:
- if (CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags,
- &trustType) != SECSuccess) {
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredFlags = 0;
- trustType = trustSSL;
- }
- break;
- default:
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredFlags = 0;
- trustType = trustSSL; /* This used to be 0, but we need something
- * that matches the enumeration type.
- */
- caCertType = 0;
- }
-
- /* If the basicConstraint extension is included in an intermmediate CA
- * certificate, make sure that the isCA flag is on. If the
- * pathLenConstraint component exists, it must be greater than the
- * number of CA certificates we have seen so far. If the extension
- * is omitted, we will assume that this is a CA certificate with
- * an unlimited pathLenConstraint (since it already passes the
- * netscape-cert-type extension checking).
- */
-
- rv = CERT_FindBasicConstraintExten(cert, &basicConstraint);
- if (rv != SECSuccess) {
- if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) {
- LOG_ERROR_OR_EXIT(log, cert, 0, 0);
- }
- /* no basic constraints found, we aren't (yet) a CA. */
- isca = PR_FALSE;
- } else {
- if (basicConstraint.isCA == PR_FALSE) {
- PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log, cert, 0, 0);
- }
-
- /* can't check path length if we don't know the previous path */
- isca = PR_TRUE;
- }
-
- if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
- /* we have some trust info, but this does NOT imply that this
- * cert is actually trusted for any purpose. The cert may be
- * explicitly UNtrusted. We won't know until we examine the
- * trust bits.
- */
- if (certUsage == certUsageStatusResponder) {
- /* Check the special case of certUsageStatusResponder */
- issuerCert = CERT_FindCertIssuer(cert, t, certUsage);
- if (issuerCert) {
- if (SEC_CheckCRL(handle, cert, issuerCert, t, wincx) !=
- SECSuccess) {
- PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
- CERT_DestroyCertificate(issuerCert);
- goto loser;
- }
- CERT_DestroyCertificate(issuerCert);
- }
- /* XXX We have NOT determined that this cert is trusted.
- * For years, NSS has treated this as trusted,
- * but it seems incorrect.
- */
- rv = rvFinal;
- goto done;
- }
-
- /*
- * check the trust params of the issuer
- */
- flags = SEC_GET_TRUST_FLAGS(&certTrust, trustType);
- if ((flags & requiredFlags) == requiredFlags) {
- /* we found a trusted one, so return */
- rv = rvFinal;
- goto done;
- }
- if (flags & CERTDB_VALID_CA) {
- validCAOverride = PR_TRUE;
- }
- /* is it explicitly distrusted? */
- if ((flags & CERTDB_TERMINAL_RECORD) &&
- ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0)) {
- /* untrusted -- the cert is explicitly untrusted, not
- * just that it doesn't chain to a trusted cert */
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
- LOG_ERROR_OR_EXIT(log, cert, 0, flags);
- }
- }
- if (!validCAOverride) {
- /*
- * Make sure that if this is an intermediate CA in the chain that
- * it was given permission by its signer to be a CA.
- */
- /*
- * if basicConstraints says it is a ca, then we check the
- * nsCertType. If the nsCertType has any CA bits set, then
- * it must have the right one.
- */
- if (!isca || (cert->nsCertType & NS_CERT_TYPE_CA)) {
- isca = (cert->nsCertType & caCertType) ? PR_TRUE : PR_FALSE;
- }
-
- if (!isca) {
- PORT_SetError(SEC_ERROR_CA_CERT_INVALID);
- LOG_ERROR_OR_EXIT(log, cert, 0, 0);
- }
-
- /* make sure key usage allows cert signing */
- if (CERT_CheckKeyUsage(cert, requiredCAKeyUsage) != SECSuccess) {
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
- LOG_ERROR_OR_EXIT(log, cert, 0, requiredCAKeyUsage);
- }
- }
- /* make sure that the issuer is not self signed. If it is, then
- * stop here to prevent looping.
- */
- if (cert->isRoot) {
- PORT_SetError(SEC_ERROR_UNTRUSTED_ISSUER);
- LOG_ERROR(log, cert, 0, 0);
- goto loser;
- }
-
- return CERT_VerifyCertChain(handle, cert, checkSig, certUsage, t,
- wincx, log);
-loser:
- rv = SECFailure;
-done:
- return rv;
-}
-
-#define NEXT_USAGE() \
- { \
- i *= 2; \
- certUsage++; \
- continue; \
- }
-
-#define VALID_USAGE() \
- { \
- NEXT_USAGE(); \
- }
-
-#define INVALID_USAGE() \
- { \
- if (returnedUsages) { \
- *returnedUsages &= (~i); \
- } \
- if (PR_TRUE == requiredUsage) { \
- valid = SECFailure; \
- } \
- NEXT_USAGE(); \
- }
-
-/*
- * check the leaf cert against trust and usage.
- * returns success if the cert is not distrusted. If the cert is
- * trusted, then the trusted bool will be true.
- * returns failure if the cert is distrusted. If failure, flags
- * will return the flag bits that indicated distrust.
- */
-SECStatus
-cert_CheckLeafTrust(CERTCertificate *cert, SECCertUsage certUsage,
- unsigned int *failedFlags, PRBool *trusted)
-{
- unsigned int flags;
- CERTCertTrust trust;
-
- *failedFlags = 0;
- *trusted = PR_FALSE;
-
- /* check trust flags to see if this cert is directly trusted */
- if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
- switch (certUsage) {
- case certUsageSSLClient:
- case certUsageSSLServer:
- flags = trust.sslFlags;
-
- /* is the cert directly trusted or not trusted ? */
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if (flags & CERTDB_TRUSTED) { /* trust this cert */
- *trusted = PR_TRUE;
- return SECSuccess;
- } else { /* don't trust this cert */
- *failedFlags = flags;
- return SECFailure;
- }
- }
- break;
- case certUsageSSLServerWithStepUp:
- /* XXX - step up certs can't be directly trusted, only distrust */
- flags = trust.sslFlags;
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if ((flags & CERTDB_TRUSTED) == 0) {
- /* don't trust this cert */
- *failedFlags = flags;
- return SECFailure;
- }
- }
- break;
- case certUsageSSLCA:
- flags = trust.sslFlags;
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
- /* don't trust this cert */
- *failedFlags = flags;
- return SECFailure;
- }
- }
- break;
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- flags = trust.emailFlags;
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if (flags & CERTDB_TRUSTED) { /* trust this cert */
- *trusted = PR_TRUE;
- return SECSuccess;
- } else { /* don't trust this cert */
- *failedFlags = flags;
- return SECFailure;
- }
- }
-
- break;
- case certUsageObjectSigner:
- flags = trust.objectSigningFlags;
-
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if (flags & CERTDB_TRUSTED) { /* trust this cert */
- *trusted = PR_TRUE;
- return SECSuccess;
- } else { /* don't trust this cert */
- *failedFlags = flags;
- return SECFailure;
- }
- }
- break;
- case certUsageVerifyCA:
- case certUsageStatusResponder:
- flags = trust.sslFlags;
- /* is the cert directly trusted or not trusted ? */
- if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
- (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
- *trusted = PR_TRUE;
- return SECSuccess;
- }
- flags = trust.emailFlags;
- /* is the cert directly trusted or not trusted ? */
- if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
- (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
- *trusted = PR_TRUE;
- return SECSuccess;
- }
- flags = trust.objectSigningFlags;
- /* is the cert directly trusted or not trusted ? */
- if ((flags & (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) ==
- (CERTDB_VALID_CA | CERTDB_TRUSTED_CA)) {
- *trusted = PR_TRUE;
- return SECSuccess;
- }
- /* fall through to test distrust */
- case certUsageAnyCA:
- case certUsageUserCertImport:
- /* do we distrust these certs explicitly */
- flags = trust.sslFlags;
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
- *failedFlags = flags;
- return SECFailure;
- }
- }
- flags = trust.emailFlags;
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
- *failedFlags = flags;
- return SECFailure;
- }
- }
- /* fall through */
- case certUsageProtectedObjectSigner:
- flags = trust.objectSigningFlags;
- if (flags & CERTDB_TERMINAL_RECORD) { /* the trust record is
- * authoritative */
- if ((flags & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA)) == 0) {
- *failedFlags = flags;
- return SECFailure;
- }
- }
- break;
- }
- }
- return SECSuccess;
-}
-
-/*
- * verify a certificate by checking if it's valid and that we
- * trust the issuer.
- *
- * certificateUsage contains a bitfield of all cert usages that are
- * required for verification to succeed
- *
- * a bitfield of cert usages is returned in *returnedUsages
- * if requiredUsages is non-zero, the returned bitmap is only
- * for those required usages, otherwise it is for all usages
- *
- */
-SECStatus
-CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertificateUsage requiredUsages, PRTime t,
- void *wincx, CERTVerifyLog *log, SECCertificateUsage *returnedUsages)
-{
- SECStatus rv;
- SECStatus valid;
- unsigned int requiredKeyUsage;
- unsigned int requiredCertType;
- unsigned int flags;
- unsigned int certType;
- PRBool allowOverride;
- SECCertTimeValidity validity;
- CERTStatusConfig *statusConfig;
- PRInt32 i;
- SECCertUsage certUsage = 0;
- PRBool checkedOCSP = PR_FALSE;
- PRBool checkAllUsages = PR_FALSE;
- PRBool revoked = PR_FALSE;
- PRBool sigerror = PR_FALSE;
- PRBool trusted = PR_FALSE;
-
- if (!requiredUsages) {
- /* there are no required usages, so the user probably wants to
- get status for all usages */
- checkAllUsages = PR_TRUE;
- }
-
- if (returnedUsages) {
- *returnedUsages = 0;
- } else {
- /* we don't have a place to return status for all usages,
- so we can skip checks for usages that aren't required */
- checkAllUsages = PR_FALSE;
- }
- valid = SECSuccess; /* start off assuming cert is valid */
-
- /* make sure that the cert is valid at time t */
- allowOverride = (PRBool)((requiredUsages & certificateUsageSSLServer) ||
- (requiredUsages & certificateUsageSSLServerWithStepUp));
- validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
- if (validity != secCertTimeValid) {
- valid = SECFailure;
- LOG_ERROR_OR_EXIT(log, cert, 0, validity);
- }
-
- /* check key usage and netscape cert type */
- cert_GetCertType(cert);
- certType = cert->nsCertType;
-
- for (i = 1; i <= certificateUsageHighest &&
- (SECSuccess == valid || returnedUsages || log);) {
- PRBool requiredUsage = (i & requiredUsages) ? PR_TRUE : PR_FALSE;
- if (PR_FALSE == requiredUsage && PR_FALSE == checkAllUsages) {
- NEXT_USAGE();
- }
- if (returnedUsages) {
- *returnedUsages |= i; /* start off assuming this usage is valid */
- }
- switch (certUsage) {
- case certUsageSSLClient:
- case certUsageSSLServer:
- case certUsageSSLServerWithStepUp:
- case certUsageSSLCA:
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- case certUsageObjectSigner:
- case certUsageStatusResponder:
- rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
- &requiredKeyUsage,
- &requiredCertType);
- if (rv != SECSuccess) {
- PORT_Assert(0);
- /* EXIT_IF_NOT_LOGGING(log); XXX ??? */
- requiredKeyUsage = 0;
- requiredCertType = 0;
- INVALID_USAGE();
- }
- break;
-
- case certUsageAnyCA:
- case certUsageProtectedObjectSigner:
- case certUsageUserCertImport:
- case certUsageVerifyCA:
- /* these usages cannot be verified */
- NEXT_USAGE();
-
- default:
- PORT_Assert(0);
- requiredKeyUsage = 0;
- requiredCertType = 0;
- INVALID_USAGE();
- }
- if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
- if (PR_TRUE == requiredUsage) {
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
- }
- LOG_ERROR(log, cert, 0, requiredKeyUsage);
- INVALID_USAGE();
- }
- if (!(certType & requiredCertType)) {
- if (PR_TRUE == requiredUsage) {
- PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
- }
- LOG_ERROR(log, cert, 0, requiredCertType);
- INVALID_USAGE();
- }
-
- rv = cert_CheckLeafTrust(cert, certUsage, &flags, &trusted);
- if (rv == SECFailure) {
- if (PR_TRUE == requiredUsage) {
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
- }
- LOG_ERROR(log, cert, 0, flags);
- INVALID_USAGE();
- } else if (trusted) {
- VALID_USAGE();
- }
-
- if (PR_TRUE == revoked || PR_TRUE == sigerror) {
- INVALID_USAGE();
- }
-
- rv = cert_VerifyCertChain(handle, cert,
- checkSig, &sigerror,
- certUsage, t, wincx, log,
- &revoked);
-
- if (rv != SECSuccess) {
- /* EXIT_IF_NOT_LOGGING(log); XXX ???? */
- INVALID_USAGE();
- }
-
- /*
- * Check OCSP revocation status, but only if the cert we are checking
- * is not a status responder itself. We only do this in the case
- * where we checked the cert chain (above); explicit trust "wins"
- * (avoids status checking, just as it avoids CRL checking) by
- * bypassing this code.
- */
-
- if (PR_FALSE == checkedOCSP) {
- checkedOCSP = PR_TRUE; /* only check OCSP once */
- statusConfig = CERT_GetStatusConfig(handle);
- if (requiredUsages != certificateUsageStatusResponder &&
- statusConfig != NULL) {
- if (statusConfig->statusChecker != NULL) {
- rv = (*statusConfig->statusChecker)(handle, cert,
- t, wincx);
- if (rv != SECSuccess) {
- LOG_ERROR(log, cert, 0, 0);
- revoked = PR_TRUE;
- INVALID_USAGE();
- }
- }
- }
- }
-
- NEXT_USAGE();
- }
-
-loser:
- return (valid);
-}
-
-SECStatus
-CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, PRTime t,
- void *wincx, CERTVerifyLog *log)
-{
- return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
- CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
-}
-
-SECStatus
-cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, PRTime t,
- PRUint32 flags, void *wincx, CERTVerifyLog *log)
-{
- SECStatus rv;
- unsigned int requiredKeyUsage;
- unsigned int requiredCertType;
- unsigned int failedFlags;
- unsigned int certType;
- PRBool trusted;
- PRBool allowOverride;
- SECCertTimeValidity validity;
- CERTStatusConfig *statusConfig;
-
-#ifdef notdef
- /* check if this cert is in the Evil list */
- rv = CERT_CheckForEvilCert(cert);
- if (rv != SECSuccess) {
- PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
- LOG_ERROR_OR_EXIT(log, cert, 0, 0);
- }
-#endif
-
- /* make sure that the cert is valid at time t */
- allowOverride = (PRBool)((certUsage == certUsageSSLServer) ||
- (certUsage == certUsageSSLServerWithStepUp));
- validity = CERT_CheckCertValidTimes(cert, t, allowOverride);
- if (validity != secCertTimeValid) {
- LOG_ERROR_OR_EXIT(log, cert, 0, validity);
- }
-
- /* check key usage and netscape cert type */
- cert_GetCertType(cert);
- certType = cert->nsCertType;
- switch (certUsage) {
- case certUsageSSLClient:
- case certUsageSSLServer:
- case certUsageSSLServerWithStepUp:
- case certUsageSSLCA:
- case certUsageEmailSigner:
- case certUsageEmailRecipient:
- case certUsageObjectSigner:
- case certUsageStatusResponder:
- rv = CERT_KeyUsageAndTypeForCertUsage(certUsage, PR_FALSE,
- &requiredKeyUsage,
- &requiredCertType);
- if (rv != SECSuccess) {
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredKeyUsage = 0;
- requiredCertType = 0;
- }
- break;
- case certUsageVerifyCA:
- case certUsageAnyCA:
- requiredKeyUsage = KU_KEY_CERT_SIGN;
- requiredCertType = NS_CERT_TYPE_CA;
- if (!(certType & NS_CERT_TYPE_CA)) {
- certType |= NS_CERT_TYPE_CA;
- }
- break;
- default:
- PORT_Assert(0);
- EXIT_IF_NOT_LOGGING(log);
- requiredKeyUsage = 0;
- requiredCertType = 0;
- }
- if (CERT_CheckKeyUsage(cert, requiredKeyUsage) != SECSuccess) {
- PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
- LOG_ERROR_OR_EXIT(log, cert, 0, requiredKeyUsage);
- }
- if (!(certType & requiredCertType)) {
- PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
- LOG_ERROR_OR_EXIT(log, cert, 0, requiredCertType);
- }
-
- rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
- if (rv == SECFailure) {
- PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
- LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
- } else if (trusted) {
- goto done;
- }
-
- rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
- t, wincx, log);
- if (rv != SECSuccess) {
- EXIT_IF_NOT_LOGGING(log);
- }
-
- /*
- * Check revocation status, but only if the cert we are checking is not a
- * status responder itself and the caller did not ask us to skip the check.
- * We only do this in the case where we checked the cert chain (above);
- * explicit trust "wins" (avoids status checking, just as it avoids CRL
- * checking, which is all done inside VerifyCertChain) by bypassing this
- * code.
- */
- if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
- certUsage != certUsageStatusResponder) {
- statusConfig = CERT_GetStatusConfig(handle);
- if (statusConfig && statusConfig->statusChecker) {
- rv = (*statusConfig->statusChecker)(handle, cert,
- t, wincx);
- if (rv != SECSuccess) {
- LOG_ERROR_OR_EXIT(log, cert, 0, 0);
- }
- }
- }
-
-done:
- if (log && log->head) {
- return SECFailure;
- }
- return (SECSuccess);
-
-loser:
- rv = SECFailure;
-
- return (rv);
-}
-
-/*
- * verify a certificate by checking if its valid and that we
- * trust the issuer. Verify time against now.
- */
-SECStatus
-CERT_VerifyCertificateNow(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertificateUsage requiredUsages,
- void *wincx, SECCertificateUsage *returnedUsages)
-{
- return (CERT_VerifyCertificate(handle, cert, checkSig,
- requiredUsages, PR_Now(), wincx, NULL, returnedUsages));
-}
-
-/* obsolete, do not use for new code */
-SECStatus
-CERT_VerifyCertNow(CERTCertDBHandle *handle, CERTCertificate *cert,
- PRBool checkSig, SECCertUsage certUsage, void *wincx)
-{
- return (CERT_VerifyCert(handle, cert, checkSig,
- certUsage, PR_Now(), wincx, NULL));
-}
-
-/* [ FROM pcertdb.c ] */
-/*
- * Supported usage values and types:
- * certUsageSSLClient
- * certUsageSSLServer
- * certUsageSSLServerWithStepUp
- * certUsageEmailSigner
- * certUsageEmailRecipient
- * certUsageObjectSigner
- */
-
-CERTCertificate *
-CERT_FindMatchingCert(CERTCertDBHandle *handle, SECItem *derName,
- CERTCertOwner owner, SECCertUsage usage,
- PRBool preferTrusted, PRTime validTime, PRBool validOnly)
-{
- CERTCertList *certList = NULL;
- CERTCertificate *cert = NULL;
- CERTCertTrust certTrust;
- unsigned int requiredTrustFlags;
- SECTrustType requiredTrustType;
- unsigned int flags;
-
- PRBool lookingForCA = PR_FALSE;
- SECStatus rv;
- CERTCertListNode *node;
- CERTCertificate *saveUntrustedCA = NULL;
-
- /* if preferTrusted is set, must be a CA cert */
- PORT_Assert(!(preferTrusted && (owner != certOwnerCA)));
-
- if (owner == certOwnerCA) {
- lookingForCA = PR_TRUE;
- if (preferTrusted) {
- rv = CERT_TrustFlagsForCACertUsage(usage, &requiredTrustFlags,
- &requiredTrustType);
- if (rv != SECSuccess) {
- goto loser;
- }
- requiredTrustFlags |= CERTDB_VALID_CA;
- }
- }
-
- certList = CERT_CreateSubjectCertList(NULL, handle, derName, validTime,
- validOnly);
- if (certList != NULL) {
- rv = CERT_FilterCertListByUsage(certList, usage, lookingForCA);
- if (rv != SECSuccess) {
- goto loser;
- }
-
- node = CERT_LIST_HEAD(certList);
-
- while (!CERT_LIST_END(node, certList)) {
- cert = node->cert;
-
- /* looking for a trusted CA cert */
- if ((owner == certOwnerCA) && preferTrusted &&
- (requiredTrustType != trustTypeNone)) {
-
- if (CERT_GetCertTrust(cert, &certTrust) != SECSuccess) {
- flags = 0;
- } else {
- flags = SEC_GET_TRUST_FLAGS(&certTrust, requiredTrustType);
- }
-
- if ((flags & requiredTrustFlags) != requiredTrustFlags) {
- /* cert is not trusted */
- /* if this is the first cert to get this far, then save
- * it, so we can use it if we can't find a trusted one
- */
- if (saveUntrustedCA == NULL) {
- saveUntrustedCA = cert;
- }
- goto endloop;
- }
- }
- /* if we got this far, then this cert meets all criteria */
- break;
-
- endloop:
- node = CERT_LIST_NEXT(node);
- cert = NULL;
- }
-
- /* use the saved one if we have it */
- if (cert == NULL) {
- cert = saveUntrustedCA;
- }
-
- /* if we found one then bump the ref count before freeing the list */
- if (cert != NULL) {
- /* bump the ref count */
- cert = CERT_DupCertificate(cert);
- }
-
- CERT_DestroyCertList(certList);
- }
-
- return (cert);
-
-loser:
- if (certList != NULL) {
- CERT_DestroyCertList(certList);
- }
-
- return (NULL);
-}
-
-/* [ From certdb.c ] */
-/*
- * Filter a list of certificates, removing those certs that do not have
- * one of the named CA certs somewhere in their cert chain.
- *
- * "certList" - the list of certificates to filter
- * "nCANames" - number of CA names
- * "caNames" - array of CA names in string(rfc 1485) form
- * "usage" - what use the certs are for, this is used when
- * selecting CA certs
- */
-SECStatus
-CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames,
- char **caNames, SECCertUsage usage)
-{
- CERTCertificate *issuerCert = NULL;
- CERTCertificate *subjectCert;
- CERTCertListNode *node, *freenode;
- CERTCertificate *cert;
- int n;
- char **names;
- PRBool found;
- PRTime time;
-
- if (nCANames <= 0) {
- return (SECSuccess);
- }
-
- time = PR_Now();
-
- node = CERT_LIST_HEAD(certList);
-
- while (!CERT_LIST_END(node, certList)) {
- cert = node->cert;
-
- subjectCert = CERT_DupCertificate(cert);
-
- /* traverse the CA certs for this cert */
- found = PR_FALSE;
- while (subjectCert != NULL) {
- n = nCANames;
- names = caNames;
-
- if (subjectCert->issuerName != NULL) {
- while (n > 0) {
- if (PORT_Strcmp(*names, subjectCert->issuerName) == 0) {
- found = PR_TRUE;
- break;
- }
-
- n--;
- names++;
- }
- }
-
- if (found) {
- break;
- }
-
- issuerCert = CERT_FindCertIssuer(subjectCert, time, usage);
- if (issuerCert == subjectCert) {
- CERT_DestroyCertificate(issuerCert);
- issuerCert = NULL;
- break;
- }
- CERT_DestroyCertificate(subjectCert);
- subjectCert = issuerCert;
- }
- CERT_DestroyCertificate(subjectCert);
- if (!found) {
- /* CA was not found, so remove this cert from the list */
- freenode = node;
- node = CERT_LIST_NEXT(node);
- CERT_RemoveCertListNode(freenode);
- } else {
- /* CA was found, so leave it in the list */
- node = CERT_LIST_NEXT(node);
- }
- }
-
- return (SECSuccess);
-}
-
-/*
- * Given a certificate, return a string containing the nickname, and possibly
- * one of the validity strings, based on the current validity state of the
- * certificate.
- *
- * "arena" - arena to allocate returned string from. If NULL, then heap
- * is used.
- * "cert" - the cert to get nickname from
- * "expiredString" - the string to append to the nickname if the cert is
- * expired.
- * "notYetGoodString" - the string to append to the nickname if the cert is
- * not yet good.
- */
-char *
-CERT_GetCertNicknameWithValidity(PLArenaPool *arena, CERTCertificate *cert,
- char *expiredString, char *notYetGoodString)
-{
- SECCertTimeValidity validity;
- char *nickname = NULL, *tmpstr = NULL;
-
- validity = CERT_CheckCertValidTimes(cert, PR_Now(), PR_FALSE);
-
- /* if the cert is good, then just use the nickname directly */
- if (validity == secCertTimeValid) {
- if (arena == NULL) {
- nickname = PORT_Strdup(cert->nickname);
- } else {
- nickname = PORT_ArenaStrdup(arena, cert->nickname);
- }
-
- if (nickname == NULL) {
- goto loser;
- }
- } else {
-
- /* if the cert is not valid, then tack one of the strings on the
- * end
- */
- if (validity == secCertTimeExpired) {
- tmpstr = PR_smprintf("%s%s", cert->nickname,
- expiredString);
- } else if (validity == secCertTimeNotValidYet) {
- /* not yet valid */
- tmpstr = PR_smprintf("%s%s", cert->nickname,
- notYetGoodString);
- } else {
- /* undetermined */
- tmpstr = PR_smprintf("%s",
- "(NULL) (Validity Unknown)");
- }
-
- if (tmpstr == NULL) {
- goto loser;
- }
-
- if (arena) {
- /* copy the string into the arena and free the malloc'd one */
- nickname = PORT_ArenaStrdup(arena, tmpstr);
- PORT_Free(tmpstr);
- } else {
- nickname = tmpstr;
- }
- if (nickname == NULL) {
- goto loser;
- }
- }
- return (nickname);
-
-loser:
- return (NULL);
-}
-
-/*
- * Collect the nicknames from all certs in a CertList. If the cert is not
- * valid, append a string to that nickname.
- *
- * "certList" - the list of certificates
- * "expiredString" - the string to append to the nickname of any expired cert
- * "notYetGoodString" - the string to append to the nickname of any cert
- * that is not yet valid
- */
-CERTCertNicknames *
-CERT_NicknameStringsFromCertList(CERTCertList *certList, char *expiredString,
- char *notYetGoodString)
-{
- CERTCertNicknames *names;
- PLArenaPool *arena;
- CERTCertListNode *node;
- char **nn;
-
- /* allocate an arena */
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (arena == NULL) {
- return (NULL);
- }
-
- /* allocate the structure */
- names = PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames));
- if (names == NULL) {
- goto loser;
- }
-
- /* init the structure */
- names->arena = arena;
- names->head = NULL;
- names->numnicknames = 0;
- names->nicknames = NULL;
- names->totallen = 0;
-
- /* count the certs in the list */
- node = CERT_LIST_HEAD(certList);
- while (!CERT_LIST_END(node, certList)) {
- names->numnicknames++;
- node = CERT_LIST_NEXT(node);
- }
-
- /* allocate nicknames array */
- names->nicknames = PORT_ArenaAlloc(arena,
- sizeof(char *) * names->numnicknames);
- if (names->nicknames == NULL) {
- goto loser;
- }
-
- /* just in case printf can't deal with null strings */
- if (expiredString == NULL) {
- expiredString = "";
- }
-
- if (notYetGoodString == NULL) {
- notYetGoodString = "";
- }
-
- /* traverse the list of certs and collect the nicknames */
- nn = names->nicknames;
- node = CERT_LIST_HEAD(certList);
- while (!CERT_LIST_END(node, certList)) {
- *nn = CERT_GetCertNicknameWithValidity(arena, node->cert,
- expiredString,
- notYetGoodString);
- if (*nn == NULL) {
- goto loser;
- }
-
- names->totallen += PORT_Strlen(*nn);
-
- nn++;
- node = CERT_LIST_NEXT(node);
- }
-
- return (names);
-
-loser:
- PORT_FreeArena(arena, PR_FALSE);
- return (NULL);
-}
-
-/*
- * Extract the nickname from a nickmake string that may have either
- * expiredString or notYetGoodString appended.
- *
- * Args:
- * "namestring" - the string containing the nickname, and possibly
- * one of the validity label strings
- * "expiredString" - the expired validity label string
- * "notYetGoodString" - the not yet good validity label string
- *
- * Returns the raw nickname
- */
-char *
-CERT_ExtractNicknameString(char *namestring, char *expiredString,
- char *notYetGoodString)
-{
- int explen, nyglen, namelen;
- int retlen;
- char *retstr;
-
- namelen = PORT_Strlen(namestring);
- explen = PORT_Strlen(expiredString);
- nyglen = PORT_Strlen(notYetGoodString);
-
- if (namelen > explen) {
- if (PORT_Strcmp(expiredString, &namestring[namelen - explen]) == 0) {
- retlen = namelen - explen;
- retstr = (char *)PORT_Alloc(retlen + 1);
- if (retstr == NULL) {
- goto loser;
- }
-
- PORT_Memcpy(retstr, namestring, retlen);
- retstr[retlen] = '\0';
- goto done;
- }
- }
-
- if (namelen > nyglen) {
- if (PORT_Strcmp(notYetGoodString, &namestring[namelen - nyglen]) == 0) {
- retlen = namelen - nyglen;
- retstr = (char *)PORT_Alloc(retlen + 1);
- if (retstr == NULL) {
- goto loser;
- }
-
- PORT_Memcpy(retstr, namestring, retlen);
- retstr[retlen] = '\0';
- goto done;
- }
- }
-
- /* if name string is shorter than either invalid string, then it must
- * be a raw nickname
- */
- retstr = PORT_Strdup(namestring);
-
-done:
- return (retstr);
-
-loser:
- return (NULL);
-}
-
-CERTCertList *
-CERT_GetCertChainFromCert(CERTCertificate *cert, PRTime time, SECCertUsage usage)
-{
- CERTCertList *chain = NULL;
- int count = 0;
-
- if (NULL == cert) {
- return NULL;
- }
-
- cert = CERT_DupCertificate(cert);
- if (NULL == cert) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return NULL;
- }
-
- chain = CERT_NewCertList();
- if (NULL == chain) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return NULL;
- }
-
- while (cert != NULL && ++count <= CERT_MAX_CERT_CHAIN) {
- if (SECSuccess != CERT_AddCertToListTail(chain, cert)) {
- /* return partial chain */
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return chain;
- }
-
- if (cert->isRoot) {
- /* return complete chain */
- return chain;
- }
-
- cert = CERT_FindCertIssuer(cert, time, usage);
- }
-
- /* return partial chain */
- PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
- return chain;
-}
« no previous file with comments | « nss/lib/certhigh/certreq.c ('k') | nss/lib/certhigh/certvfypkix.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698