Index: net/ssl/client_cert_identity.cc |
diff --git a/net/ssl/client_cert_identity.cc b/net/ssl/client_cert_identity.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..881d0e1d06d03259a7d29d1608fd07864fc20d6f |
--- /dev/null |
+++ b/net/ssl/client_cert_identity.cc |
@@ -0,0 +1,84 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "net/ssl/client_cert_identity.h" |
+ |
+#include "base/bind.h" |
+#include "net/ssl/ssl_private_key.h" |
+ |
+namespace net { |
+ |
+namespace { |
+ |
+void IdentityOwningPrivateKeyCallback( |
+ std::unique_ptr<ClientCertIdentity> identity, |
+ const base::Callback<void(scoped_refptr<SSLPrivateKey>)>& |
+ private_key_callback, |
+ scoped_refptr<SSLPrivateKey> private_key) { |
+ private_key_callback.Run(std::move(private_key)); |
+} |
+ |
+} // namespace |
+ |
+ClientCertIdentity::ClientCertIdentity(scoped_refptr<net::X509Certificate> cert) |
+ : cert_(std::move(cert)) {} |
+ClientCertIdentity::~ClientCertIdentity() = default; |
+ |
+// static |
+void ClientCertIdentity::SelfOwningAcquirePrivateKey( |
+ std::unique_ptr<ClientCertIdentity> self, |
+ const base::Callback<void(scoped_refptr<SSLPrivateKey>)>& |
+ private_key_callback) { |
+ ClientCertIdentity* self_ptr = self.get(); |
+ auto wrapped_private_key_callback = |
+ base::Bind(&IdentityOwningPrivateKeyCallback, base::Passed(&self), |
+ private_key_callback); |
+ self_ptr->AcquirePrivateKey(wrapped_private_key_callback); |
+} |
+ |
+void ClientCertIdentity::SetIntermediates( |
+ X509Certificate::OSCertHandles intermediates) { |
+ cert_ = |
+ X509Certificate::CreateFromHandle(cert_->os_cert_handle(), intermediates); |
+ // |cert_->os_cert_handle()| was already successfully parsed, so this should |
+ // never fail. |
+ DCHECK(cert_); |
+} |
+ |
+ClientCertIdentitySorter::ClientCertIdentitySorter() |
+ : now_(base::Time::Now()) {} |
+ |
+bool ClientCertIdentitySorter::operator()( |
+ const std::unique_ptr<ClientCertIdentity>& a_identity, |
+ const std::unique_ptr<ClientCertIdentity>& b_identity) const { |
+ X509Certificate* a = a_identity->certificate(); |
+ X509Certificate* b = b_identity->certificate(); |
+ DCHECK(a); |
+ DCHECK(b); |
+ |
+ // Certificates that are expired/not-yet-valid are sorted last. |
+ bool a_is_valid = now_ >= a->valid_start() && now_ <= a->valid_expiry(); |
+ bool b_is_valid = now_ >= b->valid_start() && now_ <= b->valid_expiry(); |
+ if (a_is_valid != b_is_valid) |
+ return a_is_valid && !b_is_valid; |
+ |
+ // Certificates with longer expirations appear as higher priority (less |
+ // than) certificates with shorter expirations. |
+ if (a->valid_expiry() != b->valid_expiry()) |
+ return a->valid_expiry() > b->valid_expiry(); |
+ |
+ // If the expiration dates are equivalent, certificates that were issued |
+ // more recently should be prioritized over older certificates. |
+ if (a->valid_start() != b->valid_start()) |
+ return a->valid_start() > b->valid_start(); |
+ |
+ // Otherwise, prefer client certificates with shorter chains. |
+ const X509Certificate::OSCertHandles& a_intermediates = |
+ a->GetIntermediateCertificates(); |
+ const X509Certificate::OSCertHandles& b_intermediates = |
+ b->GetIntermediateCertificates(); |
+ return a_intermediates.size() < b_intermediates.size(); |
+} |
+ |
+} // namespace net |