diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-02 17:42:12 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-02 17:42:12 +0000 |
commit | 5cf675990dde125ed599c2b584d3dc5a3ab2fba2 (patch) | |
tree | 42f933ed4aa61e3681f2a2acef88e4ecbc740bb1 /net/ssl/openssl_client_key_store.cc | |
parent | 45c4fe63c5cee99e6bb1e66b180749da25c52895 (diff) | |
download | chromium_src-5cf675990dde125ed599c2b584d3dc5a3ab2fba2.zip chromium_src-5cf675990dde125ed599c2b584d3dc5a3ab2fba2.tar.gz chromium_src-5cf675990dde125ed599c2b584d3dc5a3ab2fba2.tar.bz2 |
net: move openssl_client_key_store from net/base to net/ssl
This is a follow-up to https://codereview.chromium.org/13006020/
BUG=70818
Review URL: https://codereview.chromium.org/13351006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191853 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/ssl/openssl_client_key_store.cc')
-rw-r--r-- | net/ssl/openssl_client_key_store.cc | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/net/ssl/openssl_client_key_store.cc b/net/ssl/openssl_client_key_store.cc new file mode 100644 index 0000000..9ea044e --- /dev/null +++ b/net/ssl/openssl_client_key_store.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2013 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/openssl_client_key_store.h" + +#include <openssl/evp.h> +#include <openssl/x509.h> + +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "net/cert/x509_certificate.h" + +namespace net { + +namespace { + +typedef OpenSSLClientKeyStore::ScopedEVP_PKEY ScopedEVP_PKEY; + +// Increment the reference count of a given EVP_PKEY. This function +// is similar to EVP_PKEY_dup which is not available from the OpenSSL +// version used by Chromium at the moment. Its name is distinct to +// avoid compiler warnings about ambiguous function calls at caller +// sites. +EVP_PKEY* CopyEVP_PKEY(EVP_PKEY* key) { + if (key) + CRYPTO_add(&key->references, 1, CRYPTO_LOCK_EVP_PKEY); + return key; +} + +// Return the EVP_PKEY holding the public key of a given certificate. +// |cert| is a certificate. +// Returns a scoped EVP_PKEY for it. +ScopedEVP_PKEY GetOpenSSLPublicKey(const X509Certificate* cert) { + // X509_PUBKEY_get() increments the reference count of its result. + // Unlike X509_get_X509_PUBKEY() which simply returns a direct pointer. + EVP_PKEY* pkey = + X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle())); + if (!pkey) + LOG(ERROR) << "Can't extract private key from certificate!"; + return ScopedEVP_PKEY(pkey); +} + +} // namespace + +OpenSSLClientKeyStore::OpenSSLClientKeyStore() { +} + +OpenSSLClientKeyStore::~OpenSSLClientKeyStore() { +} + +OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, + EVP_PKEY* priv_key) { + public_key = CopyEVP_PKEY(pub_key); + private_key = CopyEVP_PKEY(priv_key); +} + +OpenSSLClientKeyStore::KeyPair::~KeyPair() { + EVP_PKEY_free(public_key); + EVP_PKEY_free(private_key); +} + +OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other) { + public_key = CopyEVP_PKEY(other.public_key); + private_key = CopyEVP_PKEY(other.private_key); +} + +void OpenSSLClientKeyStore::KeyPair::operator=(const KeyPair& other) { + EVP_PKEY* old_public_key = public_key; + EVP_PKEY* old_private_key = private_key; + public_key = CopyEVP_PKEY(other.public_key); + private_key = CopyEVP_PKEY(other.private_key); + EVP_PKEY_free(old_private_key); + EVP_PKEY_free(old_public_key); +} + +int OpenSSLClientKeyStore::FindKeyPairIndex(EVP_PKEY* public_key) { + if (!public_key) + return -1; + for (size_t n = 0; n < pairs_.size(); ++n) { + if (EVP_PKEY_cmp(pairs_[n].public_key, public_key) == 1) + return static_cast<int>(n); + } + return -1; +} + +void OpenSSLClientKeyStore::AddKeyPair(EVP_PKEY* pub_key, + EVP_PKEY* private_key) { + int index = FindKeyPairIndex(pub_key); + if (index < 0) + pairs_.push_back(KeyPair(pub_key, private_key)); +} + +// Common code for OpenSSLClientKeyStore. Shared by all OpenSSL-based +// builds. +bool OpenSSLClientKeyStore::RecordClientCertPrivateKey( + const X509Certificate* client_cert, + EVP_PKEY* private_key) { + // Sanity check. + if (!client_cert || !private_key) + return false; + + // Get public key from certificate. + ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert)); + if (!pub_key.get()) + return false; + + AddKeyPair(pub_key.get(), private_key); + return true; +} + +bool OpenSSLClientKeyStore::FetchClientCertPrivateKey( + const X509Certificate* client_cert, + ScopedEVP_PKEY* private_key) { + if (!client_cert) + return false; + + ScopedEVP_PKEY pub_key(GetOpenSSLPublicKey(client_cert)); + if (!pub_key.get()) + return false; + + int index = FindKeyPairIndex(pub_key.get()); + if (index < 0) + return false; + + private_key->reset(CopyEVP_PKEY(pairs_[index].private_key)); + return true; +} + +void OpenSSLClientKeyStore::Flush() { + pairs_.clear(); +} + +OpenSSLClientKeyStore* OpenSSLClientKeyStore::GetInstance() { + return Singleton<OpenSSLClientKeyStore>::get(); +} + +} // namespace net + + |