diff options
-rw-r--r-- | net/base/cert_database_openssl.cc | 20 | ||||
-rw-r--r-- | net/base/keygen_handler_openssl.cc | 8 | ||||
-rw-r--r-- | net/base/openssl_memory_private_key_store.cc | 64 | ||||
-rw-r--r-- | net/base/openssl_private_key_store.h | 51 | ||||
-rw-r--r-- | net/base/ssl_config_service.h | 2 | ||||
-rw-r--r-- | net/net.gyp | 4 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.cc | 17 |
7 files changed, 152 insertions, 14 deletions
diff --git a/net/base/cert_database_openssl.cc b/net/base/cert_database_openssl.cc index 73a67c1..ec5ec24 100644 --- a/net/base/cert_database_openssl.cc +++ b/net/base/cert_database_openssl.cc @@ -4,7 +4,11 @@ #include "net/base/cert_database.h" +#include <openssl/x509.h> + +#include "base/logging.h" #include "net/base/net_errors.h" +#include "net/base/openssl_private_key_store.h" #include "net/base/x509_certificate.h" namespace net { @@ -18,22 +22,28 @@ int CertDatabase::CheckUserCert(X509Certificate* cert) { if (cert->HasExpired()) return ERR_CERT_DATE_INVALID; - // TODO(bulach): implement me. - return ERR_NOT_IMPLEMENTED; + if (!OpenSSLPrivateKeyStore::GetInstance()->FetchPrivateKey( + X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle())))) + return ERR_NO_PRIVATE_KEY_FOR_CERT; + + return OK; } int CertDatabase::AddUserCert(X509Certificate* cert) { // TODO(bulach): implement me. + NOTIMPLEMENTED(); return ERR_NOT_IMPLEMENTED; } void CertDatabase::ListCerts(CertificateList* certs) { // TODO(bulach): implement me. + NOTIMPLEMENTED(); } int CertDatabase::ImportFromPKCS12(const std::string& data, const string16& password) { // TODO(bulach): implement me. + NOTIMPLEMENTED(); return ERR_NOT_IMPLEMENTED; } @@ -41,18 +51,20 @@ int CertDatabase::ExportToPKCS12(const CertificateList& certs, const string16& password, std::string* output) const { // TODO(bulach): implement me. + NOTIMPLEMENTED(); return 0; } bool CertDatabase::DeleteCertAndKey(const X509Certificate* cert) { // TODO(bulach): implement me. + NOTIMPLEMENTED(); return false; } unsigned int CertDatabase::GetCertTrust(const X509Certificate* cert, CertType type) const { // TODO(bulach): implement me. - // NOTE: This method is currently only declared for USE_NSS builds. + NOTIMPLEMENTED(); return 0; } @@ -60,7 +72,7 @@ bool CertDatabase::SetCertTrust(const X509Certificate* cert, CertType type, unsigned int trust_bits) { // TODO(bulach): implement me. - // NOTE: This method is currently only declared for USE_NSS builds. + NOTIMPLEMENTED(); return false; } diff --git a/net/base/keygen_handler_openssl.cc b/net/base/keygen_handler_openssl.cc index b04f098..73aabd7 100644 --- a/net/base/keygen_handler_openssl.cc +++ b/net/base/keygen_handler_openssl.cc @@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/openssl_util.h" #include "base/scoped_ptr.h" +#include "net/base/openssl_private_key_store.h" namespace net { @@ -18,11 +19,8 @@ std::string KeygenHandler::GenKeyAndSignChallenge() { base::RSAPrivateKey::Create(key_size_in_bits_)); EVP_PKEY* pkey = key->key(); - if (stores_key_) { - // TODO(joth): Add an abstraction for persisting OpenSSL private keys. - // See http://crbug.com/64917 - NOTIMPLEMENTED(); - } + if (stores_key_) + OpenSSLPrivateKeyStore::GetInstance()->StorePrivateKey(url_, pkey); base::ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free> spki( NETSCAPE_SPKI_new()); diff --git a/net/base/openssl_memory_private_key_store.cc b/net/base/openssl_memory_private_key_store.cc new file mode 100644 index 0000000..8dc69a0 --- /dev/null +++ b/net/base/openssl_memory_private_key_store.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2010 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. + +// Defines an in-memory private key store, primarily used for testing. + +#include <openssl/evp.h> + +#include "net/base/openssl_private_key_store.h" + +#include "base/logging.h" +#include "base/openssl_util.h" +#include "base/singleton.h" +#include "net/base/x509_certificate.h" + +namespace net { + +namespace { + +class OpenSSLMemoryKeyStore : public OpenSSLPrivateKeyStore { + public: + OpenSSLMemoryKeyStore() {} + + virtual ~OpenSSLMemoryKeyStore() { + AutoLock lock(lock_); + for (std::vector<EVP_PKEY*>::iterator it = keys_.begin(); + it != keys_.end(); ++it) { + EVP_PKEY_free(*it); + } + } + + virtual bool StorePrivateKey(const GURL& url, EVP_PKEY* pkey) { + CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); + AutoLock lock(lock_); + keys_.push_back(pkey); + return true; + } + + virtual EVP_PKEY* FetchPrivateKey(EVP_PKEY* pkey) { + AutoLock lock(lock_); + for (std::vector<EVP_PKEY*>::iterator it = keys_.begin(); + it != keys_.end(); ++it) { + if (EVP_PKEY_cmp(*it, pkey) == 1) + return *it; + } + return NULL; + } + + private: + std::vector<EVP_PKEY*> keys_; + Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(OpenSSLMemoryKeyStore); +}; + +} // namespace + +// static +OpenSSLPrivateKeyStore* OpenSSLPrivateKeyStore::GetInstance() { + return Singleton<OpenSSLMemoryKeyStore>::get(); +} + +} // namespace net + diff --git a/net/base/openssl_private_key_store.h b/net/base/openssl_private_key_store.h new file mode 100644 index 0000000..17f8fe1 --- /dev/null +++ b/net/base/openssl_private_key_store.h @@ -0,0 +1,51 @@ +// Copyright (c) 2010 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. + +#ifndef NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_ +#define NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_ +#pragma once + +#include "base/basictypes.h" + +typedef struct evp_pkey_st EVP_PKEY; + +class GURL; + +namespace net { + +// Defines an abstract store for private keys; the OpenSSL library does not +// provide this service so it is left to individual platforms to provide it. +// +// The contract is that the private key will be stored in an appropriate secure +// system location, and be available to the SSLClientSocketOpenSSL when using a +// client certificate created against the associated public key for client +// authentication. +class OpenSSLPrivateKeyStore { + public: + // Platforms must define this factory function as appropriate. + static OpenSSLPrivateKeyStore* GetInstance(); + + virtual ~OpenSSLPrivateKeyStore() {} + + // Called to store a private key generated via <keygen> while visiting |url|. + // Does not takes ownership of |pkey|, the caller reamins responsible to + // EVP_PKEY_free it. (Internally, a copy maybe made or the reference count + // incremented). + // Returns false if an error occurred whilst attempting to store the key. + virtual bool StorePrivateKey(const GURL& url, EVP_PKEY* pkey) = 0; + + // Given a |public_key| part returns the corresponding private key, or NULL + // if no key found. Does NOT return ownership. + virtual EVP_PKEY* FetchPrivateKey(EVP_PKEY* public_key) = 0; + + protected: + OpenSSLPrivateKeyStore() {} + + private: + DISALLOW_COPY_AND_ASSIGN(OpenSSLPrivateKeyStore); +}; + +} // namespace net + +#endif // NET_BASE_OPENSSL_PRIVATE_KEY_STORE_H_ diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h index 899b329..c1ae553 100644 --- a/net/base/ssl_config_service.h +++ b/net/base/ssl_config_service.h @@ -33,7 +33,7 @@ struct SSLConfig { bool dns_cert_provenance_checking_enabled; // Cipher suites which should be explicitly prevented from being used in - // addition to those disabled by the net built in policy -- by default, all + // addition to those disabled by the net built-in policy -- by default, all // cipher suites supported by the underlying SSL implementation will be // enabled except for: // - Null encryption cipher suites. diff --git a/net/net.gyp b/net/net.gyp index cb589ea..31b9cea 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -142,6 +142,8 @@ 'base/network_config_watcher_mac.h', 'base/nss_memio.c', 'base/nss_memio.h', + 'base/openssl_memory_private_key_store.cc', + 'base/openssl_private_key_store.h', 'base/pem_tokenizer.cc', 'base/pem_tokenizer.h', 'base/platform_mime_util.h', @@ -285,6 +287,8 @@ 'sources!': [ 'base/cert_database_openssl.cc', 'base/keygen_handler_openssl.cc', + 'base/openssl_memory_private_key_store.cc', + 'base/openssl_private_key_store.h', 'base/x509_certificate_openssl.cc', 'base/x509_openssl_util.cc', 'base/x509_openssl_util.h', diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index b3690a9..145aec9 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -16,6 +16,7 @@ #include "base/singleton.h" #include "net/base/cert_verifier.h" #include "net/base/net_errors.h" +#include "net/base/openssl_private_key_store.h" #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" @@ -528,10 +529,18 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, // Second pass: a client certificate should have been selected. if (ssl_config_.client_cert) { - // TODO(joth): We need a way to lookup the private key this - // certificate. See http://crbug.com/64951 and example code in - // http://codereview.chromium.org/5195001/diff/6001/net/socket/ssl_client_socket_openssl.cc - NOTIMPLEMENTED(); + EVP_PKEY* privkey = OpenSSLPrivateKeyStore::GetInstance()->FetchPrivateKey( + X509_PUBKEY_get(X509_get_X509_PUBKEY( + ssl_config_.client_cert->os_cert_handle()))); + if (privkey) { + // TODO(joth): (copied from NSS) We should wait for server certificate + // verification before sending our credentials. See http://crbug.com/13934 + *x509 = X509Certificate::DupOSCertHandle( + ssl_config_.client_cert->os_cert_handle()); + *pkey = privkey; + return 1; + } + LOG(WARNING) << "Client cert found without private key"; } // Send no client certificate. |