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

Unified Diff: net/base/x509_certificate_mac.cc

Issue 2899005: Rewrite X509Certificate::SupportsSSLClientAuth to be more accurate (Closed)
Patch Set: Rearrange a few comments Created 10 years, 5 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/x509_certificate_mac.cc
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index 8d7970ae001eaf1ce654869817718e36bba84271..08da804c9a2a74f6db8447e8d6cc2c6f2de508a4 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -358,6 +358,20 @@ OSStatus CopyCertChain(SecCertificateRef cert_handle,
return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
}
+// Returns true if |purpose| is listed as allowed in |usage|. This
+// function also considers the "Any" purpose. If the attribute is
+// present and empty, we return false.
+bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage,
+ const CSSM_OID* purpose) {
+ for (unsigned p = 0; p < usage->numPurposes; ++p) {
+ if (CSSMOIDEqual(&usage->purposes[p], purpose))
+ return true;
+ if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny))
+ return true;
+ }
+ return false;
+}
+
} // namespace
void X509Certificate::Initialize() {
@@ -699,25 +713,38 @@ bool X509Certificate::SupportsSSLClientAuth() const {
CSSMFields fields;
if (GetCertFields(cert_handle_, &fields) != noErr)
return false;
+
+ // Gather the extensions we care about. We do not support
+ // CSSMOID_NetscapeCertType on OS X.
+ const CE_ExtendedKeyUsage* ext_key_usage = NULL;
+ const CE_KeyUsage* key_usage = NULL;
for (unsigned f = 0; f < fields.num_of_fields; ++f) {
const CSSM_FIELD& field = fields.fields[f];
const CSSM_X509_EXTENSION* ext =
reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data);
- if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) {
- const CE_ExtendedKeyUsage* usage =
+ if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_KeyUsage)) {
+ key_usage = reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue);
+ } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) {
+ ext_key_usage =
reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
- for (unsigned p = 0; p < usage->numPurposes; ++p) {
- if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ClientAuth))
- return true;
- }
- } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_NetscapeCertType)) {
- uint16_t flags =
- *reinterpret_cast<const uint16_t*>(ext->value.parsedValue);
- if (flags & CE_NCT_SSL_Client)
- return true;
}
}
- return false;
+
+ // RFC5280 says to take the intersection of the two extensions.
+ //
+ // Our underlying crypto libraries don't expose
+ // ClientCertificateType, so for now we will not support fixed
+ // Diffie-Hellman mechanisms. For rsa_sign, we need the
+ // digitalSignature bit.
+ //
+ // In particular, if a key has the nonRepudiation bit and not the
+ // digitalSignature one, we will not offer it to the user.
+ if (key_usage && !((*key_usage) & CE_KU_DigitalSignature))
+ return false;
+ if (ext_key_usage && !ExtendedKeyUsageAllows(ext_key_usage,
+ &CSSMOID_ClientAuth))
+ return false;
+ return true;
}
bool X509Certificate::IsIssuedBy(
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698