]> granicus.if.org Git - curl/commitdiff
nss: add support for TLS False Start
authorAlessandro Ghedini <alessandro@ghedini.me>
Sat, 14 Feb 2015 15:59:01 +0000 (16:59 +0100)
committerKamil Dudka <kdudka@redhat.com>
Fri, 20 Mar 2015 19:14:35 +0000 (20:14 +0100)
lib/vtls/nss.c
lib/vtls/nssg.h

index 841d6b75d48244a33e2d1fb33d28aeaa8a97ce81..22d3730a813b38725e1043e0d4092175a48cdc89 100644 (file)
@@ -728,6 +728,64 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
   }
 }
 
+static SECStatus CanFalseStartCallback(PRFileDesc *sock, void *client_data,
+                                       PRBool *canFalseStart)
+{
+  struct connectdata *conn = client_data;
+  struct SessionHandle *data = conn->data;
+
+  SSLChannelInfo channelInfo;
+  SSLCipherSuiteInfo cipherInfo;
+
+  SECStatus rv;
+  PRBool negotiatedExtension;
+
+  *canFalseStart = PR_FALSE;
+
+  if(SSL_GetChannelInfo(sock, &channelInfo, sizeof(channelInfo)) != SECSuccess)
+    return SECFailure;
+
+  if(SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,
+                            sizeof(cipherInfo)) != SECSuccess)
+    return SECFailure;
+
+  /* Prevent version downgrade attacks from TLS 1.2, and avoid False Start for
+   * TLS 1.3 and later. See https://bugzilla.mozilla.org/show_bug.cgi?id=861310
+   */
+  if(channelInfo.protocolVersion != SSL_LIBRARY_VERSION_TLS_1_2)
+    goto end;
+
+  /* Only allow ECDHE key exchange algorithm.
+   * See https://bugzilla.mozilla.org/show_bug.cgi?id=952863 */
+  if(cipherInfo.keaType != ssl_kea_ecdh)
+    goto end;
+
+  /* Prevent downgrade attacks on the symmetric cipher. We do not allow CBC
+   * mode due to BEAST, POODLE, and other attacks on the MAC-then-Encrypt
+   * design. See https://bugzilla.mozilla.org/show_bug.cgi?id=1109766 */
+  if(cipherInfo.symCipher != ssl_calg_aes_gcm)
+    goto end;
+
+  /* Enforce ALPN or NPN to do False Start, as an indicator of server
+   * compatibility. */
+  rv = SSL_HandshakeNegotiatedExtension(sock, ssl_app_layer_protocol_xtn,
+                                        &negotiatedExtension);
+  if(rv != SECSuccess || !negotiatedExtension) {
+    rv = SSL_HandshakeNegotiatedExtension(sock, ssl_next_proto_nego_xtn,
+                                          &negotiatedExtension);
+  }
+
+  if(rv != SECSuccess || !negotiatedExtension)
+    goto end;
+
+  *canFalseStart = PR_TRUE;
+
+  infof(data, "Trying TLS False Start\n");
+
+end:
+  return SECSuccess;
+}
+
 static void display_cert_info(struct SessionHandle *data,
                               CERTCertificate *cert)
 {
@@ -1652,6 +1710,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 #endif
 
+#ifdef SSL_ENABLE_FALSE_START
+  if(data->set.ssl.falsestart) {
+    if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
+        != SECSuccess)
+      goto error;
+
+    if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback,
+        conn) != SECSuccess)
+      goto error;
+  }
+#endif
+
 #if defined(SSL_ENABLE_NPN) || defined(SSL_ENABLE_ALPN)
   if(data->set.ssl_enable_npn || data->set.ssl_enable_alpn) {
     int cur = 0;
@@ -1929,4 +1999,12 @@ bool Curl_nss_cert_status_request(void)
 #endif
 }
 
+bool Curl_nss_false_start(void) {
+#ifdef SSL_ENABLE_FALSE_START
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
 #endif /* USE_NSS */
index 38e75456f62bd0b296de9215908bd89f2fc02224..d0e74124eff0134d89e9633eba66725942e1e707 100644 (file)
@@ -58,6 +58,8 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
 
 bool Curl_nss_cert_status_request(void);
 
+bool Curl_nss_false_start(void);
+
 /* Set the API backend definition to NSS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
 
@@ -88,6 +90,7 @@ bool Curl_nss_cert_status_request(void);
 #define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
 #define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
 #define curlssl_cert_status_request() Curl_nss_cert_status_request()
+#define curlssl_false_start() Curl_nss_false_start()
 
 #endif /* USE_NSS */
 #endif /* HEADER_CURL_NSSG_H */