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 |