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/x509.h> | 8 #include <openssl/x509.h> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/memory/singleton.h" | 11 #include "base/memory/singleton.h" |
12 #include "net/cert/x509_certificate.h" | 12 #include "net/cert/x509_certificate.h" |
13 | 13 |
14 namespace net { | 14 namespace net { |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
18 // Increment the reference count of a given EVP_PKEY. This function | |
19 // is similar to EVP_PKEY_dup which is not available from the OpenSSL | |
20 // version used by Chromium at the moment. Its name is distinct to | |
21 // avoid compiler warnings about ambiguous function calls at caller | |
22 // sites. | |
23 EVP_PKEY* CopyEVP_PKEY(EVP_PKEY* key) { | |
24 if (key) | |
25 CRYPTO_add(&key->references, 1, CRYPTO_LOCK_EVP_PKEY); | |
26 return key; | |
27 } | |
28 | |
29 // Return the EVP_PKEY holding the public key of a given certificate. | 18 // Return the EVP_PKEY holding the public key of a given certificate. |
30 // |cert| is a certificate. | 19 // |cert| is a certificate. |
31 // Returns a scoped EVP_PKEY for it. | 20 // Returns a scoped EVP_PKEY for it. |
32 crypto::ScopedEVP_PKEY GetOpenSSLPublicKey(const X509Certificate* cert) { | 21 crypto::ScopedEVP_PKEY GetOpenSSLPublicKey(const X509Certificate* cert) { |
33 // X509_PUBKEY_get() increments the reference count of its result. | 22 // X509_PUBKEY_get() increments the reference count of its result. |
34 // Unlike X509_get_X509_PUBKEY() which simply returns a direct pointer. | 23 // Unlike X509_get_X509_PUBKEY() which simply returns a direct pointer. |
35 EVP_PKEY* pkey = | 24 EVP_PKEY* pkey = |
36 X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle())); | 25 X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle())); |
37 if (!pkey) | 26 if (!pkey) |
38 LOG(ERROR) << "Can't extract private key from certificate!"; | 27 LOG(ERROR) << "Can't extract private key from certificate!"; |
39 return crypto::ScopedEVP_PKEY(pkey); | 28 return crypto::ScopedEVP_PKEY(pkey); |
40 } | 29 } |
41 | 30 |
42 } // namespace | 31 } // namespace |
43 | 32 |
44 OpenSSLClientKeyStore::OpenSSLClientKeyStore() { | 33 OpenSSLClientKeyStore::OpenSSLClientKeyStore() { |
45 } | 34 } |
46 | 35 |
47 OpenSSLClientKeyStore::~OpenSSLClientKeyStore() { | 36 OpenSSLClientKeyStore::~OpenSSLClientKeyStore() { |
48 } | 37 } |
49 | 38 |
50 OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, | 39 OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, |
51 EVP_PKEY* priv_key) { | 40 EVP_PKEY* priv_key) |
52 public_key = CopyEVP_PKEY(pub_key); | 41 : public_key(EVP_PKEY_dup(pub_key)), |
53 private_key = CopyEVP_PKEY(priv_key); | 42 private_key(EVP_PKEY_dup(priv_key)) { |
54 } | 43 } |
55 | 44 |
56 OpenSSLClientKeyStore::KeyPair::~KeyPair() { | 45 OpenSSLClientKeyStore::KeyPair::~KeyPair() { |
57 EVP_PKEY_free(public_key); | |
58 EVP_PKEY_free(private_key); | |
59 } | 46 } |
60 | 47 |
61 OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other) { | 48 OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other) |
62 public_key = CopyEVP_PKEY(other.public_key); | 49 : public_key(EVP_PKEY_dup(other.public_key.get())), |
63 private_key = CopyEVP_PKEY(other.private_key); | 50 private_key(EVP_PKEY_dup(other.private_key.get())) { |
64 } | 51 } |
65 | 52 |
66 void OpenSSLClientKeyStore::KeyPair::operator=(const KeyPair& other) { | 53 void OpenSSLClientKeyStore::KeyPair::operator=(const KeyPair& other) { |
67 EVP_PKEY* old_public_key = public_key; | 54 // Use a temporary ScopedEVP_PKEY because scoped_ptr does not allow resetting |
68 EVP_PKEY* old_private_key = private_key; | 55 // to the current value, even though it's safe here. |
69 public_key = CopyEVP_PKEY(other.public_key); | 56 crypto::ScopedEVP_PKEY public_key_tmp(EVP_PKEY_dup(other.public_key.get())); |
70 private_key = CopyEVP_PKEY(other.private_key); | 57 crypto::ScopedEVP_PKEY private_key_tmp(EVP_PKEY_dup(other.private_key.get())); |
71 EVP_PKEY_free(old_private_key); | 58 public_key.reset(); |
72 EVP_PKEY_free(old_public_key); | 59 public_key = public_key_tmp.Pass(); |
| 60 private_key.reset(); |
| 61 private_key = private_key_tmp.Pass(); |
73 } | 62 } |
74 | 63 |
75 int OpenSSLClientKeyStore::FindKeyPairIndex(EVP_PKEY* public_key) { | 64 int OpenSSLClientKeyStore::FindKeyPairIndex(EVP_PKEY* public_key) { |
76 if (!public_key) | 65 if (!public_key) |
77 return -1; | 66 return -1; |
78 for (size_t n = 0; n < pairs_.size(); ++n) { | 67 for (size_t n = 0; n < pairs_.size(); ++n) { |
79 if (EVP_PKEY_cmp(pairs_[n].public_key, public_key) == 1) | 68 if (EVP_PKEY_cmp(pairs_[n].public_key.get(), public_key) == 1) |
80 return static_cast<int>(n); | 69 return static_cast<int>(n); |
81 } | 70 } |
82 return -1; | 71 return -1; |
83 } | 72 } |
84 | 73 |
85 void OpenSSLClientKeyStore::AddKeyPair(EVP_PKEY* pub_key, | 74 void OpenSSLClientKeyStore::AddKeyPair(EVP_PKEY* pub_key, |
86 EVP_PKEY* private_key) { | 75 EVP_PKEY* private_key) { |
87 int index = FindKeyPairIndex(pub_key); | 76 int index = FindKeyPairIndex(pub_key); |
88 if (index < 0) | 77 if (index < 0) |
89 pairs_.push_back(KeyPair(pub_key, private_key)); | 78 pairs_.push_back(KeyPair(pub_key, private_key)); |
(...skipping 23 matching lines...) Expand all Loading... |
113 return crypto::ScopedEVP_PKEY(); | 102 return crypto::ScopedEVP_PKEY(); |
114 | 103 |
115 crypto::ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert)); | 104 crypto::ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert)); |
116 if (!pub_key.get()) | 105 if (!pub_key.get()) |
117 return crypto::ScopedEVP_PKEY(); | 106 return crypto::ScopedEVP_PKEY(); |
118 | 107 |
119 int index = FindKeyPairIndex(pub_key.get()); | 108 int index = FindKeyPairIndex(pub_key.get()); |
120 if (index < 0) | 109 if (index < 0) |
121 return crypto::ScopedEVP_PKEY(); | 110 return crypto::ScopedEVP_PKEY(); |
122 | 111 |
123 return crypto::ScopedEVP_PKEY(CopyEVP_PKEY(pairs_[index].private_key)); | 112 return crypto::ScopedEVP_PKEY(EVP_PKEY_dup(pairs_[index].private_key.get())); |
124 } | 113 } |
125 | 114 |
126 void OpenSSLClientKeyStore::Flush() { | 115 void OpenSSLClientKeyStore::Flush() { |
127 pairs_.clear(); | 116 pairs_.clear(); |
128 } | 117 } |
129 | 118 |
130 OpenSSLClientKeyStore* OpenSSLClientKeyStore::GetInstance() { | 119 OpenSSLClientKeyStore* OpenSSLClientKeyStore::GetInstance() { |
131 return Singleton<OpenSSLClientKeyStore>::get(); | 120 return Singleton<OpenSSLClientKeyStore>::get(); |
132 } | 121 } |
133 | 122 |
134 } // namespace net | 123 } // namespace net |
135 | 124 |
136 | 125 |
OLD | NEW |