SECStatus AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA, const CertPolicyId& policy, const SECItem& candidateCertDER, /*out*/ TrustLevel* trustLevel) { MOZ_ASSERT(policy.IsAnyPolicy()); MOZ_ASSERT(trustLevel); MOZ_ASSERT(mTrustedRoot); if (!trustLevel || !policy.IsAnyPolicy()) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } if (!mTrustedRoot) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return SECFailure; } // Handle active distrust of the certificate. // XXX: This would be cleaner and more efficient if we could get the trust // information without constructing a CERTCertificate here, but NSS doesn't // expose it in any other easy-to-use fashion. ScopedCERTCertificate candidateCert( CERT_NewTempCertificate(CERT_GetDefaultCertDB(), const_cast<SECItem*>(&candidateCertDER), nullptr, false, true)); if (!candidateCert) { return SECFailure; } CERTCertTrust trust; if (CERT_GetCertTrust(candidateCert.get(), &trust) == SECSuccess) { PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning); // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit, // because we can have active distrust for either type of cert. Note that // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the // relevant trust bit isn't set then that means the cert must be considered // distrusted. PRUint32 relevantTrustBit = endEntityOrCA == EndEntityOrCA::MustBeCA ? CERTDB_TRUSTED_CA : CERTDB_TRUSTED; if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD))) == CERTDB_TERMINAL_RECORD) { *trustLevel = TrustLevel::ActivelyDistrusted; return SECSuccess; } } // mTrustedRoot is the only trust anchor for this validation. if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert.get())) { *trustLevel = TrustLevel::TrustAnchor; return SECSuccess; } *trustLevel = TrustLevel::InheritsTrust; return SECSuccess; }
static void addToCertListIfTrusted(CERTCertList* certList, CERTCertificate* cert) { CERTCertTrust nssTrust; if (CERT_GetCertTrust(cert, &nssTrust) != SECSuccess) { return; } unsigned int flags = SEC_GET_TRUST_FLAGS(&nssTrust, trustSSL); if (flags & CERTDB_TRUSTED_CA) { CERT_AddCertToListTail(certList, CERT_DupCertificate(cert)); } }
SECStatus NSSCertDBTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA, const CERTCertificate* candidateCert, /*out*/ TrustLevel* trustLevel) { PORT_Assert(candidateCert); PORT_Assert(trustLevel); if (!candidateCert || !trustLevel) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } // XXX: CERT_GetCertTrust seems to be abusing SECStatus as a boolean, where // SECSuccess means that there is a trust record and SECFailure means there // is not a trust record. I looked at NSS's internal uses of // CERT_GetCertTrust, and all that code uses the result as a boolean meaning // "We have a trust record." CERTCertTrust trust; if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) { PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, mCertDBTrustType); // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit, // because we can have active distrust for either type of cert. Note that // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the // relevant trust bit isn't set then that means the cert must be considered // distrusted. PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA ? CERTDB_TRUSTED_CA : CERTDB_TRUSTED; if (((flags & (relevantTrustBit|CERTDB_TERMINAL_RECORD))) == CERTDB_TERMINAL_RECORD) { *trustLevel = ActivelyDistrusted; return SECSuccess; } // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't // needed to consider end-entity certs to be their own trust anchors since // Gecko implemented nsICertOverrideService. if (flags & CERTDB_TRUSTED_CA) { *trustLevel = TrustAnchor; return SECSuccess; } } *trustLevel = InheritsTrust; return SECSuccess; }
static PRBool nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage) { CERTCertificate *cc; PRBool ca; SECStatus secrv; unsigned int requiredFlags; unsigned int trustFlags; SECTrustType trustType; CERTCertTrust trust; /* This is for NSS 3.3 functions that do not specify a usage */ if (usage->anyUsage) { return PR_FALSE; /* XXX is this right? */ } cc = (CERTCertificate *)dc->data; ca = usage->nss3lookingForCA; if (!ca) { PRBool trusted; unsigned int failedFlags; secrv = cert_CheckLeafTrust(cc, usage->nss3usage, &failedFlags, &trusted); return secrv == SECSuccess && trusted; } secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags, &trustType); if (secrv != SECSuccess) { return PR_FALSE; } secrv = CERT_GetCertTrust(cc, &trust); if (secrv != SECSuccess) { return PR_FALSE; } if (trustType == trustTypeNone) { /* normally trustTypeNone usages accept any of the given trust bits * being on as acceptable. */ trustFlags = trust.sslFlags | trust.emailFlags | trust.objectSigningFlags; } else { trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType); } return (trustFlags & requiredFlags) == requiredFlags; }
SECStatus AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA, SECOidTag policy, const CERTCertificate* candidateCert, /*out*/ TrustLevel* trustLevel) { MOZ_ASSERT(policy == SEC_OID_X509_ANY_POLICY); MOZ_ASSERT(candidateCert); MOZ_ASSERT(trustLevel); MOZ_ASSERT(mTrustedRoot); if (!candidateCert || !trustLevel || policy != SEC_OID_X509_ANY_POLICY) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } if (!mTrustedRoot) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return SECFailure; } // Handle active distrust of the certificate. CERTCertTrust trust; if (CERT_GetCertTrust(candidateCert, &trust) == SECSuccess) { PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning); // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit, // because we can have active distrust for either type of cert. Note that // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the // relevant trust bit isn't set then that means the cert must be considered // distrusted. PRUint32 relevantTrustBit = endEntityOrCA == MustBeCA ? CERTDB_TRUSTED_CA : CERTDB_TRUSTED; if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD))) == CERTDB_TERMINAL_RECORD) { *trustLevel = ActivelyDistrusted; return SECSuccess; } #ifdef MOZ_B2G_CERTDATA // XXX(Bug 972201): We have to allow the old way of supporting additional // roots until we fix bug 889744. Remove this along with the rest of the // MOZ_B2G_CERTDATA stuff. // For TRUST, we only use the CERTDB_TRUSTED_CA bit, because Gecko hasn't // needed to consider end-entity certs to be their own trust anchors since // Gecko implemented nsICertOverrideService. if (flags & CERTDB_TRUSTED_CA) { *trustLevel = TrustAnchor; return SECSuccess; } #endif } // mTrustedRoot is the only trust anchor for this validation. if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert)) { *trustLevel = TrustAnchor; return SECSuccess; } *trustLevel = InheritsTrust; return SECSuccess; }