Use false start with ALPN.
authorKyle Nekritz <knekritz@fb.com>
Thu, 3 Mar 2016 18:33:19 +0000 (10:33 -0800)
committerFacebook Github Bot 4 <facebook-github-bot-4-bot@fb.com>
Thu, 3 Mar 2016 18:35:28 +0000 (10:35 -0800)
Summary: All the work we do in SSLContext to check the cipher and NPN usage is actually completely unnecessary since OpenSSL internally checks the cipher and use of ALPN/NPN after you set the SSL_MODE option (see `ssl3_can_cutthrough()` in ssl_lib.c). This just sets the option on the SSLContext instead.

Reviewed By: siyengar

Differential Revision: D3002063

fb-gh-sync-id: 4514faf9ed2eb42a6e41d9e682b2c8aa52c46691
shipit-source-id: 4514faf9ed2eb42a6e41d9e682b2c8aa52c46691

folly/io/async/SSLContext.cpp
folly/io/async/SSLContext.h

index 6e51db562c7c1c2ab14ab285ea8f4b09ac1f727b..637a0e1f708c531408dd2a5a7209fade784f9a69 100644 (file)
@@ -510,66 +510,6 @@ 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() :
-  ciphers_{
-    TLS1_CK_DHE_DSS_WITH_AES_128_SHA,
-    TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
-    TLS1_CK_DHE_DSS_WITH_AES_256_SHA,
-    TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
-    TLS1_CK_DHE_DSS_WITH_AES_128_SHA256,
-    TLS1_CK_DHE_RSA_WITH_AES_128_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_DHE_DSS_WITH_AES_128_GCM_SHA256,
-    TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384,
-    TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
-    TLS1_CK_ECDHE_ECDSA_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_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-    TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-    TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
-  } {
-  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,
@@ -606,14 +546,6 @@ int SSLContext::selectNextProtocolCallback(SSL* ssl,
   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;
 }
@@ -766,6 +698,12 @@ void SSLContext::setSSLLockTypes(std::map<int, SSLLockType> inLockTypes) {
   lockTypes() = inLockTypes;
 }
 
+#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
+void SSLContext::enableFalseStart() {
+  SSL_CTX_set_mode(ctx_, SSL_MODE_HANDSHAKE_CUTTHROUGH);
+}
+#endif
+
 void SSLContext::markInitialized() {
   std::lock_guard<std::mutex> g(initMutex());
   initialized_ = true;
index 09592b46594c8985c9247ff4611330a4a5a0b006..03d4175876d6727dd4b8e845b67d1c18b94d8e2a 100644 (file)
@@ -376,11 +376,6 @@ 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
 
   /**
@@ -437,6 +432,15 @@ class SSLContext {
   bool checkPeerName() { return checkPeerName_; }
   std::string peerFixedName() { return peerFixedName_; }
 
+#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
+  /**
+   * Enable TLS false start, saving a roundtrip for full handshakes. Will only
+   * be used if the server uses NPN or ALPN, and a strong forward-secure cipher
+   * is negotiated.
+   */
+  void enableFalseStart();
+#endif
+
   /**
    * Helper to match a hostname versus a pattern.
    */
@@ -512,28 +516,6 @@ class SSLContext {
 #endif
   size_t pickNextProtocols();
 
-#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);