Index: net/base/cert_verify_proc_nss.cc |
diff --git a/net/base/cert_verify_proc_nss.cc b/net/base/cert_verify_proc_nss.cc |
index 3108555455e1023d385ec0fb621b4d64c7d2f182..afe795f5ea7a77cf00ecd4b415fdabc5e8906541 100644 |
--- a/net/base/cert_verify_proc_nss.cc |
+++ b/net/base/cert_verify_proc_nss.cc |
@@ -576,27 +576,6 @@ SECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle) { |
return SECOID_AddEntry(&od); |
} |
-bool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle, |
- SECOidTag ev_policy_tag) { |
- CERTCertificatePolicies* policies = DecodeCertPolicies(cert_handle); |
- if (!policies) { |
- LOG(ERROR) << "Cert has no policies extension or extension couldn't be " |
- "decoded."; |
- return false; |
- } |
- ScopedCERTCertificatePolicies scoped_policies(policies); |
- CERTPolicyInfo** policy_infos = policies->policyInfos; |
- while (*policy_infos != NULL) { |
- CERTPolicyInfo* policy_info = *policy_infos++; |
- SECOidTag oid_tag = policy_info->oid; |
- if (oid_tag == SEC_OID_UNKNOWN) |
- continue; |
- if (oid_tag == ev_policy_tag) |
- return true; |
- } |
- return false; |
-} |
- |
SHA1Fingerprint CertPublicKeyHash(CERTCertificate* cert) { |
SHA1Fingerprint hash; |
SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data, |
@@ -617,6 +596,35 @@ void AppendPublicKeyHashes(CERTCertList* cert_list, |
hashes->push_back(CertPublicKeyHash(root_cert)); |
} |
+// Returns true if |cert_handle| contains a policy OID that is an EV policy |
+// OID according to |metadata|, storing the resulting policy OID in |
+// |*ev_policy_oid|. A true return is not sufficient to establish that a |
+// certificate is EV, but a false return is sufficient to establish the |
+// certificate cannot be EV. |
+bool IsEVCandidate(EVRootCAMetadata* metadata, |
agl
2012/08/15 22:57:53
Is the assumption that there'll only be one EV OID
Ryan Sleevi
2012/08/15 23:04:58
That's what I'm not sure about. That's certainly t
|
+ CERTCertificate* cert_handle, |
+ SECOidTag* ev_policy_oid) { |
+ DCHECK(cert_handle); |
+ ScopedCERTCertificatePolicies policies(DecodeCertPolicies(cert_handle)); |
+ if (!policies.get()) |
+ return false; |
+ |
+ CERTPolicyInfo** policy_infos = policies->policyInfos; |
+ while (*policy_infos != NULL) { |
+ CERTPolicyInfo* policy_info = *policy_infos++; |
+ // If the Policy OID is unknown, that implicitly means it has not been |
+ // registered as an EV policy. |
+ if (policy_info->oid == SEC_OID_UNKNOWN) |
+ continue; |
+ if (metadata->IsEVPolicyOID(policy_info->oid)) { |
+ *ev_policy_oid = policy_info->oid; |
+ return true; |
+ } |
+ } |
+ |
+ return false; |
+} |
+ |
// Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp |
// and nsNSSCertHelper.cpp) to learn how to verify EV certificate. |
// TODO(wtc): A possible optimization is that we get the trust anchor from |
@@ -627,6 +635,11 @@ void AppendPublicKeyHashes(CERTCertList* cert_list, |
bool VerifyEV(CERTCertificate* cert_handle, int flags, CRLSet* crl_set) { |
EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); |
+ SECOidTag ev_policy_oid = SEC_OID_UNKNOWN; |
+ bool is_ev_candidate = IsEVCandidate(metadata, cert_handle, &ev_policy_oid); |
+ if (!is_ev_candidate) |
+ return false; |
+ |
CERTValOutParam cvout[3]; |
int cvout_index = 0; |
cvout[cvout_index].type = cert_po_certList; |
@@ -640,12 +653,16 @@ bool VerifyEV(CERTCertificate* cert_handle, int flags, CRLSet* crl_set) { |
cvout[cvout_index].type = cert_po_end; |
ScopedCERTValOutParam scoped_cvout(cvout); |
+ bool rev_checking_enabled = |
+ (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) || |
+ (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); |
+ |
SECStatus status = PKIXVerifyCert( |
cert_handle, |
- flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED, |
+ rev_checking_enabled, |
flags & X509Certificate::VERIFY_CERT_IO_ENABLED, |
- metadata->GetPolicyOIDs(), |
- metadata->NumPolicyOIDs(), |
+ &ev_policy_oid, |
+ 1, |
cvout); |
if (status != SECSuccess) |
return false; |
@@ -669,17 +686,7 @@ bool VerifyEV(CERTCertificate* cert_handle, int flags, CRLSet* crl_set) { |
SHA1Fingerprint fingerprint = |
X509Certificate::CalculateFingerprint(root_ca); |
- std::vector<SECOidTag> ev_policy_tags; |
- if (!metadata->GetPolicyOIDsForCA(fingerprint, &ev_policy_tags)) |
- return false; |
- DCHECK(!ev_policy_tags.empty()); |
- |
- for (std::vector<SECOidTag>::const_iterator |
- i = ev_policy_tags.begin(); i != ev_policy_tags.end(); ++i) { |
- if (CheckCertPolicies(cert_handle, *i)) |
- return true; |
- } |
- return false; |
+ return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid); |
} |
} // namespace |
@@ -773,6 +780,11 @@ int CertVerifyProcNSS::VerifyInternal(X509Certificate* cert, |
if ((flags & X509Certificate::VERIFY_EV_CERT) && |
VerifyEV(cert_handle, flags, crl_set)) { |
verify_result->cert_status |= CERT_STATUS_IS_EV; |
+ if (cert_io_enabled && |
+ (flags & (X509Certificate::VERIFY_REV_CHECKING_ENABLED | |
+ X509Certificate::VERIFY_REV_CHECKING_ENABLED_EV_ONLY)) { |
+ verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
+ } |
} |
return OK; |