Commit 297902cc authored by Shijin Kong's avatar Shijin Kong Committed by woo

enable ssl false start with Next Protocol Negotiation (NPN) extension

Summary:
This speeds up TLS handshake and might be a factor of liger perf regression.
The enabling is guarded by an #ifdef. The condition itself is defined in an
openssl patch.

Test Plan: folly unit tests pass. Tried on devices as well and from tcpdump data was sent before the new ticket was received, essentially speeded up the handshake process.

Reviewed By: subodh@fb.com

Subscribers: trunkagent, kmdent, seanc, benyluo, ssl-diffs@, ranjeeth, folly-diffs@

FB internal diff: D1806856

Tasks: 5284979

Signature: t1:1806856:1422494521:0a048ea9001da13b5d698b5a764d1e66dcbedc99
parent d6415c69
......@@ -419,6 +419,90 @@ int SSLContext::advertisedNextProtocolCallback(SSL* ssl,
return SSL_TLSEXT_ERR_OK;
}
#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH) && \
FOLLY_SSLCONTEXT_USE_TLS_FALSE_START
SSLContext::SSLFalseStartChecker::SSLFalseStartChecker() :
// The list was generated as follows:
// grep "_CK_" openssl-1.0.1e/ssl/s3_lib.c -A 4 | while read A && read B && read C && read D && read E && read F; do echo $A $B $C $D $E; done | \
// grep "\(SSL_kDHr\|SSL_kDHd\|SSL_kEDH\|SSL_kECDHr\|SSL_kECDHe\|SSL_kEECDH\)" | grep -v SSL_aNULL | grep SSL_AES | awk -F, '{ print $1"," }'
ciphers_{
TLS1_CK_DH_DSS_WITH_AES_128_SHA,
TLS1_CK_DH_RSA_WITH_AES_128_SHA,
TLS1_CK_DHE_DSS_WITH_AES_128_SHA,
TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
TLS1_CK_DH_DSS_WITH_AES_256_SHA,
TLS1_CK_DH_RSA_WITH_AES_256_SHA,
TLS1_CK_DHE_DSS_WITH_AES_256_SHA,
TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
TLS1_CK_DH_DSS_WITH_AES_128_SHA256,
TLS1_CK_DH_RSA_WITH_AES_128_SHA256,
TLS1_CK_DHE_DSS_WITH_AES_128_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
TLS1_CK_DH_DSS_WITH_AES_256_SHA256,
TLS1_CK_DH_RSA_WITH_AES_256_SHA256,
TLS1_CK_DHE_DSS_WITH_AES_256_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256,
TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384,
TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256,
TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384,
TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256,
TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384,
TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256,
TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384,
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256,
} {
length_ = sizeof(ciphers_)/sizeof(ciphers_[0]);
width_ = sizeof(ciphers_[0]);
qsort(ciphers_, length_, width_, compare_ulong);
}
bool SSLContext::SSLFalseStartChecker::canUseFalseStartWithCipher(
const SSL_CIPHER *cipher) {
unsigned long cid = cipher->id;
unsigned long *r =
(unsigned long*)bsearch(&cid, ciphers_, length_, width_, compare_ulong);
return r != nullptr;
}
int
SSLContext::SSLFalseStartChecker::compare_ulong(const void *x, const void *y) {
if (*(unsigned long *)x < *(unsigned long *)y) {
return -1;
}
if (*(unsigned long *)x > *(unsigned long *)y) {
return 1;
}
return 0;
};
bool SSLContext::canUseFalseStartWithCipher(const SSL_CIPHER *cipher) {
return falseStartChecker_.canUseFalseStartWithCipher(cipher);
}
#endif
int SSLContext::selectNextProtocolCallback(
SSL* ssl, unsigned char **out, unsigned char *outlen,
const unsigned char *server, unsigned int server_len, void *data) {
......@@ -444,6 +528,14 @@ int SSLContext::selectNextProtocolCallback(
if (retval != OPENSSL_NPN_NEGOTIATED) {
VLOG(3) << "SSLContext::selectNextProcolCallback() "
<< "unable to pick a next protocol.";
#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH) && \
FOLLY_SSLCONTEXT_USE_TLS_FALSE_START
} else {
const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
if (cipher && ctx->canUseFalseStartWithCipher(cipher)) {
SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
}
#endif
}
return SSL_TLSEXT_ERR_OK;
}
......
......@@ -31,6 +31,10 @@
#include <glog/logging.h>
#ifndef FOLLY_NO_CONFIG
#include <folly/folly-config.h>
#endif
namespace folly {
/**
......@@ -326,6 +330,11 @@ class SSLContext {
*/
void unsetNextProtocols();
void deleteNextProtocolsStrings();
#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH) && \
FOLLY_SSLCONTEXT_USE_TLS_FALSE_START
bool canUseFalseStartWithCipher(const SSL_CIPHER *cipher);
#endif
#endif // OPENSSL_NPN_NEGOTIATED
/**
......@@ -432,6 +441,29 @@ class SSLContext {
static int selectNextProtocolCallback(
SSL* ssl, unsigned char **out, unsigned char *outlen,
const unsigned char *server, unsigned int server_len, void *args);
#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH) && \
FOLLY_SSLCONTEXT_USE_TLS_FALSE_START
// This class contains all allowed ciphers for SSL false start. Call its
// `canUseFalseStartWithCipher` to check for cipher qualification.
class SSLFalseStartChecker {
public:
SSLFalseStartChecker();
bool canUseFalseStartWithCipher(const SSL_CIPHER *cipher);
private:
static int compare_ulong(const void *x, const void *y);
// All ciphers that are allowed to use false start.
unsigned long ciphers_[47];
unsigned int length_;
unsigned int width_;
};
SSLFalseStartChecker falseStartChecker_;
#endif
#endif // OPENSSL_NPN_NEGOTIATED
static int passwordCallback(char* password, int size, int, void* data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment