summaryrefslogtreecommitdiffstats
path: root/net/base
diff options
context:
space:
mode:
authorjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-17 09:57:18 +0000
committerjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-17 09:57:18 +0000
commit313834720d46a68071afe305975f8b70e9bc5782 (patch)
tree1d7b0dea339a8bcf3499cf29f27217cc985f35a1 /net/base
parent0d18ee21d5ddbfecf3951ac8fc0f5a30465e0ffe (diff)
downloadchromium_src-313834720d46a68071afe305975f8b70e9bc5782.zip
chromium_src-313834720d46a68071afe305975f8b70e9bc5782.tar.gz
chromium_src-313834720d46a68071afe305975f8b70e9bc5782.tar.bz2
Refactor EnsureOpenSSLInit and openssl_util into base
This allows the base/crypto methods to call EnsureOpenSSLInit. Also factors out the SSL_CTX and X509_STORE to be more closely associated with their consumers (ssl socket and X509Certificate resp.) rather than process wide globals. BUG=None TEST=None Review URL: http://codereview.chromium.org/4963002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66413 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r--net/base/cert_test_util.cc22
-rw-r--r--net/base/openssl_util.cc86
-rw-r--r--net/base/openssl_util.h59
-rw-r--r--net/base/x509_certificate.h7
-rw-r--r--net/base/x509_certificate_openssl.cc36
5 files changed, 43 insertions, 167 deletions
diff --git a/net/base/cert_test_util.cc b/net/base/cert_test_util.cc
index 1042d50..d5c678e 100644
--- a/net/base/cert_test_util.cc
+++ b/net/base/cert_test_util.cc
@@ -8,8 +8,9 @@
#if defined(USE_OPENSSL)
#include <openssl/err.h>
+#include <openssl/ssl.h>
#include <openssl/x509v3.h>
-#include "net/base/openssl_util.h"
+#include "base/openssl_util.h"
#elif defined(USE_NSS)
#include <cert.h>
#include "base/nss_util.h"
@@ -27,15 +28,11 @@ namespace net {
#if defined(USE_OPENSSL)
X509Certificate* AddTemporaryRootCertToStore(X509* x509_cert) {
- OpenSSLInitSingleton* openssl_init = GetOpenSSLInitSingleton();
-
- if (!X509_STORE_add_cert(openssl_init->x509_store(), x509_cert)) {
+ if (!X509_STORE_add_cert(X509Certificate::cert_store(), x509_cert)) {
unsigned long error_code = ERR_get_error();
if (ERR_GET_LIB(error_code) != ERR_LIB_X509 ||
ERR_GET_REASON(error_code) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
- do {
- LOG(ERROR) << "X509_STORE_add_cert error: " << error_code;
- } while ((error_code = ERR_get_error()) != 0);
+ base::ClearOpenSSLERRStack();
return NULL;
}
}
@@ -45,7 +42,7 @@ X509Certificate* AddTemporaryRootCertToStore(X509* x509_cert) {
}
X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
- EnsureOpenSSLInit();
+ base::EnsureOpenSSLInit();
std::string rawcert;
if (!file_util::ReadFileToString(filename, &rawcert)) {
@@ -53,7 +50,7 @@ X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
return NULL;
}
- ScopedSSL<BIO, BIO_free_all> cert_bio(
+ base::ScopedOpenSSL<BIO, BIO_free_all> cert_bio(
BIO_new_mem_buf(const_cast<char*>(rawcert.c_str()),
rawcert.length()));
if (!cert_bio.get()) {
@@ -61,8 +58,8 @@ X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
return NULL;
}
- ScopedSSL<X509, X509_free> pem_cert(PEM_read_bio_X509(cert_bio.get(),
- NULL, NULL, NULL));
+ base::ScopedOpenSSL<X509, X509_free> pem_cert(PEM_read_bio_X509(
+ cert_bio.get(), NULL, NULL, NULL));
if (pem_cert.get())
return AddTemporaryRootCertToStore(pem_cert.get());
@@ -70,7 +67,8 @@ X509Certificate* LoadTemporaryRootCert(const FilePath& filename) {
const unsigned char* der_data =
reinterpret_cast<const unsigned char*>(rawcert.c_str());
int der_length = rawcert.length();
- ScopedSSL<X509, X509_free> der_cert(d2i_X509(NULL, &der_data, der_length));
+ base::ScopedOpenSSL<X509, X509_free> der_cert(d2i_X509(
+ NULL, &der_data, der_length));
if (der_cert.get())
return AddTemporaryRootCertToStore(der_cert.get());
diff --git a/net/base/openssl_util.cc b/net/base/openssl_util.cc
deleted file mode 100644
index 51797ac..0000000
--- a/net/base/openssl_util.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2006-2008 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/base/openssl_util.h"
-
-#include <openssl/err.h>
-
-#include "base/logging.h"
-#include "base/platform_thread.h"
-
-namespace net {
-
-namespace {
-
-// We do certificate verification after handshake, so we disable the default
-// by registering a no-op verify function.
-int NoOpVerifyCallback(X509_STORE_CTX*, void *) {
- DVLOG(3) << "skipping cert verify";
- return 1;
-}
-
-unsigned long CurrentThreadId() {
- return static_cast<unsigned long>(PlatformThread::CurrentId());
-}
-
-SSL_CTX* CreateSSL_CTX() {
- SSL_load_error_strings();
- SSL_library_init();
- OpenSSL_add_all_algorithms();
- return SSL_CTX_new(SSLv23_client_method());
-}
-
-} // namespace
-
-OpenSSLInitSingleton::OpenSSLInitSingleton()
- : ssl_ctx_(CreateSSL_CTX()),
- store_(X509_STORE_new()) {
- CHECK(ssl_ctx_.get());
- CHECK(store_.get());
-
- SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL);
- X509_STORE_set_default_paths(store_.get());
- // TODO(bulach): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)).
- int num_locks = CRYPTO_num_locks();
- for (int i = 0; i < num_locks; ++i)
- locks_.push_back(new Lock());
- CRYPTO_set_locking_callback(LockingCallback);
- CRYPTO_set_id_callback(CurrentThreadId);
-}
-
-OpenSSLInitSingleton::~OpenSSLInitSingleton() {
- CRYPTO_set_locking_callback(NULL);
- EVP_cleanup();
- ERR_free_strings();
-}
-
-OpenSSLInitSingleton* GetOpenSSLInitSingleton() {
- return Singleton<OpenSSLInitSingleton>::get();
-}
-
-void EnsureOpenSSLInit() {
- Singleton<OpenSSLInitSingleton>::get();
-}
-
-// static
-void OpenSSLInitSingleton::LockingCallback(int mode,
- int n,
- const char* file,
- int line) {
- GetOpenSSLInitSingleton()->OnLockingCallback(mode, n, file, line);
-}
-
-void OpenSSLInitSingleton::OnLockingCallback(int mode,
- int n,
- const char* file,
- int line) {
- CHECK_LT(static_cast<size_t>(n), locks_.size());
- if (mode & CRYPTO_LOCK)
- locks_[n]->Acquire();
- else
- locks_[n]->Release();
-}
-
-} // namespace net
-
diff --git a/net/base/openssl_util.h b/net/base/openssl_util.h
deleted file mode 100644
index d4603c6..0000000
--- a/net/base/openssl_util.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2006-2008 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 <openssl/ssl.h>
-
-#include "base/lock.h"
-#include "base/scoped_vector.h"
-#include "base/singleton.h"
-
-namespace net {
-
-// A helper class that takes care of destroying OpenSSL objects when it goes out
-// of scope.
-template <typename T, void (*destructor)(T*)>
-class ScopedSSL {
- public:
- explicit ScopedSSL(T* ptr_) : ptr_(ptr_) { }
- ~ScopedSSL() { if (ptr_) (*destructor)(ptr_); }
-
- T* get() const { return ptr_; }
-
- private:
- T* ptr_;
-};
-
-// Singleton for initializing / cleaning up OpenSSL and holding a X509 store.
-// Access it via GetOpenSSLInitSingleton().
-class OpenSSLInitSingleton {
- public:
- SSL_CTX* ssl_ctx() const { return ssl_ctx_.get(); }
- X509_STORE* x509_store() const { return store_.get(); }
-
- private:
- friend struct DefaultSingletonTraits<OpenSSLInitSingleton>;
- OpenSSLInitSingleton();
- ~OpenSSLInitSingleton();
-
- static void LockingCallback(int mode, int n, const char* file, int line);
- void OnLockingCallback(int mode, int n, const char* file, int line);
-
- ScopedSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
- ScopedSSL<X509_STORE, X509_STORE_free> store_;
- // These locks are used and managed by OpenSSL via LockingCallback().
- ScopedVector<Lock> locks_;
-
- DISALLOW_COPY_AND_ASSIGN(OpenSSLInitSingleton);
-};
-
-OpenSSLInitSingleton* GetOpenSSLInitSingleton();
-
-// Initialize OpenSSL if it isn't already initialized. This must be called
-// before any other OpenSSL functions (except GetOpenSSLInitSingleton above).
-// This function is thread-safe, and OpenSSL will only ever be initialized once.
-// OpenSSL will be properly shut down on program exit.
-void EnsureOpenSSLInit();
-
-} // namespace net
-
diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h
index 2a7e6d7..1866a17 100644
--- a/net/base/x509_certificate.h
+++ b/net/base/x509_certificate.h
@@ -26,6 +26,7 @@
#elif defined(USE_OPENSSL)
// Forward declaration; real one in <x509.h>
struct x509_st;
+typedef struct x509_store_st X509_STORE;
#elif defined(USE_NSS)
// Forward declaration; real one in <cert.h>
struct CERTCertificateStr;
@@ -234,6 +235,12 @@ class X509Certificate : public base::RefCountedThreadSafe<X509Certificate> {
static HCERTSTORE cert_store();
#endif
+#if defined(USE_OPENSSL)
+ // Returns a handle to a global, in-memory certificate store. We
+ // use it for test code, e.g. importing the test server's certificate.
+ static X509_STORE* cert_store();
+#endif
+
// Verifies the certificate against the given hostname. Returns OK if
// successful or an error code upon failure.
//
diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc
index 512de14..2be38dd 100644
--- a/net/base/x509_certificate_openssl.cc
+++ b/net/base/x509_certificate_openssl.cc
@@ -13,13 +13,13 @@
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
+#include "base/openssl_util.h"
#include "base/pickle.h"
#include "base/singleton.h"
#include "base/string_number_conversions.h"
#include "net/base/cert_status_flags.h"
#include "net/base/cert_verify_result.h"
#include "net/base/net_errors.h"
-#include "net/base/openssl_util.h"
#include "net/base/x509_openssl_util.h"
namespace net {
@@ -31,8 +31,9 @@ namespace {
void CreateOSCertHandlesFromPKCS7Bytes(
const char* data, int length,
X509Certificate::OSCertHandles* handles) {
+ base::EnsureOpenSSLInit();
const unsigned char* der_data = reinterpret_cast<const unsigned char*>(data);
- ScopedSSL<PKCS7, PKCS7_free> pkcs7_cert(
+ base::ScopedOpenSSL<PKCS7, PKCS7_free> pkcs7_cert(
d2i_PKCS7(NULL, &der_data, length));
if (!pkcs7_cert.get())
return;
@@ -98,7 +99,7 @@ void ParseSubjectAltNames(X509Certificate::OSCertHandle cert,
if (!alt_name_ext)
return;
- ScopedSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names(
+ base::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free> alt_names(
reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext)));
if (!alt_names.get())
return;
@@ -206,16 +207,22 @@ void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
class X509InitSingleton {
public:
int der_cache_ex_index() const { return der_cache_ex_index_; }
+ X509_STORE* store() const { return store_.get(); }
private:
friend struct DefaultSingletonTraits<X509InitSingleton>;
- X509InitSingleton() {
- der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
+ X509InitSingleton()
+ : der_cache_ex_index_((base::EnsureOpenSSLInit(),
+ X509_get_ex_new_index(0, 0, 0, 0,
+ DERCache_free))),
+ store_(X509_STORE_new()) {
DCHECK_NE(der_cache_ex_index_, -1);
+ X509_STORE_set_default_paths(store_.get());
+ // TODO(joth): Enable CRL (see X509_STORE_set_flags(X509_V_FLAG_CRL_CHECK)).
}
- ~X509InitSingleton() {}
int der_cache_ex_index_;
+ base::ScopedOpenSSL<X509_STORE, X509_STORE_free> store_;
DISALLOW_COPY_AND_ASSIGN(X509InitSingleton);
};
@@ -290,6 +297,7 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
}
void X509Certificate::Initialize() {
+ base::EnsureOpenSSLInit();
fingerprint_ = CalculateFingerprint(cert_handle_);
ParsePrincipal(cert_handle_, X509_get_subject_name(cert_handle_), &subject_);
ParsePrincipal(cert_handle_, X509_get_issuer_name(cert_handle_), &issuer_);
@@ -311,6 +319,7 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
const char* data, int length) {
if (length < 0)
return NULL;
+ base::EnsureOpenSSLInit();
const unsigned char* d2i_data =
reinterpret_cast<const unsigned char*>(data);
// Don't cache this data via SetDERCache as this wire format may be not be
@@ -346,6 +355,7 @@ X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
return results;
}
+// static
X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
void** pickle_iter) {
const char* data;
@@ -374,6 +384,11 @@ void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
dns_names->push_back(subject_.common_name);
}
+// static
+X509_STORE* X509Certificate::cert_store() {
+ return Singleton<X509InitSingleton>::get()->store();
+}
+
int X509Certificate::Verify(const std::string& hostname,
int flags,
CertVerifyResult* verify_result) const {
@@ -387,9 +402,11 @@ int X509Certificate::Verify(const std::string& hostname,
if (!x509_openssl_util::VerifyHostname(hostname, cert_names))
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
- ScopedSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(X509_STORE_CTX_new());
+ base::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(
+ X509_STORE_CTX_new());
- ScopedSSL<STACK_OF(X509), sk_X509_free_fn> intermediates(sk_X509_new_null());
+ base::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates(
+ sk_X509_new_null());
if (!intermediates.get())
return ERR_OUT_OF_MEMORY;
@@ -398,8 +415,7 @@ int X509Certificate::Verify(const std::string& hostname,
if (!sk_X509_push(intermediates.get(), *it))
return ERR_OUT_OF_MEMORY;
}
- int rv = X509_STORE_CTX_init(ctx.get(),
- GetOpenSSLInitSingleton()->x509_store(),
+ int rv = X509_STORE_CTX_init(ctx.get(), cert_store(),
cert_handle_, intermediates.get());
CHECK_EQ(1, rv);