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

Unified Diff: net/ssl/client_cert_store_mac.cc

Issue 2910893002: Improved support for loading client certificates on smart cards on macOS
Patch Set: Improved support for loading client certificates on smart cards on macOS Created 3 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/ssl/client_cert_store_mac.cc
diff --git a/net/ssl/client_cert_store_mac.cc b/net/ssl/client_cert_store_mac.cc
index 7fadb337f1e7735ae8ffd340c81c93c95588d7c4..1027aad86dc4b8321df5f6b6caafce2ce38549d9 100644
--- a/net/ssl/client_cert_store_mac.cc
+++ b/net/ssl/client_cert_store_mac.cc
@@ -12,6 +12,8 @@
#include <algorithm>
#include <string>
+#include <utility>
+#include <vector>
#include "base/callback.h"
#include "base/logging.h"
@@ -231,6 +233,37 @@ void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
sort(sort_begin, sort_end, x509_util::ClientCertSorter());
}
+// Given an |identity|, identifies its corresponding certificate, and either
+// adds it to |regular_certs| or assigns it to |preferred_cert|, if the
+// |identity| matches the |preferred_identity|.
+void AddIdentity(SecIdentityRef identity,
+ SecIdentityRef preferred_identity,
+ CertificateList* regular_certs,
+ scoped_refptr<X509Certificate>* preferred_cert) {
+ OSStatus err;
+ ScopedCFTypeRef<SecCertificateRef> cert_handle;
+ err = SecIdentityCopyCertificate(identity, cert_handle.InitializeInto());
+ if (err != noErr)
+ return;
+
+ if (!SupportsSSLClientAuth(cert_handle))
+ return;
+
+ scoped_refptr<X509Certificate> cert(
+ x509_util::CreateX509CertificateFromSecCertificate(
+ cert_handle, std::vector<SecCertificateRef>()));
+ if (!cert)
+ return;
+
+ if (preferred_identity && CFEqual(preferred_identity, identity)) {
+ // Only one certificate should match.
+ DCHECK(!preferred_cert->get());
+ *preferred_cert = cert;
+ } else {
+ regular_certs->push_back(cert);
+ }
+}
+
} // namespace
ClientCertStoreMac::ClientCertStoreMac() {}
@@ -284,29 +317,7 @@ void ClientCertStoreMac::GetClientCerts(
if (err)
break;
ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity);
-
- SecCertificateRef cert_handle;
- err = SecIdentityCopyCertificate(identity, &cert_handle);
- if (err != noErr)
- continue;
- ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
-
- if (!SupportsSSLClientAuth(cert_handle))
- continue;
-
- scoped_refptr<X509Certificate> cert(
- x509_util::CreateX509CertificateFromSecCertificate(
- cert_handle, std::vector<SecCertificateRef>()));
- if (!cert)
- continue;
-
- if (preferred_identity && CFEqual(preferred_identity, identity)) {
- // Only one certificate should match.
- DCHECK(!preferred_cert.get());
- preferred_cert = cert;
- } else {
- regular_certs.push_back(cert);
- }
+ AddIdentity(identity, preferred_identity, &regular_certs, &preferred_cert);
}
if (err != errSecItemNotFound) {
@@ -315,6 +326,36 @@ void ClientCertStoreMac::GetClientCerts(
return;
}
+ // macOS provides two ways to search for identities. SecIdentitySearchCreate()
+ // is deprecated, as it relies on CSSM_KEYUSE_SIGN (part of the deprecated
+ // CDSM/CSSA implementation), but is necessary to return some certificates
+ // that would otherwise not be returned by SecItemCopyMatching(), which is the
+ // non-deprecated way. However, SecIdentitySearchCreate() will not return all
+ // items, particularly smart-card based identities, so it's necessary to call
+ // both functions.
+ static const void* kKeys[] = {
+ kSecClass, kSecMatchLimit, kSecReturnRef, kSecAttrCanSign,
+ };
+ static const void* kValues[] = {
+ kSecClassIdentity, kSecMatchLimitAll, kCFBooleanTrue, kCFBooleanTrue,
+ };
+ ScopedCFTypeRef<CFDictionaryRef> query(CFDictionaryCreate(
+ kCFAllocatorDefault, kKeys, kValues, arraysize(kValues),
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ ScopedCFTypeRef<CFArrayRef> result;
+ {
+ base::AutoLock lock(crypto::GetMacSecurityServicesLock());
+ err = SecItemCopyMatching(
+ query, reinterpret_cast<CFTypeRef*>(result.InitializeInto()));
+ }
+ if (!err) {
+ for (CFIndex i = 0; i < CFArrayGetCount(result); i++) {
+ void* item = const_cast<void*>(CFArrayGetValueAtIndex(result, i));
+ AddIdentity(reinterpret_cast<SecIdentityRef>(item), preferred_identity,
+ &regular_certs, &preferred_cert);
+ }
+ }
+
CertificateList selected_certs;
GetClientCertsImpl(preferred_cert, regular_certs, request, true,
&selected_certs);
« 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