blob: 0bc97beb48e55670ac1d5901b7933d0f35f0574c [file] [log] [blame]
[email protected]ede323ea2013-03-02 22:54:411// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]5cf67592013-04-02 17:42:125#include "net/ssl/openssl_client_key_store.h"
[email protected]ede323ea2013-03-02 22:54:416
7#include <openssl/evp.h>
8#include <openssl/x509.h>
dcheng9961abd2014-10-14 22:42:049#include <algorithm>
[email protected]ede323ea2013-03-02 22:54:4110
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/singleton.h"
[email protected]6e7845ae2013-03-29 21:48:1113#include "net/cert/x509_certificate.h"
[email protected]ede323ea2013-03-02 22:54:4114
15namespace net {
16
17namespace {
18
[email protected]ede323ea2013-03-02 22:54:4119// Return the EVP_PKEY holding the public key of a given certificate.
20// |cert| is a certificate.
21// Returns a scoped EVP_PKEY for it.
[email protected]c50776672014-07-11 20:26:3522crypto::ScopedEVP_PKEY GetOpenSSLPublicKey(const X509Certificate* cert) {
[email protected]ede323ea2013-03-02 22:54:4123 // X509_PUBKEY_get() increments the reference count of its result.
24 // Unlike X509_get_X509_PUBKEY() which simply returns a direct pointer.
25 EVP_PKEY* pkey =
26 X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle()));
27 if (!pkey)
28 LOG(ERROR) << "Can't extract private key from certificate!";
[email protected]c50776672014-07-11 20:26:3529 return crypto::ScopedEVP_PKEY(pkey);
[email protected]ede323ea2013-03-02 22:54:4130}
31
32} // namespace
33
34OpenSSLClientKeyStore::OpenSSLClientKeyStore() {
35}
36
37OpenSSLClientKeyStore::~OpenSSLClientKeyStore() {
38}
39
davidbenc681bac2015-05-13 22:14:5740OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, EVP_PKEY* priv_key)
41 : public_key(EVP_PKEY_up_ref(pub_key)),
42 private_key(EVP_PKEY_up_ref(priv_key)) {
[email protected]ede323ea2013-03-02 22:54:4143}
44
45OpenSSLClientKeyStore::KeyPair::~KeyPair() {
[email protected]ede323ea2013-03-02 22:54:4146}
47
[email protected]24176af2014-08-14 09:31:0448OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other)
davidbenc681bac2015-05-13 22:14:5749 : public_key(EVP_PKEY_up_ref(other.public_key.get())),
50 private_key(EVP_PKEY_up_ref(other.private_key.get())) {
[email protected]ede323ea2013-03-02 22:54:4151}
52
dcheng9961abd2014-10-14 22:42:0453void OpenSSLClientKeyStore::KeyPair::operator=(KeyPair other) {
54 swap(other);
55}
56
57void OpenSSLClientKeyStore::KeyPair::swap(KeyPair& other) {
58 using std::swap;
59 swap(public_key, other.public_key);
60 swap(private_key, other.private_key);
[email protected]ede323ea2013-03-02 22:54:4161}
62
63int OpenSSLClientKeyStore::FindKeyPairIndex(EVP_PKEY* public_key) {
64 if (!public_key)
65 return -1;
66 for (size_t n = 0; n < pairs_.size(); ++n) {
[email protected]24176af2014-08-14 09:31:0467 if (EVP_PKEY_cmp(pairs_[n].public_key.get(), public_key) == 1)
[email protected]ede323ea2013-03-02 22:54:4168 return static_cast<int>(n);
69 }
70 return -1;
71}
72
73void OpenSSLClientKeyStore::AddKeyPair(EVP_PKEY* pub_key,
74 EVP_PKEY* private_key) {
75 int index = FindKeyPairIndex(pub_key);
76 if (index < 0)
77 pairs_.push_back(KeyPair(pub_key, private_key));
78}
79
80// Common code for OpenSSLClientKeyStore. Shared by all OpenSSL-based
81// builds.
82bool OpenSSLClientKeyStore::RecordClientCertPrivateKey(
83 const X509Certificate* client_cert,
84 EVP_PKEY* private_key) {
85 // Sanity check.
86 if (!client_cert || !private_key)
87 return false;
88
89 // Get public key from certificate.
[email protected]c50776672014-07-11 20:26:3590 crypto::ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert));
[email protected]ede323ea2013-03-02 22:54:4191 if (!pub_key.get())
92 return false;
93
94 AddKeyPair(pub_key.get(), private_key);
95 return true;
96}
97
[email protected]97a854f2014-07-29 07:51:3698crypto::ScopedEVP_PKEY OpenSSLClientKeyStore::FetchClientCertPrivateKey(
99 const X509Certificate* client_cert) {
[email protected]ede323ea2013-03-02 22:54:41100 if (!client_cert)
[email protected]97a854f2014-07-29 07:51:36101 return crypto::ScopedEVP_PKEY();
[email protected]ede323ea2013-03-02 22:54:41102
[email protected]c50776672014-07-11 20:26:35103 crypto::ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert));
[email protected]ede323ea2013-03-02 22:54:41104 if (!pub_key.get())
[email protected]97a854f2014-07-29 07:51:36105 return crypto::ScopedEVP_PKEY();
[email protected]ede323ea2013-03-02 22:54:41106
107 int index = FindKeyPairIndex(pub_key.get());
108 if (index < 0)
[email protected]97a854f2014-07-29 07:51:36109 return crypto::ScopedEVP_PKEY();
[email protected]ede323ea2013-03-02 22:54:41110
davidbenc681bac2015-05-13 22:14:57111 return crypto::ScopedEVP_PKEY(
112 EVP_PKEY_up_ref(pairs_[index].private_key.get()));
[email protected]ede323ea2013-03-02 22:54:41113}
114
115void OpenSSLClientKeyStore::Flush() {
116 pairs_.clear();
117}
118
119OpenSSLClientKeyStore* OpenSSLClientKeyStore::GetInstance() {
120 return Singleton<OpenSSLClientKeyStore>::get();
121}
122
123} // namespace net
124
125