summaryrefslogtreecommitdiff
path: root/chromium/net/ssl
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-06-18 14:10:49 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2015-06-18 13:53:24 +0000
commit813fbf95af77a531c57a8c497345ad2c61d475b3 (patch)
tree821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/net/ssl
parentaf6588f8d723931a298c995fa97259bb7f7deb55 (diff)
downloadqtwebengine-chromium-813fbf95af77a531c57a8c497345ad2c61d475b3.tar.gz
BASELINE: Update chromium to 44.0.2403.47
Change-Id: Ie056fedba95cf5e5c76b30c4b2c80fca4764aa2f Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/net/ssl')
-rw-r--r--chromium/net/ssl/channel_id_service.cc4
-rw-r--r--chromium/net/ssl/client_cert_store.h10
-rw-r--r--chromium/net/ssl/client_cert_store_chromeos.h16
-rw-r--r--chromium/net/ssl/client_cert_store_chromeos_unittest.cc4
-rw-r--r--chromium/net/ssl/client_cert_store_win.h8
-rw-r--r--chromium/net/ssl/openssl_client_key_store.cc14
-rw-r--r--chromium/net/ssl/openssl_client_key_store_unittest.cc2
-rw-r--r--chromium/net/ssl/openssl_platform_key_mac.cc2
-rw-r--r--chromium/net/ssl/openssl_platform_key_nss.cc17
-rw-r--r--chromium/net/ssl/openssl_platform_key_win.cc631
-rw-r--r--chromium/net/ssl/openssl_ssl_util.cc25
-rw-r--r--chromium/net/ssl/openssl_ssl_util.h5
-rw-r--r--chromium/net/ssl/scoped_openssl_types.h24
-rw-r--r--chromium/net/ssl/ssl_cipher_suite_names.cc442
-rw-r--r--chromium/net/ssl/ssl_cipher_suite_names.h5
-rw-r--r--chromium/net/ssl/ssl_cipher_suite_names_unittest.cc9
-rw-r--r--chromium/net/ssl/ssl_client_cert_type.h1
-rw-r--r--chromium/net/ssl/ssl_client_session_cache_openssl.cc99
-rw-r--r--chromium/net/ssl/ssl_client_session_cache_openssl.h96
-rw-r--r--chromium/net/ssl/ssl_client_session_cache_openssl_unittest.cc226
-rw-r--r--chromium/net/ssl/ssl_config.cc14
-rw-r--r--chromium/net/ssl/ssl_config.h42
-rw-r--r--chromium/net/ssl/ssl_config_service.cc7
-rw-r--r--chromium/net/ssl/ssl_config_service.h5
-rw-r--r--chromium/net/ssl/ssl_config_service_unittest.cc12
-rw-r--r--chromium/net/ssl/ssl_connection_status_flags.h21
-rw-r--r--chromium/net/ssl/ssl_connection_status_flags_unittest.cc4
-rw-r--r--chromium/net/ssl/ssl_failure_state.h49
28 files changed, 1502 insertions, 292 deletions
diff --git a/chromium/net/ssl/channel_id_service.cc b/chromium/net/ssl/channel_id_service.cc
index 9bc21794a9c..7fcbc539b32 100644
--- a/chromium/net/ssl/channel_id_service.cc
+++ b/chromium/net/ssl/channel_id_service.cc
@@ -27,7 +27,7 @@
#include "net/cert/x509_util.h"
#include "url/gurl.h"
-#if defined(USE_NSS)
+#if !defined(USE_OPENSSL)
#include <private/pprthred.h> // PR_DetachThread
#endif
@@ -246,7 +246,7 @@ class ChannelIDServiceWorker {
scoped_ptr<ChannelIDStore::ChannelID> cert =
GenerateChannelID(server_identifier_, serial_number_, &error);
DVLOG(1) << "GenerateCert " << server_identifier_ << " returned " << error;
-#if defined(USE_NSS)
+#if !defined(USE_OPENSSL)
// Detach the thread from NSPR.
// Calling NSS functions attaches the thread to NSPR, which stores
// the NSPR thread ID in thread-specific data.
diff --git a/chromium/net/ssl/client_cert_store.h b/chromium/net/ssl/client_cert_store.h
index fe050e5f099..b1172deb7d9 100644
--- a/chromium/net/ssl/client_cert_store.h
+++ b/chromium/net/ssl/client_cert_store.h
@@ -14,8 +14,10 @@ namespace net {
class SSLCertRequestInfo;
-// The caller is expected to keep the ClientCertStore alive until the callback
-// supplied to GetClientCerts has been run.
+// A handle to a client certificate store to query matching certificates when a
+// server requests client auth. Note that there may be multiple ClientCertStore
+// objects corresponding to the same platform certificate store; each request
+// gets its own uniquely owned handle.
class NET_EXPORT ClientCertStore {
public:
virtual ~ClientCertStore() {}
@@ -23,8 +25,8 @@ class NET_EXPORT ClientCertStore {
// Get client certs matching the |cert_request_info|. On completion, the
// results will be stored in |selected_certs| and the |callback| will be run.
// The |callback| may be called sychronously. The caller must ensure the
- // ClientCertStore and the |selected_certs| object remain alive until the
- // callback has been run.
+ // ClientCertStore, |cert_request_info|, and |selected_certs| remain alive
+ // until the callback has been run.
virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
CertificateList* selected_certs,
const base::Closure& callback) = 0;
diff --git a/chromium/net/ssl/client_cert_store_chromeos.h b/chromium/net/ssl/client_cert_store_chromeos.h
index 5e9922daab4..2bc359cd9a5 100644
--- a/chromium/net/ssl/client_cert_store_chromeos.h
+++ b/chromium/net/ssl/client_cert_store_chromeos.h
@@ -38,19 +38,19 @@ class NET_EXPORT ClientCertStoreChromeOS : public ClientCertStoreNSS {
ClientCertStoreChromeOS(
scoped_ptr<CertFilter> cert_filter,
const PasswordDelegateFactory& password_delegate_factory);
- virtual ~ClientCertStoreChromeOS();
+ ~ClientCertStoreChromeOS() override;
// ClientCertStoreNSS:
- virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
- CertificateList* selected_certs,
- const base::Closure& callback) override;
+ void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs,
+ const base::Closure& callback) override;
protected:
// ClientCertStoreNSS:
- virtual void GetClientCertsImpl(CERTCertList* cert_list,
- const SSLCertRequestInfo& request,
- bool query_nssdb,
- CertificateList* selected_certs) override;
+ void GetClientCertsImpl(CERTCertList* cert_list,
+ const SSLCertRequestInfo& request,
+ bool query_nssdb,
+ CertificateList* selected_certs) override;
private:
void CertFilterInitialized(const SSLCertRequestInfo* request,
diff --git a/chromium/net/ssl/client_cert_store_chromeos_unittest.cc b/chromium/net/ssl/client_cert_store_chromeos_unittest.cc
index ca2c0494088..94acac6273a 100644
--- a/chromium/net/ssl/client_cert_store_chromeos_unittest.cc
+++ b/chromium/net/ssl/client_cert_store_chromeos_unittest.cc
@@ -20,7 +20,7 @@ namespace net {
namespace {
-class TestCertFilter : public net::ClientCertStoreChromeOS::CertFilter {
+class TestCertFilter : public ClientCertStoreChromeOS::CertFilter {
public:
explicit TestCertFilter(bool init_finished)
: init_finished_(init_finished), init_called_(false) {}
@@ -36,7 +36,7 @@ class TestCertFilter : public net::ClientCertStoreChromeOS::CertFilter {
}
bool IsCertAllowed(
- const scoped_refptr<net::X509Certificate>& cert) const override {
+ const scoped_refptr<X509Certificate>& cert) const override {
if (not_allowed_cert_.get() && cert->Equals(not_allowed_cert_.get()))
return false;
return true;
diff --git a/chromium/net/ssl/client_cert_store_win.h b/chromium/net/ssl/client_cert_store_win.h
index 567c267abef..3c6f187f991 100644
--- a/chromium/net/ssl/client_cert_store_win.h
+++ b/chromium/net/ssl/client_cert_store_win.h
@@ -17,12 +17,12 @@ namespace net {
class NET_EXPORT ClientCertStoreWin : public ClientCertStore {
public:
ClientCertStoreWin();
- virtual ~ClientCertStoreWin();
+ ~ClientCertStoreWin() override;
// ClientCertStore:
- virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
- CertificateList* selected_certs,
- const base::Closure& callback) override;
+ void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs,
+ const base::Closure& callback) override;
private:
friend class ClientCertStoreWinTestDelegate;
diff --git a/chromium/net/ssl/openssl_client_key_store.cc b/chromium/net/ssl/openssl_client_key_store.cc
index de65cd9d677..0bc97beb48e 100644
--- a/chromium/net/ssl/openssl_client_key_store.cc
+++ b/chromium/net/ssl/openssl_client_key_store.cc
@@ -37,18 +37,17 @@ OpenSSLClientKeyStore::OpenSSLClientKeyStore() {
OpenSSLClientKeyStore::~OpenSSLClientKeyStore() {
}
-OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key,
- EVP_PKEY* priv_key)
- : public_key(EVP_PKEY_dup(pub_key)),
- private_key(EVP_PKEY_dup(priv_key)) {
+OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, EVP_PKEY* priv_key)
+ : public_key(EVP_PKEY_up_ref(pub_key)),
+ private_key(EVP_PKEY_up_ref(priv_key)) {
}
OpenSSLClientKeyStore::KeyPair::~KeyPair() {
}
OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other)
- : public_key(EVP_PKEY_dup(other.public_key.get())),
- private_key(EVP_PKEY_dup(other.private_key.get())) {
+ : public_key(EVP_PKEY_up_ref(other.public_key.get())),
+ private_key(EVP_PKEY_up_ref(other.private_key.get())) {
}
void OpenSSLClientKeyStore::KeyPair::operator=(KeyPair other) {
@@ -109,7 +108,8 @@ crypto::ScopedEVP_PKEY OpenSSLClientKeyStore::FetchClientCertPrivateKey(
if (index < 0)
return crypto::ScopedEVP_PKEY();
- return crypto::ScopedEVP_PKEY(EVP_PKEY_dup(pairs_[index].private_key.get()));
+ return crypto::ScopedEVP_PKEY(
+ EVP_PKEY_up_ref(pairs_[index].private_key.get()));
}
void OpenSSLClientKeyStore::Flush() {
diff --git a/chromium/net/ssl/openssl_client_key_store_unittest.cc b/chromium/net/ssl/openssl_client_key_store_unittest.cc
index 7909afd5a82..f1d8a304b4c 100644
--- a/chromium/net/ssl/openssl_client_key_store_unittest.cc
+++ b/chromium/net/ssl/openssl_client_key_store_unittest.cc
@@ -27,7 +27,7 @@ class OpenSSLClientKeyStoreTest : public ::testing::Test {
: store_(OpenSSLClientKeyStore::GetInstance()) {
}
- virtual ~OpenSSLClientKeyStoreTest() {
+ ~OpenSSLClientKeyStoreTest() override {
if (store_)
store_->Flush();
}
diff --git a/chromium/net/ssl/openssl_platform_key_mac.cc b/chromium/net/ssl/openssl_platform_key_mac.cc
index d36924455df..34857afda35 100644
--- a/chromium/net/ssl/openssl_platform_key_mac.cc
+++ b/chromium/net/ssl/openssl_platform_key_mac.cc
@@ -4,7 +4,9 @@
#include "net/ssl/openssl_platform_key.h"
+#include <openssl/ec_key.h>
#include <openssl/err.h>
+#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
diff --git a/chromium/net/ssl/openssl_platform_key_nss.cc b/chromium/net/ssl/openssl_platform_key_nss.cc
new file mode 100644
index 00000000000..a9471e44523
--- /dev/null
+++ b/chromium/net/ssl/openssl_platform_key_nss.cc
@@ -0,0 +1,17 @@
+// Copyright 2015 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 "base/logging.h"
+#include "net/ssl/openssl_platform_key.h"
+
+namespace net {
+
+crypto::ScopedEVP_PKEY FetchClientCertPrivateKey(
+ const X509Certificate* certificate) {
+ // TODO(davidben): Implement client auth for NSS. https://crbug.com/479036
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/openssl_platform_key_win.cc b/chromium/net/ssl/openssl_platform_key_win.cc
index c7db5cbd7dc..c250581cfa9 100644
--- a/chromium/net/ssl/openssl_platform_key_win.cc
+++ b/chromium/net/ssl/openssl_platform_key_win.cc
@@ -4,15 +4,640 @@
#include "net/ssl/openssl_platform_key.h"
+#include <windows.h>
+#include <NCrypt.h>
+
+#include <string.h>
+
+#include <algorithm>
+#include <vector>
+
+#include <openssl/bn.h>
+#include <openssl/digest.h>
+#include <openssl/ec_key.h>
+#include <openssl/err.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/obj_mac.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+#include <openssl/x509.h>
+
+#include "base/debug/debugger.h"
+#include "base/debug/stack_trace.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/win/windows_version.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_capi_types.h"
+#include "crypto/wincrypt_shim.h"
+#include "net/base/net_errors.h"
+#include "net/cert/x509_certificate.h"
+#include "net/ssl/openssl_ssl_util.h"
+#include "net/ssl/scoped_openssl_types.h"
namespace net {
+namespace {
+
+using NCryptFreeObjectFunc = SECURITY_STATUS(WINAPI*)(NCRYPT_HANDLE);
+using NCryptSignHashFunc =
+ SECURITY_STATUS(WINAPI*)(NCRYPT_KEY_HANDLE, // hKey
+ VOID*, // pPaddingInfo
+ PBYTE, // pbHashValue
+ DWORD, // cbHashValue
+ PBYTE, // pbSignature
+ DWORD, // cbSignature
+ DWORD*, // pcbResult
+ DWORD); // dwFlags
+
+class CNGFunctions {
+ public:
+ CNGFunctions()
+ : ncrypt_free_object_(nullptr),
+ ncrypt_sign_hash_(nullptr) {
+ HMODULE ncrypt = GetModuleHandle(L"ncrypt.dll");
+ if (ncrypt != nullptr) {
+ ncrypt_free_object_ = reinterpret_cast<NCryptFreeObjectFunc>(
+ GetProcAddress(ncrypt, "NCryptFreeObject"));
+ ncrypt_sign_hash_ = reinterpret_cast<NCryptSignHashFunc>(
+ GetProcAddress(ncrypt, "NCryptSignHash"));
+ }
+ }
+
+ NCryptFreeObjectFunc ncrypt_free_object() const {
+ return ncrypt_free_object_;
+ }
+
+ NCryptSignHashFunc ncrypt_sign_hash() const { return ncrypt_sign_hash_; }
+
+ private:
+ NCryptFreeObjectFunc ncrypt_free_object_;
+ NCryptSignHashFunc ncrypt_sign_hash_;
+};
+
+base::LazyInstance<CNGFunctions>::Leaky g_cng_functions =
+ LAZY_INSTANCE_INITIALIZER;
+
+struct CERT_KEY_CONTEXTDeleter {
+ void operator()(PCERT_KEY_CONTEXT key) {
+ if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
+ g_cng_functions.Get().ncrypt_free_object()(key->hNCryptKey);
+ } else {
+ CryptReleaseContext(key->hCryptProv, 0);
+ }
+ delete key;
+ }
+};
+
+using ScopedCERT_KEY_CONTEXT =
+ scoped_ptr<CERT_KEY_CONTEXT, CERT_KEY_CONTEXTDeleter>;
+
+// KeyExData contains the data that is contained in the EX_DATA of the
+// RSA and ECDSA objects that are created to wrap Windows system keys.
+struct KeyExData {
+ KeyExData(ScopedCERT_KEY_CONTEXT key, size_t key_length)
+ : key(key.Pass()), key_length(key_length) {}
+
+ ScopedCERT_KEY_CONTEXT key;
+ size_t key_length;
+};
+
+// ExDataDup is called when one of the RSA or EC_KEY objects is
+// duplicated. This is not supported and should never happen.
+int ExDataDup(CRYPTO_EX_DATA* to,
+ const CRYPTO_EX_DATA* from,
+ void** from_d,
+ int idx,
+ long argl,
+ void* argp) {
+ CHECK_EQ((void*)nullptr, *from_d);
+ return 0;
+}
+
+// ExDataFree is called when one of the RSA or EC_KEY objects is freed.
+void ExDataFree(void* parent,
+ void* ptr,
+ CRYPTO_EX_DATA* ex_data,
+ int idx,
+ long argl,
+ void* argp) {
+ KeyExData* data = reinterpret_cast<KeyExData*>(ptr);
+ delete data;
+}
+
+extern const RSA_METHOD win_rsa_method;
+extern const ECDSA_METHOD win_ecdsa_method;
+
+// BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA
+// by forwarding the requested operations to CAPI or CNG.
+class BoringSSLEngine {
+ public:
+ BoringSSLEngine()
+ : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
+ nullptr /* argp */,
+ nullptr /* new_func */,
+ ExDataDup,
+ ExDataFree)),
+ ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
+ nullptr /* argp */,
+ nullptr /* new_func */,
+ ExDataDup,
+ ExDataFree)),
+ engine_(ENGINE_new()) {
+ ENGINE_set_RSA_method(engine_, &win_rsa_method, sizeof(win_rsa_method));
+ ENGINE_set_ECDSA_method(engine_, &win_ecdsa_method,
+ sizeof(win_ecdsa_method));
+ }
+
+ int rsa_ex_index() const { return rsa_index_; }
+ int ec_key_ex_index() const { return ec_key_index_; }
+
+ const ENGINE* engine() const { return engine_; }
+
+ private:
+ const int rsa_index_;
+ const int ec_key_index_;
+ ENGINE* const engine_;
+};
+
+base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
+ LAZY_INSTANCE_INITIALIZER;
+
+// Signs |in| with |key|, writing the output to |out| and the size to |out_len|.
+// Although the buffer is preallocated, this calls NCryptSignHash twice. Some
+// smartcards are buggy and assume the two-call pattern. See
+// https://crbug.com/470204. Returns true on success and false on error.
+bool DoNCryptSignHash(NCRYPT_KEY_HANDLE key,
+ void* padding,
+ const BYTE* in,
+ DWORD in_len,
+ BYTE* out,
+ DWORD max_out,
+ DWORD* out_len,
+ DWORD flags) {
+ // Determine the output length.
+ DWORD signature_len;
+ SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
+ key, padding, const_cast<BYTE*>(in), in_len, nullptr, 0, &signature_len,
+ flags);
+ if (FAILED(ncrypt_status)) {
+ LOG(ERROR) << "NCryptSignHash failed: " << ncrypt_status;
+ return false;
+ }
+ // Check |max_out| externally rather than trust the smartcard.
+ if (signature_len == 0 || signature_len > max_out) {
+ LOG(ERROR) << "Bad signature length.";
+ return false;
+ }
+ // It is important that |signature_len| already be initialized with the
+ // correct size. Some smartcards are buggy and do not write to it on the
+ // second call.
+ ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
+ key, padding, const_cast<PBYTE>(in), in_len, out, signature_len,
+ &signature_len, flags);
+ if (FAILED(ncrypt_status)) {
+ LOG(ERROR) << "NCryptSignHash failed: " << ncrypt_status;
+ return false;
+ }
+ if (signature_len == 0) {
+ LOG(ERROR) << "Bad signature length.";
+ return false;
+ }
+ *out_len = signature_len;
+ return true;
+}
+
+// Custom RSA_METHOD that uses the platform APIs for signing.
+
+const KeyExData* RsaGetExData(const RSA* rsa) {
+ return reinterpret_cast<const KeyExData*>(
+ RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
+}
+
+size_t RsaMethodSize(const RSA* rsa) {
+ const KeyExData* ex_data = RsaGetExData(rsa);
+ return (ex_data->key_length + 7) / 8;
+}
+
+int RsaMethodSign(int hash_nid,
+ const uint8_t* in,
+ unsigned in_len,
+ uint8_t* out,
+ unsigned* out_len,
+ const RSA* rsa) {
+ // TODO(davidben): Switch BoringSSL's sign hook to using size_t rather than
+ // unsigned.
+ const KeyExData* ex_data = RsaGetExData(rsa);
+ if (!ex_data) {
+ NOTREACHED();
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
+ BCRYPT_PKCS1_PADDING_INFO rsa_padding_info;
+ switch (hash_nid) {
+ case NID_md5_sha1:
+ rsa_padding_info.pszAlgId = nullptr;
+ break;
+ case NID_sha1:
+ rsa_padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM;
+ break;
+ case NID_sha256:
+ rsa_padding_info.pszAlgId = BCRYPT_SHA256_ALGORITHM;
+ break;
+ case NID_sha384:
+ rsa_padding_info.pszAlgId = BCRYPT_SHA384_ALGORITHM;
+ break;
+ case NID_sha512:
+ rsa_padding_info.pszAlgId = BCRYPT_SHA512_ALGORITHM;
+ break;
+ default:
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+ }
+
+ DWORD signature_len;
+ if (!DoNCryptSignHash(ex_data->key->hNCryptKey, &rsa_padding_info, in,
+ in_len, out, RSA_size(rsa), &signature_len,
+ BCRYPT_PAD_PKCS1)) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ *out_len = signature_len;
+ return 1;
+ }
+
+ ALG_ID hash_alg;
+ switch (hash_nid) {
+ case NID_md5_sha1:
+ hash_alg = CALG_SSL3_SHAMD5;
+ break;
+ case NID_sha1:
+ hash_alg = CALG_SHA1;
+ break;
+ case NID_sha256:
+ hash_alg = CALG_SHA_256;
+ break;
+ case NID_sha384:
+ hash_alg = CALG_SHA_384;
+ break;
+ case NID_sha512:
+ hash_alg = CALG_SHA_512;
+ break;
+ default:
+ OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+ }
+
+ HCRYPTHASH hash;
+ if (!CryptCreateHash(ex_data->key->hCryptProv, hash_alg, 0, 0, &hash)) {
+ PLOG(ERROR) << "CreateCreateHash failed";
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ DWORD hash_len;
+ DWORD arg_len = sizeof(hash_len);
+ if (!CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hash_len),
+ &arg_len, 0)) {
+ PLOG(ERROR) << "CryptGetHashParam HP_HASHSIZE failed";
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ if (hash_len != in_len) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ if (!CryptSetHashParam(hash, HP_HASHVAL, const_cast<BYTE*>(in), 0)) {
+ PLOG(ERROR) << "CryptSetHashParam HP_HASHVAL failed";
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ DWORD signature_len = RSA_size(rsa);
+ if (!CryptSignHash(hash, ex_data->key->dwKeySpec, nullptr, 0, out,
+ &signature_len)) {
+ PLOG(ERROR) << "CryptSignHash failed";
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+
+ /* CryptoAPI signs in little-endian, so reverse it. */
+ std::reverse(out, out + signature_len);
+ *out_len = signature_len;
+ return 1;
+}
+
+int RsaMethodEncrypt(RSA* rsa,
+ size_t* out_len,
+ uint8_t* out,
+ size_t max_out,
+ const uint8_t* in,
+ size_t in_len,
+ int padding) {
+ NOTIMPLEMENTED();
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+}
+
+int RsaMethodSignRaw(RSA* rsa,
+ size_t* out_len,
+ uint8_t* out,
+ size_t max_out,
+ const uint8_t* in,
+ size_t in_len,
+ int padding) {
+ NOTIMPLEMENTED();
+ OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+}
+
+int RsaMethodDecrypt(RSA* rsa,
+ size_t* out_len,
+ uint8_t* out,
+ size_t max_out,
+ const uint8_t* in,
+ size_t in_len,
+ int padding) {
+ NOTIMPLEMENTED();
+ OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+}
+
+int RsaMethodVerifyRaw(RSA* rsa,
+ size_t* out_len,
+ uint8_t* out,
+ size_t max_out,
+ const uint8_t* in,
+ size_t in_len,
+ int padding) {
+ NOTIMPLEMENTED();
+ OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+}
+
+int RsaMethodSupportsDigest(const RSA* rsa, const EVP_MD* md) {
+ const KeyExData* ex_data = RsaGetExData(rsa);
+ if (!ex_data) {
+ NOTREACHED();
+ return 0;
+ }
+
+ int hash_nid = EVP_MD_type(md);
+ if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
+ // Only hashes which appear in RsaSignPKCS1 are supported.
+ if (hash_nid != NID_sha1 && hash_nid != NID_sha256 &&
+ hash_nid != NID_sha384 && hash_nid != NID_sha512) {
+ return 0;
+ }
+
+ // If the key is a 1024-bit RSA, assume conservatively that it may only be
+ // able to sign SHA-1 hashes. This is the case for older Estonian ID cards
+ // that have 1024-bit RSA keys.
+ //
+ // CNG does provide NCryptIsAlgSupported and NCryptEnumAlgorithms functions,
+ // however they seem to both return NTE_NOT_SUPPORTED when querying the
+ // NCRYPT_PROV_HANDLE at the key's NCRYPT_PROVIDER_HANDLE_PROPERTY.
+ if (ex_data->key_length <= 1024 && hash_nid != NID_sha1)
+ return 0;
+
+ return 1;
+ } else {
+ // If the key is in CAPI, assume conservatively that the CAPI service
+ // provider may only be able to sign SHA-1 hashes.
+ return hash_nid == NID_sha1;
+ }
+}
+
+const RSA_METHOD win_rsa_method = {
+ {
+ 0, // references
+ 1, // is_static
+ },
+ nullptr, // app_data
+
+ nullptr, // init
+ nullptr, // finish
+ RsaMethodSize,
+ RsaMethodSign,
+ nullptr, // verify
+ RsaMethodEncrypt,
+ RsaMethodSignRaw,
+ RsaMethodDecrypt,
+ RsaMethodVerifyRaw,
+ nullptr, // private_transform
+ nullptr, // mod_exp
+ nullptr, // bn_mod_exp
+ RSA_FLAG_OPAQUE,
+ nullptr, // keygen
+ RsaMethodSupportsDigest,
+};
+
+// Custom ECDSA_METHOD that uses the platform APIs.
+// Note that for now, only signing through ECDSA_sign() is really supported.
+// all other method pointers are either stubs returning errors, or no-ops.
+
+const KeyExData* EcKeyGetExData(const EC_KEY* ec_key) {
+ return reinterpret_cast<const KeyExData*>(EC_KEY_get_ex_data(
+ ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
+}
+
+size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
+ const KeyExData* ex_data = EcKeyGetExData(ec_key);
+ // key_length is the size of the group order for EC keys.
+ return (ex_data->key_length + 7) / 8;
+}
+
+int EcdsaMethodSign(const uint8_t* digest,
+ size_t digest_len,
+ uint8_t* out_sig,
+ unsigned int* out_sig_len,
+ EC_KEY* ec_key) {
+ const KeyExData* ex_data = EcKeyGetExData(ec_key);
+ // Only CNG supports ECDSA.
+ if (!ex_data || ex_data->key->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
+ NOTREACHED();
+ OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ // An ECDSA signature is two integers, modulo the order of the group.
+ size_t order_len = (ex_data->key_length + 7) / 8;
+ if (order_len == 0) {
+ NOTREACHED();
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ std::vector<uint8_t> raw_sig(order_len * 2);
+
+ DWORD signature_len;
+ if (!DoNCryptSignHash(ex_data->key->hNCryptKey, nullptr, digest, digest_len,
+ &raw_sig[0], raw_sig.size(), &signature_len, 0)) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ if (signature_len != raw_sig.size()) {
+ LOG(ERROR) << "Bad signature length";
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+
+ // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value.
+ crypto::ScopedECDSA_SIG sig(ECDSA_SIG_new());
+ if (!sig) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ sig->r = BN_bin2bn(&raw_sig[0], order_len, nullptr);
+ sig->s = BN_bin2bn(&raw_sig[order_len], order_len, nullptr);
+ if (!sig->r || !sig->s) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+
+ // Ensure the DER-encoded signature fits in the bounds.
+ int len = i2d_ECDSA_SIG(sig.get(), nullptr);
+ if (len < 0 || static_cast<size_t>(len) > ECDSA_size(ec_key)) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+
+ len = i2d_ECDSA_SIG(sig.get(), &out_sig);
+ if (len < 0) {
+ OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
+ return 0;
+ }
+ *out_sig_len = len;
+ return 1;
+}
+
+int EcdsaMethodVerify(const uint8_t* digest,
+ size_t digest_len,
+ const uint8_t* sig,
+ size_t sig_len,
+ EC_KEY* eckey) {
+ NOTIMPLEMENTED();
+ OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
+ return 0;
+}
+
+const ECDSA_METHOD win_ecdsa_method = {
+ {
+ 0, // references
+ 1, // is_static
+ },
+ nullptr, // app_data
+
+ nullptr, // init
+ nullptr, // finish
+ EcdsaMethodGroupOrderSize,
+ EcdsaMethodSign,
+ EcdsaMethodVerify,
+ ECDSA_FLAG_OPAQUE,
+};
+
+// Determines the key type and length of |certificate|'s public key. The type is
+// returned as an OpenSSL EVP_PKEY type. The key length for RSA key is the size
+// of the RSA modulus in bits. For an ECDSA key, it is the number of bits to
+// represent the group order. It returns true on success and false on failure.
+bool GetKeyInfo(const X509Certificate* certificate,
+ int* out_type,
+ size_t* out_length) {
+ crypto::OpenSSLErrStackTracer tracker(FROM_HERE);
+
+ std::string der_encoded;
+ if (!X509Certificate::GetDEREncoded(certificate->os_cert_handle(),
+ &der_encoded))
+ return false;
+ const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data());
+ ScopedX509 x509(d2i_X509(NULL, &bytes, der_encoded.size()));
+ if (!x509)
+ return false;
+ crypto::ScopedEVP_PKEY key(X509_get_pubkey(x509.get()));
+ if (!key)
+ return false;
+ *out_type = EVP_PKEY_id(key.get());
+ *out_length = EVP_PKEY_bits(key.get());
+ return true;
+}
+
+crypto::ScopedEVP_PKEY CreateRSAWrapper(ScopedCERT_KEY_CONTEXT key,
+ size_t key_length) {
+ crypto::ScopedRSA rsa(RSA_new_method(global_boringssl_engine.Get().engine()));
+ if (!rsa)
+ return nullptr;
+
+ RSA_set_ex_data(rsa.get(), global_boringssl_engine.Get().rsa_ex_index(),
+ new KeyExData(key.Pass(), key_length));
+
+ crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
+ if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
+ return nullptr;
+ return pkey.Pass();
+}
+
+crypto::ScopedEVP_PKEY CreateECDSAWrapper(ScopedCERT_KEY_CONTEXT key,
+ size_t key_length) {
+ crypto::ScopedEC_KEY ec_key(
+ EC_KEY_new_method(global_boringssl_engine.Get().engine()));
+ if (!ec_key)
+ return nullptr;
+
+ EC_KEY_set_ex_data(ec_key.get(),
+ global_boringssl_engine.Get().ec_key_ex_index(),
+ new KeyExData(key.Pass(), key_length));
+
+ crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
+ if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()))
+ return nullptr;
+
+ return pkey.Pass();
+}
+
+} // namespace
+
crypto::ScopedEVP_PKEY FetchClientCertPrivateKey(
const X509Certificate* certificate) {
- // TODO(davidben): Implement on Windows.
- NOTIMPLEMENTED();
- return crypto::ScopedEVP_PKEY();
+ PCCERT_CONTEXT cert_context = certificate->os_cert_handle();
+
+ HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov = 0;
+ DWORD key_spec = 0;
+ BOOL must_free = FALSE;
+ DWORD flags = 0;
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA)
+ flags |= CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
+
+ if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr,
+ &crypt_prov, &key_spec, &must_free)) {
+ PLOG(WARNING) << "Could not acquire private key";
+ return nullptr;
+ }
+
+ // Should never get a cached handle back - ownership must always be
+ // transferred.
+ CHECK_EQ(must_free, TRUE);
+ ScopedCERT_KEY_CONTEXT key(new CERT_KEY_CONTEXT);
+ key->dwKeySpec = key_spec;
+ key->hCryptProv = crypt_prov;
+
+ // Rather than query the private key for metadata, extract the public key from
+ // the certificate without using Windows APIs. CAPI and CNG do not
+ // consistently work depending on the system. See https://crbug.com/468345.
+ int key_type;
+ size_t key_length;
+ if (!GetKeyInfo(certificate, &key_type, &key_length))
+ return nullptr;
+
+ switch (key_type) {
+ case EVP_PKEY_RSA:
+ return CreateRSAWrapper(key.Pass(), key_length);
+ case EVP_PKEY_EC:
+ return CreateECDSAWrapper(key.Pass(), key_length);
+ default:
+ return nullptr;
+ }
}
} // namespace net
diff --git a/chromium/net/ssl/openssl_ssl_util.cc b/chromium/net/ssl/openssl_ssl_util.cc
index 9fb83a43f5d..54a34009323 100644
--- a/chromium/net/ssl/openssl_ssl_util.cc
+++ b/chromium/net/ssl/openssl_ssl_util.cc
@@ -67,7 +67,6 @@ int MapOpenSSLErrorSSL(uint32_t error_code) {
case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
case SSL_R_UNKNOWN_CIPHER_TYPE:
case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
- case SSL_R_UNKNOWN_PKEY_TYPE:
case SSL_R_UNKNOWN_SSL_VERSION:
return ERR_NOT_IMPLEMENTED;
case SSL_R_UNSUPPORTED_SSL_VERSION:
@@ -114,17 +113,11 @@ int MapOpenSSLErrorSSL(uint32_t error_code) {
case SSL_R_EXTRA_DATA_IN_MESSAGE:
case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
case SSL_R_INVALID_COMMAND:
- case SSL_R_INVALID_STATUS_RESPONSE:
case SSL_R_INVALID_TICKET_KEYS_LENGTH:
// SSL_do_handshake reports this error when the server responds to a
// ClientHello with a fatal close_notify alert.
- case SSL_AD_REASON_OFFSET + SSL_AD_CLOSE_NOTIFY:
+ case SSL_R_SSLV3_ALERT_CLOSE_NOTIFY:
case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
- // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
- // server after receiving ClientHello if there's no common supported cipher.
- // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
- // to match the NSS implementation. See also http://goo.gl/oMtZW
- case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
case SSL_R_TLSV1_ALERT_DECODE_ERROR:
@@ -139,8 +132,20 @@ int MapOpenSSLErrorSSL(uint32_t error_code) {
// The only way that the certificate verify callback can fail is if
// the leaf certificate changed during a renegotiation.
return ERR_SSL_SERVER_CERT_CHANGED;
- case SSL_AD_REASON_OFFSET + SSL3_AD_INAPPROPRIATE_FALLBACK:
+ case SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK:
return ERR_SSL_INAPPROPRIATE_FALLBACK;
+ // SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the server after
+ // receiving ClientHello if there's no common supported cipher. Map that
+ // specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH to match the NSS
+ // implementation. See https://goo.gl/oMtZW and https://crbug.com/446505.
+ case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE: {
+ uint32_t previous = ERR_peek_error();
+ if (previous != 0 && ERR_GET_LIB(previous) == ERR_LIB_SSL &&
+ ERR_GET_REASON(previous) == SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO) {
+ return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
+ }
+ return ERR_SSL_PROTOCOL_ERROR;
+ }
default:
LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
return ERR_SSL_PROTOCOL_ERROR;
@@ -150,7 +155,7 @@ int MapOpenSSLErrorSSL(uint32_t error_code) {
base::Value* NetLogOpenSSLErrorCallback(int net_error,
int ssl_error,
const OpenSSLErrorInfo& error_info,
- NetLog::LogLevel /* log_level */) {
+ NetLogCaptureMode /* capture_mode */) {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetInteger("net_error", net_error);
dict->SetInteger("ssl_error", ssl_error);
diff --git a/chromium/net/ssl/openssl_ssl_util.h b/chromium/net/ssl/openssl_ssl_util.h
index a0339fca18d..6c886cc1c9c 100644
--- a/chromium/net/ssl/openssl_ssl_util.h
+++ b/chromium/net/ssl/openssl_ssl_util.h
@@ -5,7 +5,7 @@
#ifndef NET_SSL_OPENSSL_SSL_UTIL_H_
#define NET_SSL_OPENSSL_SSL_UTIL_H_
-#include "net/base/net_log.h"
+#include "net/log/net_log.h"
namespace crypto {
class OpenSSLErrStackTracer;
@@ -51,7 +51,8 @@ struct OpenSSLErrorInfo {
// Converts an OpenSSL error code into a net error code, walking the OpenSSL
// error stack if needed. If a value on the stack is used, the error code and
// associated information are returned in |*out_error_info|. Otherwise its
-// fields are set to 0 and NULL.
+// fields are set to 0 and NULL. This function will never return OK, so
+// SSL_ERROR_ZERO_RETURN must be handled externally.
//
// Note that |tracer| is not currently used in the implementation, but is passed
// in anyway as this ensures the caller will clear any residual codes left on
diff --git a/chromium/net/ssl/scoped_openssl_types.h b/chromium/net/ssl/scoped_openssl_types.h
new file mode 100644
index 00000000000..a8c3c345975
--- /dev/null
+++ b/chromium/net/ssl/scoped_openssl_types.h
@@ -0,0 +1,24 @@
+// Copyright 2015 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_SSL_SCOPED_OPENSSL_TYPES_H_
+#define NET_SSL_SCOPED_OPENSSL_TYPES_H_
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "crypto/scoped_openssl_types.h"
+
+namespace net {
+
+using ScopedPKCS8_PRIV_KEY_INFO =
+ crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
+using ScopedSSL = crypto::ScopedOpenSSL<SSL, SSL_free>;
+using ScopedSSL_CTX = crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free>;
+using ScopedSSL_SESSION = crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free>;
+using ScopedX509 = crypto::ScopedOpenSSL<X509, X509_free>;
+
+} // namespace net
+
+#endif // NET_SSL_SCOPED_OPENSSL_TYPES_H_
diff --git a/chromium/net/ssl/ssl_cipher_suite_names.cc b/chromium/net/ssl/ssl_cipher_suite_names.cc
index 55b0276ee5c..87a3259e54c 100644
--- a/chromium/net/ssl/ssl_cipher_suite_names.cc
+++ b/chromium/net/ssl/ssl_cipher_suite_names.cc
@@ -25,180 +25,183 @@
// The following tables were generated by ssl_cipher_suite_names_generate.go,
// found in the same directory as this file.
+namespace {
+
struct CipherSuite {
uint16 cipher_suite, encoded;
};
-static const struct CipherSuite kCipherSuites[] = {
- {0x0, 0x0}, // TLS_NULL_WITH_NULL_NULL
- {0x1, 0x101}, // TLS_RSA_WITH_NULL_MD5
- {0x2, 0x102}, // TLS_RSA_WITH_NULL_SHA
- {0x3, 0x209}, // TLS_RSA_EXPORT_WITH_RC4_40_MD5
- {0x4, 0x111}, // TLS_RSA_WITH_RC4_128_MD5
- {0x5, 0x112}, // TLS_RSA_WITH_RC4_128_SHA
- {0x6, 0x219}, // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
- {0x7, 0x122}, // TLS_RSA_WITH_IDEA_CBC_SHA
- {0x8, 0x22a}, // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
- {0x9, 0x132}, // TLS_RSA_WITH_DES_CBC_SHA
- {0xa, 0x13a}, // TLS_RSA_WITH_3DES_EDE_CBC_SHA
- {0xb, 0x32a}, // TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
- {0xc, 0x432}, // TLS_DH_DSS_WITH_DES_CBC_SHA
- {0xd, 0x43a}, // TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
- {0xe, 0x52a}, // TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
- {0xf, 0x632}, // TLS_DH_RSA_WITH_DES_CBC_SHA
- {0x10, 0x63a}, // TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
- {0x11, 0x72a}, // TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
- {0x12, 0x832}, // TLS_DHE_DSS_WITH_DES_CBC_SHA
- {0x13, 0x83a}, // TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
- {0x14, 0x92a}, // TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
- {0x15, 0xa32}, // TLS_DHE_RSA_WITH_DES_CBC_SHA
- {0x16, 0xa3a}, // TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
- {0x17, 0xb09}, // TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
- {0x18, 0xc11}, // TLS_DH_anon_WITH_RC4_128_MD5
- {0x19, 0xb2a}, // TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
- {0x1a, 0xc32}, // TLS_DH_anon_WITH_DES_CBC_SHA
- {0x1b, 0xc3a}, // TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
- {0x2f, 0x142}, // TLS_RSA_WITH_AES_128_CBC_SHA
- {0x30, 0x442}, // TLS_DH_DSS_WITH_AES_128_CBC_SHA
- {0x31, 0x642}, // TLS_DH_RSA_WITH_AES_128_CBC_SHA
- {0x32, 0x842}, // TLS_DHE_DSS_WITH_AES_128_CBC_SHA
- {0x33, 0xa42}, // TLS_DHE_RSA_WITH_AES_128_CBC_SHA
- {0x34, 0xc42}, // TLS_DH_anon_WITH_AES_128_CBC_SHA
- {0x35, 0x14a}, // TLS_RSA_WITH_AES_256_CBC_SHA
- {0x36, 0x44a}, // TLS_DH_DSS_WITH_AES_256_CBC_SHA
- {0x37, 0x64a}, // TLS_DH_RSA_WITH_AES_256_CBC_SHA
- {0x38, 0x84a}, // TLS_DHE_DSS_WITH_AES_256_CBC_SHA
- {0x39, 0xa4a}, // TLS_DHE_RSA_WITH_AES_256_CBC_SHA
- {0x3a, 0xc4a}, // TLS_DH_anon_WITH_AES_256_CBC_SHA
- {0x3b, 0x103}, // TLS_RSA_WITH_NULL_SHA256
- {0x3c, 0x143}, // TLS_RSA_WITH_AES_128_CBC_SHA256
- {0x3d, 0x14b}, // TLS_RSA_WITH_AES_256_CBC_SHA256
- {0x3e, 0x443}, // TLS_DH_DSS_WITH_AES_128_CBC_SHA256
- {0x3f, 0x643}, // TLS_DH_RSA_WITH_AES_128_CBC_SHA256
- {0x40, 0x843}, // TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
- {0x41, 0x152}, // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
- {0x42, 0x452}, // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
- {0x43, 0x652}, // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
- {0x44, 0x852}, // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
- {0x45, 0xa52}, // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
- {0x46, 0xc52}, // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
- {0x67, 0xa43}, // TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
- {0x68, 0x44b}, // TLS_DH_DSS_WITH_AES_256_CBC_SHA256
- {0x69, 0x64b}, // TLS_DH_RSA_WITH_AES_256_CBC_SHA256
- {0x6a, 0x84b}, // TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
- {0x6b, 0xa4b}, // TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
- {0x6c, 0xc43}, // TLS_DH_anon_WITH_AES_128_CBC_SHA256
- {0x6d, 0xc4b}, // TLS_DH_anon_WITH_AES_256_CBC_SHA256
- {0x84, 0x15a}, // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
- {0x85, 0x45a}, // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
- {0x86, 0x65a}, // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
- {0x87, 0x85a}, // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
- {0x88, 0xa5a}, // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
- {0x89, 0xc5a}, // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
- {0x96, 0x162}, // TLS_RSA_WITH_SEED_CBC_SHA
- {0x97, 0x462}, // TLS_DH_DSS_WITH_SEED_CBC_SHA
- {0x98, 0x662}, // TLS_DH_RSA_WITH_SEED_CBC_SHA
- {0x99, 0x862}, // TLS_DHE_DSS_WITH_SEED_CBC_SHA
- {0x9a, 0xa62}, // TLS_DHE_RSA_WITH_SEED_CBC_SHA
- {0x9b, 0xc62}, // TLS_DH_anon_WITH_SEED_CBC_SHA
- {0x9c, 0x16f}, // TLS_RSA_WITH_AES_128_GCM_SHA256
- {0x9d, 0x177}, // TLS_RSA_WITH_AES_256_GCM_SHA384
- {0x9e, 0xa6f}, // TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
- {0x9f, 0xa77}, // TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
- {0xa0, 0x66f}, // TLS_DH_RSA_WITH_AES_128_GCM_SHA256
- {0xa1, 0x677}, // TLS_DH_RSA_WITH_AES_256_GCM_SHA384
- {0xa2, 0x86f}, // TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
- {0xa3, 0x877}, // TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
- {0xa4, 0x46f}, // TLS_DH_DSS_WITH_AES_128_GCM_SHA256
- {0xa5, 0x477}, // TLS_DH_DSS_WITH_AES_256_GCM_SHA384
- {0xa6, 0xc6f}, // TLS_DH_anon_WITH_AES_128_GCM_SHA256
- {0xa7, 0xc77}, // TLS_DH_anon_WITH_AES_256_GCM_SHA384
- {0xba, 0x153}, // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xbb, 0x453}, // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256
- {0xbc, 0x653}, // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xbd, 0x853}, // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
- {0xbe, 0xa53}, // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xbf, 0xc53}, // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256
- {0xc0, 0x15b}, // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
- {0xc1, 0x45b}, // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256
- {0xc2, 0x65b}, // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256
- {0xc3, 0x85b}, // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
- {0xc4, 0xa5b}, // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
- {0xc5, 0xc5b}, // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256
- {0xc001, 0xd02}, // TLS_ECDH_ECDSA_WITH_NULL_SHA
- {0xc002, 0xd12}, // TLS_ECDH_ECDSA_WITH_RC4_128_SHA
- {0xc003, 0xd3a}, // TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
- {0xc004, 0xd42}, // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
- {0xc005, 0xd4a}, // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
- {0xc006, 0xe02}, // TLS_ECDHE_ECDSA_WITH_NULL_SHA
- {0xc007, 0xe12}, // TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
- {0xc008, 0xe3a}, // TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
- {0xc009, 0xe42}, // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- {0xc00a, 0xe4a}, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- {0xc00b, 0xf02}, // TLS_ECDH_RSA_WITH_NULL_SHA
- {0xc00c, 0xf12}, // TLS_ECDH_RSA_WITH_RC4_128_SHA
- {0xc00d, 0xf3a}, // TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
- {0xc00e, 0xf42}, // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
- {0xc00f, 0xf4a}, // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
- {0xc010, 0x1002}, // TLS_ECDHE_RSA_WITH_NULL_SHA
- {0xc011, 0x1012}, // TLS_ECDHE_RSA_WITH_RC4_128_SHA
- {0xc012, 0x103a}, // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- {0xc013, 0x1042}, // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- {0xc014, 0x104a}, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- {0xc015, 0x1102}, // TLS_ECDH_anon_WITH_NULL_SHA
- {0xc016, 0x1112}, // TLS_ECDH_anon_WITH_RC4_128_SHA
- {0xc017, 0x113a}, // TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
- {0xc018, 0x1142}, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
- {0xc019, 0x114a}, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
- {0xc023, 0xe43}, // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
- {0xc024, 0xe4c}, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
- {0xc025, 0xd43}, // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
- {0xc026, 0xd4c}, // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
- {0xc027, 0x1043}, // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- {0xc028, 0x104c}, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
- {0xc029, 0xf43}, // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
- {0xc02a, 0xf4c}, // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
- {0xc02b, 0xe6f}, // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- {0xc02c, 0xe77}, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- {0xc02d, 0xd6f}, // TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
- {0xc02e, 0xd77}, // TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
- {0xc02f, 0x106f}, // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- {0xc030, 0x1077}, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- {0xc031, 0xf6f}, // TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
- {0xc032, 0xf77}, // TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
- {0xc072, 0xe53}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xc073, 0xe5c}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- {0xc074, 0xd53}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xc075, 0xd5c}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
- {0xc076, 0x1053}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xc077, 0x105c}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
- {0xc078, 0xf53}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
- {0xc079, 0xf5c}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
- {0xc07a, 0x17f}, // TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc07b, 0x187}, // TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xc07c, 0xa7f}, // TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc07d, 0xa87}, // TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xc07e, 0x67f}, // TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc07f, 0x687}, // TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xc080, 0x87f}, // TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256
- {0xc081, 0x887}, // TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384
- {0xc082, 0x47f}, // TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256
- {0xc083, 0x487}, // TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384
- {0xc084, 0xc7f}, // TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256
- {0xc085, 0xc87}, // TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384
- {0xc086, 0xe7f}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc087, 0xe87}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xc088, 0xd7f}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc089, 0xd87}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xc08a, 0x107f}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc08b, 0x1087}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
- {0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
- {0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
+const struct CipherSuite kCipherSuites[] = {
+ {0x0, 0x0}, // TLS_NULL_WITH_NULL_NULL
+ {0x1, 0x101}, // TLS_RSA_WITH_NULL_MD5
+ {0x2, 0x102}, // TLS_RSA_WITH_NULL_SHA
+ {0x3, 0x209}, // TLS_RSA_EXPORT_WITH_RC4_40_MD5
+ {0x4, 0x111}, // TLS_RSA_WITH_RC4_128_MD5
+ {0x5, 0x112}, // TLS_RSA_WITH_RC4_128_SHA
+ {0x6, 0x219}, // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
+ {0x7, 0x122}, // TLS_RSA_WITH_IDEA_CBC_SHA
+ {0x8, 0x22a}, // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
+ {0x9, 0x132}, // TLS_RSA_WITH_DES_CBC_SHA
+ {0xa, 0x13a}, // TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ {0xb, 0x32a}, // TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
+ {0xc, 0x432}, // TLS_DH_DSS_WITH_DES_CBC_SHA
+ {0xd, 0x43a}, // TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
+ {0xe, 0x52a}, // TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
+ {0xf, 0x632}, // TLS_DH_RSA_WITH_DES_CBC_SHA
+ {0x10, 0x63a}, // TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
+ {0x11, 0x72a}, // TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
+ {0x12, 0x832}, // TLS_DHE_DSS_WITH_DES_CBC_SHA
+ {0x13, 0x83a}, // TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
+ {0x14, 0x92a}, // TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
+ {0x15, 0xa32}, // TLS_DHE_RSA_WITH_DES_CBC_SHA
+ {0x16, 0xa3a}, // TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ {0x17, 0xb09}, // TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
+ {0x18, 0xc11}, // TLS_DH_anon_WITH_RC4_128_MD5
+ {0x19, 0xb2a}, // TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
+ {0x1a, 0xc32}, // TLS_DH_anon_WITH_DES_CBC_SHA
+ {0x1b, 0xc3a}, // TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
+ {0x2f, 0x142}, // TLS_RSA_WITH_AES_128_CBC_SHA
+ {0x30, 0x442}, // TLS_DH_DSS_WITH_AES_128_CBC_SHA
+ {0x31, 0x642}, // TLS_DH_RSA_WITH_AES_128_CBC_SHA
+ {0x32, 0x842}, // TLS_DHE_DSS_WITH_AES_128_CBC_SHA
+ {0x33, 0xa42}, // TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ {0x34, 0xc42}, // TLS_DH_anon_WITH_AES_128_CBC_SHA
+ {0x35, 0x14a}, // TLS_RSA_WITH_AES_256_CBC_SHA
+ {0x36, 0x44a}, // TLS_DH_DSS_WITH_AES_256_CBC_SHA
+ {0x37, 0x64a}, // TLS_DH_RSA_WITH_AES_256_CBC_SHA
+ {0x38, 0x84a}, // TLS_DHE_DSS_WITH_AES_256_CBC_SHA
+ {0x39, 0xa4a}, // TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ {0x3a, 0xc4a}, // TLS_DH_anon_WITH_AES_256_CBC_SHA
+ {0x3b, 0x103}, // TLS_RSA_WITH_NULL_SHA256
+ {0x3c, 0x143}, // TLS_RSA_WITH_AES_128_CBC_SHA256
+ {0x3d, 0x14b}, // TLS_RSA_WITH_AES_256_CBC_SHA256
+ {0x3e, 0x443}, // TLS_DH_DSS_WITH_AES_128_CBC_SHA256
+ {0x3f, 0x643}, // TLS_DH_RSA_WITH_AES_128_CBC_SHA256
+ {0x40, 0x843}, // TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
+ {0x41, 0x152}, // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ {0x42, 0x452}, // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
+ {0x43, 0x652}, // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
+ {0x44, 0x852}, // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
+ {0x45, 0xa52}, // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ {0x46, 0xc52}, // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
+ {0x67, 0xa43}, // TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ {0x68, 0x44b}, // TLS_DH_DSS_WITH_AES_256_CBC_SHA256
+ {0x69, 0x64b}, // TLS_DH_RSA_WITH_AES_256_CBC_SHA256
+ {0x6a, 0x84b}, // TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
+ {0x6b, 0xa4b}, // TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ {0x6c, 0xc43}, // TLS_DH_anon_WITH_AES_128_CBC_SHA256
+ {0x6d, 0xc4b}, // TLS_DH_anon_WITH_AES_256_CBC_SHA256
+ {0x84, 0x15a}, // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ {0x85, 0x45a}, // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
+ {0x86, 0x65a}, // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
+ {0x87, 0x85a}, // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
+ {0x88, 0xa5a}, // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ {0x89, 0xc5a}, // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
+ {0x96, 0x162}, // TLS_RSA_WITH_SEED_CBC_SHA
+ {0x97, 0x462}, // TLS_DH_DSS_WITH_SEED_CBC_SHA
+ {0x98, 0x662}, // TLS_DH_RSA_WITH_SEED_CBC_SHA
+ {0x99, 0x862}, // TLS_DHE_DSS_WITH_SEED_CBC_SHA
+ {0x9a, 0xa62}, // TLS_DHE_RSA_WITH_SEED_CBC_SHA
+ {0x9b, 0xc62}, // TLS_DH_anon_WITH_SEED_CBC_SHA
+ {0x9c, 0x16f}, // TLS_RSA_WITH_AES_128_GCM_SHA256
+ {0x9d, 0x177}, // TLS_RSA_WITH_AES_256_GCM_SHA384
+ {0x9e, 0xa6f}, // TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ {0x9f, 0xa77}, // TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ {0xa0, 0x66f}, // TLS_DH_RSA_WITH_AES_128_GCM_SHA256
+ {0xa1, 0x677}, // TLS_DH_RSA_WITH_AES_256_GCM_SHA384
+ {0xa2, 0x86f}, // TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
+ {0xa3, 0x877}, // TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
+ {0xa4, 0x46f}, // TLS_DH_DSS_WITH_AES_128_GCM_SHA256
+ {0xa5, 0x477}, // TLS_DH_DSS_WITH_AES_256_GCM_SHA384
+ {0xa6, 0xc6f}, // TLS_DH_anon_WITH_AES_128_GCM_SHA256
+ {0xa7, 0xc77}, // TLS_DH_anon_WITH_AES_256_GCM_SHA384
+ {0xba, 0x153}, // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xbb, 0x453}, // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256
+ {0xbc, 0x653}, // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xbd, 0x853}, // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
+ {0xbe, 0xa53}, // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xbf, 0xc53}, // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256
+ {0xc0, 0x15b}, // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ {0xc1, 0x45b}, // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256
+ {0xc2, 0x65b}, // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ {0xc3, 0x85b}, // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
+ {0xc4, 0xa5b}, // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ {0xc5, 0xc5b}, // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256
+ {0xc001, 0xd02}, // TLS_ECDH_ECDSA_WITH_NULL_SHA
+ {0xc002, 0xd12}, // TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ {0xc003, 0xd3a}, // TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ {0xc004, 0xd42}, // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ {0xc005, 0xd4a}, // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ {0xc006, 0xe02}, // TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ {0xc007, 0xe12}, // TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ {0xc008, 0xe3a}, // TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ {0xc009, 0xe42}, // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ {0xc00a, 0xe4a}, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ {0xc00b, 0xf02}, // TLS_ECDH_RSA_WITH_NULL_SHA
+ {0xc00c, 0xf12}, // TLS_ECDH_RSA_WITH_RC4_128_SHA
+ {0xc00d, 0xf3a}, // TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ {0xc00e, 0xf42}, // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ {0xc00f, 0xf4a}, // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ {0xc010, 0x1002}, // TLS_ECDHE_RSA_WITH_NULL_SHA
+ {0xc011, 0x1012}, // TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ {0xc012, 0x103a}, // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ {0xc013, 0x1042}, // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ {0xc014, 0x104a}, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ {0xc015, 0x1102}, // TLS_ECDH_anon_WITH_NULL_SHA
+ {0xc016, 0x1112}, // TLS_ECDH_anon_WITH_RC4_128_SHA
+ {0xc017, 0x113a}, // TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
+ {0xc018, 0x1142}, // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+ {0xc019, 0x114a}, // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
+ {0xc023, 0xe43}, // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ {0xc024, 0xe4c}, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ {0xc025, 0xd43}, // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ {0xc026, 0xd4c}, // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ {0xc027, 0x1043}, // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ {0xc028, 0x104c}, // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ {0xc029, 0xf43}, // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ {0xc02a, 0xf4c}, // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ {0xc02b, 0xe6f}, // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ {0xc02c, 0xe77}, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ {0xc02d, 0xd6f}, // TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ {0xc02e, 0xd77}, // TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ {0xc02f, 0x106f}, // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ {0xc030, 0x1077}, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ {0xc031, 0xf6f}, // TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ {0xc032, 0xf77}, // TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ {0xc072, 0xe53}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xc073, 0xe5c}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ {0xc074, 0xd53}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xc075, 0xd5c}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ {0xc076, 0x1053}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xc077, 0x105c}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ {0xc078, 0xf53}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ {0xc079, 0xf5c}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ {0xc07a, 0x17f}, // TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc07b, 0x187}, // TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc07c, 0xa7f}, // TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc07d, 0xa87}, // TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc07e, 0x67f}, // TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc07f, 0x687}, // TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc080, 0x87f}, // TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc081, 0x887}, // TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc082, 0x47f}, // TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc083, 0x487}, // TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc084, 0xc7f}, // TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc085, 0xc87}, // TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc086, 0xe7f}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc087, 0xe87}, // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc088, 0xd7f}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc089, 0xd87}, // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc08a, 0x107f}, // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc08b, 0x1087}, // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ {0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ {0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
+ {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
+ {0xcc15, 0x0a8f}, // TLS_DHE_RSA_WITH_CHACHA20_POLY1305
};
-static const struct {
+const struct {
char name[15];
} kKeyExchangeNames[18] = {
{"NULL"}, // 0
@@ -221,7 +224,7 @@ static const struct {
{"ECDH_anon"}, // 17
};
-static const struct {
+const struct {
char name[18];
} kCipherNames[18] = {
{"NULL"}, // 0
@@ -244,22 +247,20 @@ static const struct {
{"CHACHA20_POLY1305"}, // 17
};
-static const struct {
- char name[7];
+const struct {
+ char name[12];
} kMacNames[5] = {
{"NULL"}, // 0
- {"MD5"}, // 1
- {"SHA1"}, // 2
- {"SHA256"}, // 3
- {"SHA384"}, // 4
+ {"HMAC-MD5"}, // 1
+ {"HMAC-SHA1"}, // 2
+ {"HMAC-SHA256"}, // 3
+ {"HMAC-SHA384"}, // 4
// 7 is reserved to indicate an AEAD cipher suite.
};
-static const int kAEADMACValue = 7;
-
-namespace net {
+const int kAEADMACValue = 7;
-static int CipherSuiteCmp(const void* ia, const void* ib) {
+int CipherSuiteCmp(const void* ia, const void* ib) {
const CipherSuite* a = static_cast<const CipherSuite*>(ia);
const CipherSuite* b = static_cast<const CipherSuite*>(ib);
@@ -272,6 +273,29 @@ static int CipherSuiteCmp(const void* ia, const void* ib) {
}
}
+bool GetCipherProperties(uint16 cipher_suite,
+ int* out_key_exchange,
+ int* out_cipher,
+ int* out_mac) {
+ CipherSuite desired = {0};
+ desired.cipher_suite = cipher_suite;
+ void* r = bsearch(&desired, kCipherSuites, arraysize(kCipherSuites),
+ sizeof(kCipherSuites[0]), CipherSuiteCmp);
+
+ if (!r)
+ return false;
+
+ const CipherSuite* cs = static_cast<const CipherSuite*>(r);
+ *out_key_exchange = cs->encoded >> 8;
+ *out_cipher = (cs->encoded >> 3) & 0x1f;
+ *out_mac = cs->encoded & 0x7;
+ return true;
+}
+
+} // namespace
+
+namespace net {
+
void SSLCipherSuiteToStrings(const char** key_exchange_str,
const char** cipher_str,
const char** mac_str,
@@ -280,22 +304,10 @@ void SSLCipherSuiteToStrings(const char** key_exchange_str,
*key_exchange_str = *cipher_str = *mac_str = "???";
*is_aead = false;
- struct CipherSuite desired = {0};
- desired.cipher_suite = cipher_suite;
-
- void* r = bsearch(&desired, kCipherSuites,
- arraysize(kCipherSuites), sizeof(kCipherSuites[0]),
- CipherSuiteCmp);
-
- if (!r)
+ int key_exchange, cipher, mac;
+ if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac))
return;
- const CipherSuite* cs = static_cast<CipherSuite*>(r);
-
- const int key_exchange = cs->encoded >> 8;
- const int cipher = (cs->encoded >> 3) & 0x1f;
- const int mac = cs->encoded & 0x7;
-
*key_exchange_str = kKeyExchangeNames[key_exchange].name;
*cipher_str = kCipherNames[cipher].name;
if (mac == kAEADMACValue) {
@@ -346,27 +358,43 @@ bool ParseSSLCipherString(const std::string& cipher_string,
}
bool IsSecureTLSCipherSuite(uint16 cipher_suite) {
- CipherSuite desired = {0};
- desired.cipher_suite = cipher_suite;
+ int key_exchange, cipher, mac;
+ if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac))
+ return false;
+
+ // Only allow forward secure key exchanges.
+ switch (key_exchange) {
+ case 10: // DHE_RSA
+ case 14: // ECDHE_ECDSA
+ case 16: // ECDHE_RSA
+ break;
+ default:
+ return false;
+ }
- void* r = bsearch(&desired,
- kCipherSuites,
- arraysize(kCipherSuites),
- sizeof(kCipherSuites[0]),
- CipherSuiteCmp);
+ switch (cipher) {
+ case 13: // AES_128_GCM
+ case 14: // AES_256_GCM
+ case 17: // CHACHA20_POLY1305
+ break;
+ default:
+ return false;
+ }
- if (!r)
+ // Only AEADs allowed.
+ if (mac != kAEADMACValue)
return false;
- const CipherSuite* cs = static_cast<const CipherSuite*>(r);
+ return true;
+}
- const int key_exchange = cs->encoded >> 8;
- const int cipher = (cs->encoded >> 3) & 0x1f;
- const int mac = cs->encoded & 0x7;
+bool IsFalseStartableTLSCipherSuite(uint16 cipher_suite) {
+ int key_exchange, cipher, mac;
+ if (!GetCipherProperties(cipher_suite, &key_exchange, &cipher, &mac))
+ return false;
- // Only allow forward secure key exchanges.
+ // Only allow ECDHE key exchanges.
switch (key_exchange) {
- case 10: // DHE_RSA
case 14: // ECDHE_ECDSA
case 16: // ECDHE_RSA
break;
diff --git a/chromium/net/ssl/ssl_cipher_suite_names.h b/chromium/net/ssl/ssl_cipher_suite_names.h
index 29c03a1aea0..f7aea964b91 100644
--- a/chromium/net/ssl/ssl_cipher_suite_names.h
+++ b/chromium/net/ssl/ssl_cipher_suite_names.h
@@ -55,7 +55,10 @@ NET_EXPORT bool ParseSSLCipherString(const std::string& cipher_string,
// Currently, this function follows these criteria:
// 1) Only uses forward secure key exchanges
// 2) Only uses AEADs
-NET_EXPORT_PRIVATE bool IsSecureTLSCipherSuite(uint16 cipher_suite);
+NET_EXPORT bool IsSecureTLSCipherSuite(uint16 cipher_suite);
+
+// Returns true if |cipher_suite| is suitable for use with False Start.
+NET_EXPORT bool IsFalseStartableTLSCipherSuite(uint16 cipher_suite);
} // namespace net
diff --git a/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc b/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc
index 042ca82a5d3..6334c30d686 100644
--- a/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc
+++ b/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc
@@ -18,7 +18,7 @@ TEST(CipherSuiteNamesTest, Basic) {
SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xc001);
EXPECT_STREQ("ECDH_ECDSA", key_exchange);
EXPECT_STREQ("NULL", cipher);
- EXPECT_STREQ("SHA1", mac);
+ EXPECT_STREQ("HMAC-SHA1", mac);
EXPECT_FALSE(is_aead);
SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0x009f);
@@ -27,6 +27,12 @@ TEST(CipherSuiteNamesTest, Basic) {
EXPECT_TRUE(is_aead);
EXPECT_EQ(NULL, mac);
+ SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xcc15);
+ EXPECT_STREQ("DHE_RSA", key_exchange);
+ EXPECT_STREQ("CHACHA20_POLY1305", cipher);
+ EXPECT_TRUE(is_aead);
+ EXPECT_EQ(NULL, mac);
+
SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, 0xff31);
EXPECT_STREQ("???", key_exchange);
EXPECT_STREQ("???", cipher);
@@ -70,6 +76,7 @@ TEST(CipherSuiteNamesTest, SecureCipherSuites) {
// Secure ones.
EXPECT_TRUE(IsSecureTLSCipherSuite(0xcc13));
EXPECT_TRUE(IsSecureTLSCipherSuite(0xcc14));
+ EXPECT_TRUE(IsSecureTLSCipherSuite(0xcc15));
}
} // anonymous namespace
diff --git a/chromium/net/ssl/ssl_client_cert_type.h b/chromium/net/ssl/ssl_client_cert_type.h
index dd6e997a1c5..d15d06d5c28 100644
--- a/chromium/net/ssl/ssl_client_cert_type.h
+++ b/chromium/net/ssl/ssl_client_cert_type.h
@@ -11,7 +11,6 @@ namespace net {
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-1
enum SSLClientCertType {
CLIENT_CERT_RSA_SIGN = 1,
- CLIENT_CERT_DSS_SIGN = 2,
CLIENT_CERT_ECDSA_SIGN = 64,
// 224-255 are Reserved for Private Use, we pick one to use as "invalid".
CLIENT_CERT_INVALID_TYPE = 255,
diff --git a/chromium/net/ssl/ssl_client_session_cache_openssl.cc b/chromium/net/ssl/ssl_client_session_cache_openssl.cc
new file mode 100644
index 00000000000..a0f03247a7a
--- /dev/null
+++ b/chromium/net/ssl/ssl_client_session_cache_openssl.cc
@@ -0,0 +1,99 @@
+// Copyright 2015 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/ssl_client_session_cache_openssl.h"
+
+#include <utility>
+
+#include "base/time/clock.h"
+#include "base/time/default_clock.h"
+
+namespace net {
+
+SSLClientSessionCacheOpenSSL::SSLClientSessionCacheOpenSSL(const Config& config)
+ : clock_(new base::DefaultClock),
+ config_(config),
+ cache_(config.max_entries),
+ lookups_since_flush_(0) {
+}
+
+SSLClientSessionCacheOpenSSL::~SSLClientSessionCacheOpenSSL() {
+ Flush();
+}
+
+size_t SSLClientSessionCacheOpenSSL::size() const {
+ return cache_.size();
+}
+
+SSL_SESSION* SSLClientSessionCacheOpenSSL::Lookup(
+ const std::string& cache_key) {
+ base::AutoLock lock(lock_);
+
+ // Expire stale sessions.
+ lookups_since_flush_++;
+ if (lookups_since_flush_ >= config_.expiration_check_count) {
+ lookups_since_flush_ = 0;
+ FlushExpiredSessions();
+ }
+
+ CacheEntryMap::iterator iter = cache_.Get(cache_key);
+ if (iter == cache_.end())
+ return nullptr;
+ if (IsExpired(iter->second, clock_->Now())) {
+ cache_.Erase(iter);
+ return nullptr;
+ }
+ return iter->second->session.get();
+}
+
+void SSLClientSessionCacheOpenSSL::Insert(const std::string& cache_key,
+ SSL_SESSION* session) {
+ base::AutoLock lock(lock_);
+
+ // Make a new entry.
+ CacheEntry* entry = new CacheEntry;
+ entry->session.reset(SSL_SESSION_up_ref(session));
+ entry->creation_time = clock_->Now();
+
+ // Takes ownership.
+ cache_.Put(cache_key, entry);
+}
+
+void SSLClientSessionCacheOpenSSL::Flush() {
+ base::AutoLock lock(lock_);
+
+ cache_.Clear();
+}
+
+void SSLClientSessionCacheOpenSSL::SetClockForTesting(
+ scoped_ptr<base::Clock> clock) {
+ clock_ = clock.Pass();
+}
+
+SSLClientSessionCacheOpenSSL::CacheEntry::CacheEntry() {
+}
+
+SSLClientSessionCacheOpenSSL::CacheEntry::~CacheEntry() {
+}
+
+bool SSLClientSessionCacheOpenSSL::IsExpired(
+ SSLClientSessionCacheOpenSSL::CacheEntry* entry,
+ const base::Time& now) {
+ return now < entry->creation_time ||
+ entry->creation_time + config_.timeout < now;
+}
+
+void SSLClientSessionCacheOpenSSL::FlushExpiredSessions() {
+ base::Time now = clock_->Now();
+ CacheEntryMap::iterator iter = cache_.begin();
+ while (iter != cache_.end()) {
+ if (IsExpired(iter->second, now)) {
+ iter = cache_.Erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_client_session_cache_openssl.h b/chromium/net/ssl/ssl_client_session_cache_openssl.h
new file mode 100644
index 00000000000..9d2f4b57b9b
--- /dev/null
+++ b/chromium/net/ssl/ssl_client_session_cache_openssl.h
@@ -0,0 +1,96 @@
+// Copyright 2015 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_SSL_SSL_CLIENT_SESSION_CACHE_OPENSSL_H
+#define NET_SSL_SSL_CLIENT_SESSION_CACHE_OPENSSL_H
+
+#include <openssl/ssl.h>
+
+#include <string>
+
+#include "base/containers/mru_cache.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "net/base/net_export.h"
+#include "net/ssl/scoped_openssl_types.h"
+
+namespace base {
+class Clock;
+}
+
+namespace net {
+
+class NET_EXPORT SSLClientSessionCacheOpenSSL {
+ public:
+ struct Config {
+ // The maximum number of entries in the cache.
+ size_t max_entries = 1024;
+ // The number of calls to Lookup before a new check for expired sessions.
+ size_t expiration_check_count = 256;
+ // How long each session should last.
+ base::TimeDelta timeout = base::TimeDelta::FromHours(1);
+ };
+
+ explicit SSLClientSessionCacheOpenSSL(const Config& config);
+ ~SSLClientSessionCacheOpenSSL();
+
+ size_t size() const;
+
+ // Returns the session associated with |cache_key| and moves it to the front
+ // of the MRU list. Returns null if there is none. The caller is responsible
+ // for taking a reference to the pointer if the cache is destroyed or a call
+ // to Insert is made.
+ SSL_SESSION* Lookup(const std::string& cache_key);
+
+ // Inserts |session| into the cache at |cache_key|. If there is an existing
+ // one, it is released. Every |expiration_check_count| calls, the cache is
+ // checked for stale entries.
+ void Insert(const std::string& cache_key, SSL_SESSION* session);
+
+ // Removes all entries from the cache.
+ void Flush();
+
+ void SetClockForTesting(scoped_ptr<base::Clock> clock);
+
+ private:
+ struct CacheEntry {
+ CacheEntry();
+ ~CacheEntry();
+
+ ScopedSSL_SESSION session;
+ // The time at which this entry was created.
+ base::Time creation_time;
+ };
+
+ using CacheEntryMap =
+ base::MRUCacheBase<std::string,
+ CacheEntry*,
+ base::MRUCachePointerDeletor<CacheEntry*>,
+ base::MRUCacheHashMap>;
+
+ // Returns true if |entry| is expired as of |now|.
+ bool IsExpired(CacheEntry* entry, const base::Time& now);
+
+ // Removes all expired sessions from the cache.
+ void FlushExpiredSessions();
+
+ scoped_ptr<base::Clock> clock_;
+ Config config_;
+ CacheEntryMap cache_;
+ size_t lookups_since_flush_;
+
+ // TODO(davidben): After https://crbug.com/458365 is fixed, replace this with
+ // a ThreadChecker. The session cache should be single-threaded like other
+ // classes in net.
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLClientSessionCacheOpenSSL);
+};
+
+} // namespace net
+
+#endif // NET_SSL_SSL_CLIENT_SESSION_CACHE_OPENSSL_H
diff --git a/chromium/net/ssl/ssl_client_session_cache_openssl_unittest.cc b/chromium/net/ssl/ssl_client_session_cache_openssl_unittest.cc
new file mode 100644
index 00000000000..8cb9eabb6d6
--- /dev/null
+++ b/chromium/net/ssl/ssl_client_session_cache_openssl_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2015 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/ssl_client_session_cache_openssl.h"
+
+#include <openssl/ssl.h>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/test/simple_test_clock.h"
+#include "net/ssl/scoped_openssl_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+// Test basic insertion and lookup operations.
+TEST(SSLClientSessionCacheOpenSSLTest, Basic) {
+ SSLClientSessionCacheOpenSSL::Config config;
+ SSLClientSessionCacheOpenSSL cache(config);
+
+ ScopedSSL_SESSION session1(SSL_SESSION_new());
+ ScopedSSL_SESSION session2(SSL_SESSION_new());
+ ScopedSSL_SESSION session3(SSL_SESSION_new());
+ EXPECT_EQ(1, session1->references);
+ EXPECT_EQ(1, session2->references);
+ EXPECT_EQ(1, session3->references);
+
+ EXPECT_EQ(nullptr, cache.Lookup("key1"));
+ EXPECT_EQ(nullptr, cache.Lookup("key2"));
+ EXPECT_EQ(0u, cache.size());
+
+ cache.Insert("key1", session1.get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1"));
+ EXPECT_EQ(nullptr, cache.Lookup("key2"));
+ EXPECT_EQ(1u, cache.size());
+
+ cache.Insert("key2", session2.get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1"));
+ EXPECT_EQ(session2.get(), cache.Lookup("key2"));
+ EXPECT_EQ(2u, cache.size());
+
+ EXPECT_EQ(2, session1->references);
+ EXPECT_EQ(2, session2->references);
+
+ cache.Insert("key1", session3.get());
+ EXPECT_EQ(session3.get(), cache.Lookup("key1"));
+ EXPECT_EQ(session2.get(), cache.Lookup("key2"));
+ EXPECT_EQ(2u, cache.size());
+
+ EXPECT_EQ(1, session1->references);
+ EXPECT_EQ(2, session2->references);
+ EXPECT_EQ(2, session3->references);
+
+ cache.Flush();
+ EXPECT_EQ(nullptr, cache.Lookup("key1"));
+ EXPECT_EQ(nullptr, cache.Lookup("key2"));
+ EXPECT_EQ(nullptr, cache.Lookup("key3"));
+ EXPECT_EQ(0u, cache.size());
+
+ EXPECT_EQ(1, session1->references);
+ EXPECT_EQ(1, session2->references);
+ EXPECT_EQ(1, session3->references);
+}
+
+// Test that a session may be inserted at two different keys. This should never
+// be necessary, but the API doesn't prohibit it.
+TEST(SSLClientSessionCacheOpenSSLTest, DoubleInsert) {
+ SSLClientSessionCacheOpenSSL::Config config;
+ SSLClientSessionCacheOpenSSL cache(config);
+
+ ScopedSSL_SESSION session(SSL_SESSION_new());
+ EXPECT_EQ(1, session->references);
+
+ EXPECT_EQ(nullptr, cache.Lookup("key1"));
+ EXPECT_EQ(nullptr, cache.Lookup("key2"));
+ EXPECT_EQ(0u, cache.size());
+
+ cache.Insert("key1", session.get());
+ EXPECT_EQ(session.get(), cache.Lookup("key1"));
+ EXPECT_EQ(nullptr, cache.Lookup("key2"));
+ EXPECT_EQ(1u, cache.size());
+
+ EXPECT_EQ(2, session->references);
+
+ cache.Insert("key2", session.get());
+ EXPECT_EQ(session.get(), cache.Lookup("key1"));
+ EXPECT_EQ(session.get(), cache.Lookup("key2"));
+ EXPECT_EQ(2u, cache.size());
+
+ EXPECT_EQ(3, session->references);
+
+ cache.Flush();
+ EXPECT_EQ(nullptr, cache.Lookup("key1"));
+ EXPECT_EQ(nullptr, cache.Lookup("key2"));
+ EXPECT_EQ(0u, cache.size());
+
+ EXPECT_EQ(1, session->references);
+}
+
+// Tests that the session cache's size is correctly bounded.
+TEST(SSLClientSessionCacheOpenSSLTest, MaxEntries) {
+ SSLClientSessionCacheOpenSSL::Config config;
+ config.max_entries = 3;
+ SSLClientSessionCacheOpenSSL cache(config);
+
+ ScopedSSL_SESSION session1(SSL_SESSION_new());
+ ScopedSSL_SESSION session2(SSL_SESSION_new());
+ ScopedSSL_SESSION session3(SSL_SESSION_new());
+ ScopedSSL_SESSION session4(SSL_SESSION_new());
+
+ // Insert three entries.
+ cache.Insert("key1", session1.get());
+ cache.Insert("key2", session2.get());
+ cache.Insert("key3", session3.get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1"));
+ EXPECT_EQ(session2.get(), cache.Lookup("key2"));
+ EXPECT_EQ(session3.get(), cache.Lookup("key3"));
+ EXPECT_EQ(3u, cache.size());
+
+ // On insertion of a fourth, the first is removed.
+ cache.Insert("key4", session4.get());
+ EXPECT_EQ(nullptr, cache.Lookup("key1"));
+ EXPECT_EQ(session4.get(), cache.Lookup("key4"));
+ EXPECT_EQ(session3.get(), cache.Lookup("key3"));
+ EXPECT_EQ(session2.get(), cache.Lookup("key2"));
+ EXPECT_EQ(3u, cache.size());
+
+ // Despite being newest, the next to be removed is session4 as it was accessed
+ // least. recently.
+ cache.Insert("key1", session1.get());
+ EXPECT_EQ(session1.get(), cache.Lookup("key1"));
+ EXPECT_EQ(session2.get(), cache.Lookup("key2"));
+ EXPECT_EQ(session3.get(), cache.Lookup("key3"));
+ EXPECT_EQ(nullptr, cache.Lookup("key4"));
+ EXPECT_EQ(3u, cache.size());
+}
+
+// Tests that session expiration works properly.
+TEST(SSLClientSessionCacheOpenSSLTest, Expiration) {
+ const size_t kNumEntries = 20;
+ const size_t kExpirationCheckCount = 10;
+ const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000);
+
+ SSLClientSessionCacheOpenSSL::Config config;
+ config.expiration_check_count = kExpirationCheckCount;
+ config.timeout = kTimeout;
+ SSLClientSessionCacheOpenSSL cache(config);
+ base::SimpleTestClock* clock = new base::SimpleTestClock;
+ cache.SetClockForTesting(make_scoped_ptr(clock));
+
+ // Add |kNumEntries - 1| entries.
+ for (size_t i = 0; i < kNumEntries - 1; i++) {
+ ScopedSSL_SESSION session(SSL_SESSION_new());
+ cache.Insert(base::SizeTToString(i), session.get());
+ }
+ EXPECT_EQ(kNumEntries - 1, cache.size());
+
+ // Expire all the previous entries and insert one more entry.
+ clock->Advance(kTimeout * 2);
+ ScopedSSL_SESSION session(SSL_SESSION_new());
+ cache.Insert("key", session.get());
+
+ // All entries are still in the cache.
+ EXPECT_EQ(kNumEntries, cache.size());
+
+ // Perform one fewer lookup than needed to trigger the expiration check. This
+ // shall not expire any session.
+ for (size_t i = 0; i < kExpirationCheckCount - 1; i++)
+ cache.Lookup("key");
+
+ // All entries are still in the cache.
+ EXPECT_EQ(kNumEntries, cache.size());
+
+ // Perform one more lookup. This will expire all sessions but the last one.
+ cache.Lookup("key");
+ EXPECT_EQ(1u, cache.size());
+ EXPECT_EQ(session.get(), cache.Lookup("key"));
+ for (size_t i = 0; i < kNumEntries - 1; i++) {
+ SCOPED_TRACE(i);
+ EXPECT_EQ(nullptr, cache.Lookup(base::SizeTToString(i)));
+ }
+}
+
+// Tests that Lookup performs an expiration check before returning a cached
+// session.
+TEST(SSLClientSessionCacheOpenSSLTest, LookupExpirationCheck) {
+ // kExpirationCheckCount is set to a suitably large number so the automated
+ // pruning never triggers.
+ const size_t kExpirationCheckCount = 1000;
+ const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(1000);
+
+ SSLClientSessionCacheOpenSSL::Config config;
+ config.expiration_check_count = kExpirationCheckCount;
+ config.timeout = kTimeout;
+ SSLClientSessionCacheOpenSSL cache(config);
+ base::SimpleTestClock* clock = new base::SimpleTestClock;
+ cache.SetClockForTesting(make_scoped_ptr(clock));
+
+ // Insert an entry into the session cache.
+ ScopedSSL_SESSION session(SSL_SESSION_new());
+ cache.Insert("key", session.get());
+ EXPECT_EQ(session.get(), cache.Lookup("key"));
+ EXPECT_EQ(1u, cache.size());
+
+ // Expire the session.
+ clock->Advance(kTimeout * 2);
+
+ // The entry has not been removed yet.
+ EXPECT_EQ(1u, cache.size());
+
+ // But it will not be returned on lookup and gets pruned at that point.
+ EXPECT_EQ(nullptr, cache.Lookup("key"));
+ EXPECT_EQ(0u, cache.size());
+
+ // Sessions also are treated as expired if the clock rewinds.
+ cache.Insert("key", session.get());
+ EXPECT_EQ(session.get(), cache.Lookup("key"));
+ EXPECT_EQ(1u, cache.size());
+
+ clock->Advance(-kTimeout * 2);
+
+ EXPECT_EQ(nullptr, cache.Lookup("key"));
+ EXPECT_EQ(0u, cache.size());
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/ssl_config.cc b/chromium/net/ssl/ssl_config.cc
index 8efdd58386e..ada954f1db3 100644
--- a/chromium/net/ssl/ssl_config.cc
+++ b/chromium/net/ssl/ssl_config.cc
@@ -4,12 +4,12 @@
#include "net/ssl/ssl_config.h"
+#include "net/socket/ssl_client_socket.h"
+
namespace net {
const uint16 kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_TLS1;
-const uint16 kDefaultSSLVersionMax = SSL_PROTOCOL_VERSION_TLS1_2;
-
const uint16 kDefaultSSLVersionFallbackMin = SSL_PROTOCOL_VERSION_TLS1;
SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
@@ -20,16 +20,20 @@ SSLConfig::SSLConfig()
: rev_checking_enabled(false),
rev_checking_required_local_anchors(false),
version_min(kDefaultSSLVersionMin),
- version_max(kDefaultSSLVersionMax),
+ version_max(SSLClientSocket::GetMaxSupportedSSLVersion()),
version_fallback_min(kDefaultSSLVersionFallbackMin),
+ enable_deprecated_cipher_suites(false),
channel_id_enabled(true),
false_start_enabled(true),
signed_cert_timestamps_enabled(true),
- require_forward_secrecy(false),
+ require_ecdhe(false),
send_client_cert(false),
verify_ev_cert(false),
version_fallback(false),
- cert_io_enabled(true) {
+ cert_io_enabled(true),
+ renego_allowed_default(false),
+ fastradio_padding_enabled(false),
+ fastradio_padding_eligible(false) {
}
SSLConfig::~SSLConfig() {}
diff --git a/chromium/net/ssl/ssl_config.h b/chromium/net/ssl/ssl_config.h
index 1deaf6e653b..853e8812223 100644
--- a/chromium/net/ssl/ssl_config.h
+++ b/chromium/net/ssl/ssl_config.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
#include "net/cert/x509_certificate.h"
+#include "net/socket/next_proto.h"
namespace net {
@@ -20,7 +21,6 @@ namespace net {
// The most significant byte is |major|, and the least significant byte
// is |minor|.
enum {
- SSL_PROTOCOL_VERSION_SSL3 = 0x0300,
SSL_PROTOCOL_VERSION_TLS1 = 0x0301,
SSL_PROTOCOL_VERSION_TLS1_1 = 0x0302,
SSL_PROTOCOL_VERSION_TLS1_2 = 0x0303,
@@ -29,8 +29,8 @@ enum {
// Default minimum protocol version.
NET_EXPORT extern const uint16 kDefaultSSLVersionMin;
-// Default maximum protocol version.
-NET_EXPORT extern const uint16 kDefaultSSLVersionMax;
+// For maximum supported protocol version, use
+// SSLClientSocket::GetMaxSupportedSSLVersion().
// Default minimum protocol version that it's acceptable to fallback to.
NET_EXPORT extern const uint16 kDefaultSSLVersionFallbackMin;
@@ -38,7 +38,6 @@ NET_EXPORT extern const uint16 kDefaultSSLVersionFallbackMin;
// A collection of SSL-related configuration settings.
struct NET_EXPORT SSLConfig {
// Default to revocation checking.
- // Default to SSL 3.0 ~ default_version_max() on.
SSLConfig();
~SSLConfig();
@@ -69,10 +68,9 @@ struct NET_EXPORT SSLConfig {
bool rev_checking_required_local_anchors;
// The minimum and maximum protocol versions that are enabled.
- // SSL 3.0 is 0x0300, TLS 1.0 is 0x0301, TLS 1.1 is 0x0302, and so on.
// (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined above.)
- // SSL 2.0 is not supported. If version_max < version_min, it means no
- // protocol versions are enabled.
+ // SSL 2.0 and SSL 3.0 are not supported. If version_max < version_min, it
+ // means no protocol versions are enabled.
uint16 version_min;
uint16 version_max;
@@ -105,16 +103,19 @@ struct NET_EXPORT SSLConfig {
// disable TLS_ECDH_ECDSA_WITH_RC4_128_SHA, specify 0xC002.
std::vector<uint16> disabled_cipher_suites;
+ // Enables deprecated cipher suites. Currently, RC4 is deprecated.
+ bool enable_deprecated_cipher_suites;
+
bool channel_id_enabled; // True if TLS channel ID extension is enabled.
bool false_start_enabled; // True if we'll use TLS False Start.
// True if the Certificate Transparency signed_certificate_timestamp
// TLS extension is enabled.
bool signed_cert_timestamps_enabled;
- // require_forward_secrecy, if true, causes only (EC)DHE cipher suites to be
- // enabled. NOTE: this only applies to server sockets currently, although
- // that could be extended if needed.
- bool require_forward_secrecy;
+ // If true, causes only ECDHE cipher suites to be enabled. NOTE: This only
+ // applies to server sockets currently, although that could be extended if
+ // needed.
+ bool require_ecdhe;
// TODO(wtc): move the following members to a new SSLParams structure. They
// are not SSL configuration settings.
@@ -155,9 +156,26 @@ struct NET_EXPORT SSLConfig {
// Protocol Negotiation, but there is no overlap between the server's and
// client's protocol sets, then the first protocol in this list will be
// requested by the client.
- std::vector<std::string> next_protos;
+ NextProtoVector next_protos;
+
+ // True if renegotiation should be allowed for the default application-level
+ // protocol when the peer negotiates neither ALPN nor NPN.
+ bool renego_allowed_default;
+
+ // The list of application-level protocols to enable renegotiation for.
+ NextProtoVector renego_allowed_for_protos;
scoped_refptr<X509Certificate> client_cert;
+
+ // Information about how to proceed with fastradio padding.
+ // |fastradio_padding_enabled| determines if the feature is enabled globally.
+ // |fastradio_padding_eligible| determines if the endpoint associated with
+ // this config should use it.
+ // |fastradio_padding_eligible| can be true when |fastradio_padding_enabled|
+ // is false: in this case, fastradio padding would not be enabled, but
+ // metrics can be collected for experiments.
+ bool fastradio_padding_enabled;
+ bool fastradio_padding_eligible;
};
} // namespace net
diff --git a/chromium/net/ssl/ssl_config_service.cc b/chromium/net/ssl/ssl_config_service.cc
index 4661930dc51..5b57cc2c4a9 100644
--- a/chromium/net/ssl/ssl_config_service.cc
+++ b/chromium/net/ssl/ssl_config_service.cc
@@ -77,6 +77,10 @@ void SSLConfigService::NotifySSLConfigChange() {
FOR_EACH_OBSERVER(Observer, observer_list_, OnSSLConfigChanged());
}
+bool SSLConfigService::SupportsFastradioPadding(const GURL& url) {
+ return false;
+}
+
SSLConfigService::~SSLConfigService() {
}
@@ -92,8 +96,7 @@ void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
new_config.disabled_cipher_suites) ||
(orig_config.channel_id_enabled != new_config.channel_id_enabled) ||
(orig_config.false_start_enabled != new_config.false_start_enabled) ||
- (orig_config.require_forward_secrecy !=
- new_config.require_forward_secrecy);
+ (orig_config.require_ecdhe != new_config.require_ecdhe);
if (config_changed)
NotifySSLConfigChange();
diff --git a/chromium/net/ssl/ssl_config_service.h b/chromium/net/ssl/ssl_config_service.h
index e074309ffac..dd3236d2a58 100644
--- a/chromium/net/ssl/ssl_config_service.h
+++ b/chromium/net/ssl/ssl_config_service.h
@@ -14,6 +14,8 @@
#include "net/cert/ct_ev_whitelist.h"
#include "net/ssl/ssl_config.h"
+class GURL;
+
namespace net {
// The interface for retrieving the SSL configuration. This interface
@@ -66,6 +68,9 @@ class NET_EXPORT SSLConfigService
// called on the IO thread.
void NotifySSLConfigChange();
+ // Returns true if the |url| should use fastradio padding.
+ virtual bool SupportsFastradioPadding(const GURL& url);
+
protected:
friend class base::RefCountedThreadSafe<SSLConfigService>;
diff --git a/chromium/net/ssl/ssl_config_service_unittest.cc b/chromium/net/ssl/ssl_config_service_unittest.cc
index 7306c68d713..7428dd00eb9 100644
--- a/chromium/net/ssl/ssl_config_service_unittest.cc
+++ b/chromium/net/ssl/ssl_config_service_unittest.cc
@@ -49,8 +49,8 @@ TEST(SSLConfigServiceTest, NoChangesWontNotifyObservers) {
SSLConfig initial_config;
initial_config.rev_checking_enabled = true;
initial_config.false_start_enabled = false;
- initial_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
- initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
+ initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
+ initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
scoped_refptr<MockSSLConfigService> mock_service(
new MockSSLConfigService(initial_config));
@@ -67,8 +67,8 @@ TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) {
SSLConfig initial_config;
initial_config.rev_checking_enabled = true;
initial_config.false_start_enabled = false;
- initial_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
- initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
+ initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
+ initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
scoped_refptr<MockSSLConfigService> mock_service(
new MockSSLConfigService(initial_config));
@@ -85,11 +85,11 @@ TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) {
mock_service->SetSSLConfig(initial_config);
// Test that changing the SSL version range triggers updates.
- initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
+ initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1_1;
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
- initial_config.version_max = SSL_PROTOCOL_VERSION_SSL3;
+ initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
diff --git a/chromium/net/ssl/ssl_connection_status_flags.h b/chromium/net/ssl/ssl_connection_status_flags.h
index faae306a505..5d806ae7d72 100644
--- a/chromium/net/ssl/ssl_connection_status_flags.h
+++ b/chromium/net/ssl/ssl_connection_status_flags.h
@@ -13,7 +13,6 @@ namespace net {
// Status flags for SSLInfo::connection_status.
enum {
// The lower 16 bits are reserved for the TLS ciphersuite id.
- SSL_CONNECTION_CIPHERSUITE_SHIFT = 0,
SSL_CONNECTION_CIPHERSUITE_MASK = 0xffff,
// The next two bits are reserved for the compression used.
@@ -38,7 +37,8 @@ enum {
};
// NOTE: the SSL version enum constants must be between 0 and
-// SSL_CONNECTION_VERSION_MASK, inclusive.
+// SSL_CONNECTION_VERSION_MASK, inclusive. These values are persisted to disk
+// and used in UMA, so they must remain stable.
enum {
SSL_CONNECTION_VERSION_UNKNOWN = 0, // Unknown SSL version.
SSL_CONNECTION_VERSION_SSL2 = 1,
@@ -50,12 +50,11 @@ enum {
SSL_CONNECTION_VERSION_QUIC = 7,
SSL_CONNECTION_VERSION_MAX,
};
-COMPILE_ASSERT(SSL_CONNECTION_VERSION_MAX - 1 <= SSL_CONNECTION_VERSION_MASK,
- SSL_CONNECTION_VERSION_MASK_too_small);
+static_assert(SSL_CONNECTION_VERSION_MAX - 1 <= SSL_CONNECTION_VERSION_MASK,
+ "SSL_CONNECTION_VERSION_MASK too small");
-inline int SSLConnectionStatusToCipherSuite(int connection_status) {
- return (connection_status >> SSL_CONNECTION_CIPHERSUITE_SHIFT) &
- SSL_CONNECTION_CIPHERSUITE_MASK;
+inline uint16 SSLConnectionStatusToCipherSuite(int connection_status) {
+ return static_cast<uint16>(connection_status);
}
inline int SSLConnectionStatusToVersion(int connection_status) {
@@ -63,14 +62,12 @@ inline int SSLConnectionStatusToVersion(int connection_status) {
SSL_CONNECTION_VERSION_MASK;
}
-inline void SSLConnectionStatusSetCipherSuite(int cipher_suite,
+inline void SSLConnectionStatusSetCipherSuite(uint16 cipher_suite,
int* connection_status) {
// Clear out the old ciphersuite.
- *connection_status &=
- ~(SSL_CONNECTION_CIPHERSUITE_MASK << SSL_CONNECTION_CIPHERSUITE_SHIFT);
+ *connection_status &= ~SSL_CONNECTION_CIPHERSUITE_MASK;
// Set the new ciphersuite.
- *connection_status |= ((cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK)
- << SSL_CONNECTION_CIPHERSUITE_SHIFT);
+ *connection_status |= cipher_suite;
}
inline void SSLConnectionStatusSetVersion(int version, int* connection_status) {
diff --git a/chromium/net/ssl/ssl_connection_status_flags_unittest.cc b/chromium/net/ssl/ssl_connection_status_flags_unittest.cc
index 64fea1313a3..98e4f53b3fd 100644
--- a/chromium/net/ssl/ssl_connection_status_flags_unittest.cc
+++ b/chromium/net/ssl/ssl_connection_status_flags_unittest.cc
@@ -15,13 +15,13 @@ TEST(SSLConnectionStatusTest, SetCipherSuite) {
int expected_version = SSLConnectionStatusToVersion(connection_status);
SSLConnectionStatusSetCipherSuite(12345, &connection_status);
- EXPECT_EQ(12345, SSLConnectionStatusToCipherSuite(connection_status));
+ EXPECT_EQ(12345U, SSLConnectionStatusToCipherSuite(connection_status));
EXPECT_EQ(expected_version, SSLConnectionStatusToVersion(connection_status));
}
TEST(SSLConnectionStatusTest, SetVersion) {
int connection_status = 0xDEADBEEF;
- int expected_cipher_suite =
+ uint16 expected_cipher_suite =
SSLConnectionStatusToCipherSuite(connection_status);
SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_2,
diff --git a/chromium/net/ssl/ssl_failure_state.h b/chromium/net/ssl/ssl_failure_state.h
new file mode 100644
index 00000000000..5f43e0ab434
--- /dev/null
+++ b/chromium/net/ssl/ssl_failure_state.h
@@ -0,0 +1,49 @@
+// Copyright 2015 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_SSL_SSL_FAILURE_STATE_H_
+#define NET_SSL_SSL_FAILURE_STATE_H_
+
+namespace net {
+
+// Describes the most likely cause for the TLS handshake failure. This is an
+// approximation used to classify the causes of TLS version fallback. These
+// values are used in histograms, so new values must be appended.
+enum SSLFailureState {
+ // The connection was successful.
+ SSL_FAILURE_NONE = 0,
+
+ // The connection failed for unknown reasons.
+ SSL_FAILURE_UNKNOWN = 1,
+
+ // The connection failed after sending ClientHello and before receiving
+ // ServerHello.
+ SSL_FAILURE_CLIENT_HELLO = 2,
+
+ // The connection failed after negotiating TLS_RSA_WITH_AES_128_GCM_SHA256 or
+ // TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 and completing the client's second
+ // leg. Some Microsoft IIS servers fail at this point. See
+ // https://crbug.com/433406.
+ SSL_FAILURE_BUGGY_GCM = 3,
+
+ // The connection failed after CertificateVerify was sent. Some servers are
+ // known to incorrectly implement TLS 1.2 client auth.
+ SSL_FAILURE_CLIENT_AUTH = 4,
+
+ // The connection failed because the server attempted to resume a session at
+ // the wrong version. Some versions of OpenSSL may do this in rare
+ // circumstances. See https://crbug.com/441456
+ SSL_FAILURE_SESSION_MISMATCH = 5,
+
+ // The connection failed after sending the NextProto message. Some F5 servers
+ // fail to parse such messages in TLS 1.1 and TLS 1.2, but not 1.0. See
+ // https://crbug.com/466977.
+ SSL_FAILURE_NEXT_PROTO = 6,
+
+ SSL_FAILURE_MAX,
+};
+
+} // namespace net
+
+#endif // NET_SSL_SSL_FAILURE_STATE_H_