| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/ssl/openssl_client_key_store.h" | 5 #include "net/ssl/openssl_client_key_store.h" |
| 6 | 6 |
| 7 #include <openssl/evp.h> | 7 #include <openssl/evp.h> |
| 8 #include <openssl/mem.h> |
| 8 #include <openssl/x509.h> | 9 #include <openssl/x509.h> |
| 9 | 10 |
| 10 #include <algorithm> | 11 #include <utility> |
| 11 #include <memory> | |
| 12 | 12 |
| 13 #include "base/memory/singleton.h" | 13 #include "base/memory/singleton.h" |
| 14 #include "crypto/auto_cbb.h" |
| 15 #include "crypto/scoped_openssl_types.h" |
| 14 #include "net/cert/x509_certificate.h" | 16 #include "net/cert/x509_certificate.h" |
| 17 #include "net/ssl/ssl_private_key.h" |
| 15 | 18 |
| 16 namespace net { | 19 namespace net { |
| 17 | 20 |
| 18 namespace { | 21 namespace { |
| 19 | 22 |
| 20 // Return the EVP_PKEY holding the public key of a given certificate. | 23 // Serializes the SubjectPublicKeyInfo for |cert|. |
| 21 // |cert| is a certificate. | 24 bool GetCertificateSPKI(const X509Certificate* cert, std::string* spki) { |
| 22 // Returns a scoped EVP_PKEY for it. | 25 crypto::ScopedEVP_PKEY pkey(X509_get_pubkey(cert->os_cert_handle())); |
| 23 crypto::ScopedEVP_PKEY GetOpenSSLPublicKey(const X509Certificate* cert) { | 26 if (!pkey) { |
| 24 // X509_PUBKEY_get() increments the reference count of its result. | |
| 25 // Unlike X509_get_X509_PUBKEY() which simply returns a direct pointer. | |
| 26 EVP_PKEY* pkey = | |
| 27 X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle())); | |
| 28 if (!pkey) | |
| 29 LOG(ERROR) << "Can't extract private key from certificate!"; | 27 LOG(ERROR) << "Can't extract private key from certificate!"; |
| 30 return crypto::ScopedEVP_PKEY(pkey); | 28 return false; |
| 29 } |
| 30 |
| 31 crypto::AutoCBB cbb; |
| 32 uint8_t* der; |
| 33 size_t der_len; |
| 34 if (!CBB_init(cbb.get(), 0) || |
| 35 !EVP_marshal_public_key(cbb.get(), pkey.get()) || |
| 36 !CBB_finish(cbb.get(), &der, &der_len)) { |
| 37 return false; |
| 38 } |
| 39 |
| 40 spki->assign(reinterpret_cast<char*>(der), |
| 41 reinterpret_cast<char*>(der) + der_len); |
| 42 OPENSSL_free(der); |
| 43 return true; |
| 31 } | 44 } |
| 32 | 45 |
| 33 } // namespace | 46 } // namespace |
| 34 | 47 |
| 35 OpenSSLClientKeyStore::OpenSSLClientKeyStore() { | |
| 36 } | |
| 37 | |
| 38 OpenSSLClientKeyStore::~OpenSSLClientKeyStore() { | |
| 39 } | |
| 40 | |
| 41 OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, EVP_PKEY* priv_key) | |
| 42 : public_key(pub_key), private_key(priv_key) { | |
| 43 EVP_PKEY_up_ref(pub_key); | |
| 44 EVP_PKEY_up_ref(priv_key); | |
| 45 } | |
| 46 | |
| 47 OpenSSLClientKeyStore::KeyPair::~KeyPair() { | |
| 48 } | |
| 49 | |
| 50 OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other) | |
| 51 : public_key(other.public_key.get()), private_key(other.private_key.get()) { | |
| 52 EVP_PKEY_up_ref(public_key.get()); | |
| 53 EVP_PKEY_up_ref(private_key.get()); | |
| 54 } | |
| 55 | |
| 56 void OpenSSLClientKeyStore::KeyPair::operator=(KeyPair other) { | |
| 57 swap(other); | |
| 58 } | |
| 59 | |
| 60 void OpenSSLClientKeyStore::KeyPair::swap(KeyPair& other) { | |
| 61 using std::swap; | |
| 62 swap(public_key, other.public_key); | |
| 63 swap(private_key, other.private_key); | |
| 64 } | |
| 65 | |
| 66 int OpenSSLClientKeyStore::FindKeyPairIndex(EVP_PKEY* public_key) { | |
| 67 if (!public_key) | |
| 68 return -1; | |
| 69 for (size_t n = 0; n < pairs_.size(); ++n) { | |
| 70 if (EVP_PKEY_cmp(pairs_[n].public_key.get(), public_key) == 1) | |
| 71 return static_cast<int>(n); | |
| 72 } | |
| 73 return -1; | |
| 74 } | |
| 75 | |
| 76 void OpenSSLClientKeyStore::AddKeyPair(EVP_PKEY* pub_key, | |
| 77 EVP_PKEY* private_key) { | |
| 78 int index = FindKeyPairIndex(pub_key); | |
| 79 if (index < 0) | |
| 80 pairs_.push_back(KeyPair(pub_key, private_key)); | |
| 81 } | |
| 82 | |
| 83 // Common code for OpenSSLClientKeyStore. Shared by all OpenSSL-based | |
| 84 // builds. | |
| 85 bool OpenSSLClientKeyStore::RecordClientCertPrivateKey( | |
| 86 const X509Certificate* client_cert, | |
| 87 EVP_PKEY* private_key) { | |
| 88 // Sanity check. | |
| 89 if (!client_cert || !private_key) | |
| 90 return false; | |
| 91 | |
| 92 // Get public key from certificate. | |
| 93 crypto::ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert)); | |
| 94 if (!pub_key.get()) | |
| 95 return false; | |
| 96 | |
| 97 AddKeyPair(pub_key.get(), private_key); | |
| 98 return true; | |
| 99 } | |
| 100 | |
| 101 crypto::ScopedEVP_PKEY OpenSSLClientKeyStore::FetchClientCertPrivateKey( | |
| 102 const X509Certificate* client_cert) { | |
| 103 if (!client_cert) | |
| 104 return crypto::ScopedEVP_PKEY(); | |
| 105 | |
| 106 crypto::ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert)); | |
| 107 if (!pub_key.get()) | |
| 108 return crypto::ScopedEVP_PKEY(); | |
| 109 | |
| 110 int index = FindKeyPairIndex(pub_key.get()); | |
| 111 if (index < 0) | |
| 112 return crypto::ScopedEVP_PKEY(); | |
| 113 | |
| 114 EVP_PKEY_up_ref(pairs_[index].private_key.get()); | |
| 115 return crypto::ScopedEVP_PKEY(pairs_[index].private_key.get()); | |
| 116 } | |
| 117 | |
| 118 void OpenSSLClientKeyStore::Flush() { | |
| 119 pairs_.clear(); | |
| 120 } | |
| 121 | |
| 122 OpenSSLClientKeyStore* OpenSSLClientKeyStore::GetInstance() { | 48 OpenSSLClientKeyStore* OpenSSLClientKeyStore::GetInstance() { |
| 123 return base::Singleton<OpenSSLClientKeyStore>::get(); | 49 return base::Singleton<OpenSSLClientKeyStore>::get(); |
| 124 } | 50 } |
| 125 | 51 |
| 52 bool OpenSSLClientKeyStore::RecordClientCertPrivateKey( |
| 53 const X509Certificate* client_cert, |
| 54 scoped_refptr<SSLPrivateKey> private_key) { |
| 55 DCHECK(client_cert); |
| 56 DCHECK(private_key); |
| 57 |
| 58 std::string spki; |
| 59 if (!GetCertificateSPKI(client_cert, &spki)) |
| 60 return false; |
| 61 |
| 62 key_map_[spki] = std::move(private_key); |
| 63 return true; |
| 64 } |
| 65 |
| 66 scoped_refptr<SSLPrivateKey> OpenSSLClientKeyStore::FetchClientCertPrivateKey( |
| 67 const X509Certificate* client_cert) { |
| 68 DCHECK(client_cert); |
| 69 |
| 70 std::string spki; |
| 71 if (!GetCertificateSPKI(client_cert, &spki)) |
| 72 return nullptr; |
| 73 |
| 74 auto iter = key_map_.find(spki); |
| 75 if (iter == key_map_.end()) |
| 76 return nullptr; |
| 77 |
| 78 return iter->second; |
| 79 } |
| 80 |
| 81 void OpenSSLClientKeyStore::Flush() { |
| 82 key_map_.clear(); |
| 83 } |
| 84 |
| 85 OpenSSLClientKeyStore::OpenSSLClientKeyStore() {} |
| 86 |
| 87 OpenSSLClientKeyStore::~OpenSSLClientKeyStore() {} |
| 88 |
| 126 } // namespace net | 89 } // namespace net |
| 127 | |
| 128 | |
| OLD | NEW |