Hello, I've implemented new libcurl/curl options for enabling TLS false start [0]. AFAICT only nss supports it so only the nss backend implements the new option.
Both chromium and firefox enable false start only if the server also suports NPN/ALPN or if it supports forward secrecy in order to avoid weird/broken SSL implementations. Also, since there is a chance that application data is sent to an imposter (since we send the data before verifying the server's Finished frame), it is also recommended to only enable false start when strong ciphers are used. So I wonder, should we do all theses checks in libcurl too or just let the user decide? Anyway, see attached patches (I'm sending them during the freeze so that I can get some comments early). To verify that it works you can use wireshark to capture the TLS handshake. For example, using curl on the server https://www.ghedini.me without false start, the first "Application Data" comes after the server's "Change Cipher Spec": 10 0.167263 192.168.1.129 -> 149.154.152.214 TLSv1.2 640 Client Key Exchange, Change Cipher Spec, Hello Request, Hello Request 11 0.279561 149.154.152.214 -> 192.168.1.129 TCP 66 443→36077 [ACK] Seq=3565 Ack=709 Win=15552 Len=0 TSval=390241702 TSecr=6631431 12 0.337845 149.154.152.214 -> 192.168.1.129 TLSv1.2 117 Change Cipher Spec, Encrypted Handshake Message 13 0.338256 192.168.1.129 -> 149.154.152.214 TLSv1.2 177 Application Data With false start enabled the "Application Data" comes before the "Change Cipher Spec": 10 0.170108 192.168.1.129 -> 149.154.152.214 TLSv1.2 640 Client Key Exchange, Change Cipher Spec, Hello Request, Hello Request 11 0.288298 149.154.152.214 -> 192.168.1.129 TCP 66 443→36080 [ACK] Seq=3565 Ack=709 Win=15552 Len=0 TSval=390260804 TSecr=6650533 12 0.288338 192.168.1.129 -> 149.154.152.214 TLSv1.2 177 Application Data 13 0.345018 149.154.152.214 -> 192.168.1.129 TLSv1.2 117 Change Cipher Spec, Encrypted Handshake Message Cheers [0] https://tools.ietf.org/html/draft-bmoeller-tls-falsestart
From f82be0415046e299b922e8fbb350d0449fad35b4 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini <[email protected]> Date: Sat, 14 Feb 2015 16:57:07 +0100 Subject: [PATCH 1/3] url: add CURLOPT_SSL_FALSESTART option This option can be used to enable/disable TLS False Start defined in the RFC draft-bmoeller-tls-falsestart. --- docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 | 48 ++++++++++++++++++++++++++++++ include/curl/curl.h | 3 ++ lib/url.c | 11 +++++++ lib/urldata.h | 1 + lib/vtls/vtls.c | 12 ++++++++ lib/vtls/vtls.h | 3 ++ 6 files changed, 78 insertions(+) create mode 100644 docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 diff --git a/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 new file mode 100644 index 0000000..7d88fc4 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_SSL_FALSESTART.3 @@ -0,0 +1,48 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al. +.\" * +.\" * This software is licensed as described in the file COPYING, which +.\" * you should have received as part of this distribution. The terms +.\" * are also available at http://curl.haxx.se/docs/copyright.html. +.\" * +.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell +.\" * copies of the Software, and permit persons to whom the Software is +.\" * furnished to do so, under the terms of the COPYING file. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" ************************************************************************** +.\" +.TH CURLOPT_SSL_FALSESTART 3 "14 Feb 2015" "libcurl 7.41.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_SSL_FALSESTART \- enable TLS false start +.SH SYNOPSIS +#include <curl/curl.h> + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_FALSESTART, long enable); +.SH DESCRIPTION +Pass a long as parameter set to 1 to enable or 0 to disable. + +This option determines whether libcurl should use false start during the TLS +handshake. False start is a mode where a TLS client will start sending +application data before verifying the server's Finished message, thus saving a +round trip when performing a full handshake. +.SH DEFAULT +0 +.SH PROTOCOLS +All TLS based protocols: HTTPS, FTPS, IMAPS, POP3, SMTPS etc. +.SH EXAMPLE +TODO +.SH AVAILABILITY +Added in 7.42.0. This option is currently only supported by the NSS TLS +backend. +.SH RETURN VALUE +Returns CURLE_OK if false start is supported by the SSL backend, otherwise +returns CURLE_NOT_BUILT_IN. diff --git a/include/curl/curl.h b/include/curl/curl.h index 0a326d3..4fcbd57 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1626,6 +1626,9 @@ typedef enum { /* Set if we should verify the certificate status. */ CINIT(SSL_VERIFYSTATUS, LONG, 232), + /* Set if we should enable TLS false start. */ + CINIT(SSL_FALSESTART, LONG, 233), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/url.c b/lib/url.c index 407910c..b0116d3 100644 --- a/lib/url.c +++ b/lib/url.c @@ -2028,6 +2028,17 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, result = CURLE_NOT_BUILT_IN; #endif break; + case CURLOPT_SSL_FALSESTART: + /* + * Enable TLS false start. + */ + if(!Curl_ssl_false_start()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.falsestart = (0 != va_arg(param, long))?TRUE:FALSE; + break; case CURLOPT_CERTINFO: #ifdef have_curlssl_certinfo data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE; diff --git a/lib/urldata.h b/lib/urldata.h index 50a745f..e9dd9a8 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -379,6 +379,7 @@ struct ssl_config_data { void *fsslctxp; /* parameter for call back */ bool sessionid; /* cache session IDs or not */ bool certinfo; /* gather lots of certificate info */ + bool falsestart; #ifdef USE_TLS_SRP char *username; /* TLS username (for, e.g., SRP) */ diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index cf1df24..e4e7ce6 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -860,4 +860,16 @@ bool Curl_ssl_cert_status_request(void) #endif } +/* + * Check whether the SSL backend supports false start. + */ +bool Curl_ssl_false_start(void) +{ +#ifdef curlssl_false_start + return curlssl_false_start(); +#else + return FALSE; +#endif +} + #endif /* USE_SSL */ diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index e56a8b6..116265e 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -118,6 +118,8 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey, bool Curl_ssl_cert_status_request(void); +bool Curl_ssl_false_start(void); + #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ #else @@ -145,6 +147,7 @@ bool Curl_ssl_cert_status_request(void); #define Curl_ssl_kill_session(x) Curl_nop_stmt #define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) #define Curl_ssl_cert_status_request() FALSE +#define Curl_ssl_false_start() FALSE #endif #endif /* HEADER_CURL_VTLS_H */ -- 2.1.4
From 7bdd586bffe6d9eb0e236b2a6517fabf248346b4 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini <[email protected]> Date: Sat, 14 Feb 2015 16:59:01 +0100 Subject: [PATCH 2/3] nss: add support for TLS False Start --- lib/vtls/nss.c | 27 +++++++++++++++++++++++++++ lib/vtls/nssg.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c index f55c476..f3635c9 100644 --- a/lib/vtls/nss.c +++ b/lib/vtls/nss.c @@ -733,6 +733,13 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg) #endif } +static SECStatus CanFalseStartCallback(PRFileDesc *fd, void *client_data, + PRBool *canFalseStart) +{ + *canFalseStart = true; + return PR_SUCCESS; +} + static void display_cert_info(struct SessionHandle *data, CERTCertificate *cert) { @@ -1653,6 +1660,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) } #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 + #ifdef USE_NGHTTP2 if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { #ifdef SSL_ENABLE_NPN @@ -1950,4 +1969,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 */ diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h index 38e7545..d0e7412 100644 --- a/lib/vtls/nssg.h +++ b/lib/vtls/nssg.h @@ -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 */ -- 2.1.4
From fe8c9530e2d4b07d9db0468b6a3bdbb08d8b9a26 Mon Sep 17 00:00:00 2001 From: Alessandro Ghedini <[email protected]> Date: Sat, 14 Feb 2015 18:17:04 +0100 Subject: [PATCH 3/3] curl: add --false-start option --- docs/curl.1 | 9 +++++++++ src/tool_cfgable.h | 2 ++ src/tool_getparam.c | 5 +++++ src/tool_help.c | 1 + src/tool_operate.c | 3 +++ 5 files changed, 20 insertions(+) diff --git a/docs/curl.1 b/docs/curl.1 index 03944ca..b76f5c1 100644 --- a/docs/curl.1 +++ b/docs/curl.1 @@ -562,6 +562,15 @@ or no response at all is received, the verification fails. This is currently only implemented in the GnuTLS and NSS backends. (Added in 7.41.0) +.IP "--false-start" + +(SSL) Tells curl to use false start during the TLS handshake. False start is a +mode where a TLS client will start sending application data before verifying +the server's Finished message, thus saving a round trip when performing a full +handshake. + +This is currently only implemented in the NSS backend. +(Added in 7.42.0) .IP "-f, --fail" (HTTP) Fail silently (no output at all) on server errors. This is mostly done to better enable scripts etc to better deal with failed attempts. In normal diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 4008cd0..e851130 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -207,6 +207,8 @@ struct OperationConfig { bool noalpn; /* enable/disable TLS ALPN extension */ char *unix_socket_path; /* path to Unix domain socket */ + bool falsestart; + struct GlobalConfig *global; struct OperationConfig *prev; struct OperationConfig *next; /* Always last in the struct */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 5b60c9c..54e7613 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -218,6 +218,7 @@ static const struct LongShort aliases[]= { {"Eo", "login-options", TRUE}, {"Ep", "pinnedpubkey", TRUE}, {"Eq", "cert-status", FALSE}, + {"Er", "false-start", FALSE}, {"f", "fail", FALSE}, {"F", "form", TRUE}, {"Fs", "form-string", TRUE}, @@ -1368,6 +1369,10 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ config->verifystatus = TRUE; break; + case 'r': /* --false-start */ + config->falsestart = TRUE; + break; + default: /* certificate file */ { char *certname, *passphrase; diff --git a/src/tool_help.c b/src/tool_help.c index 4616211..69778b9 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -83,6 +83,7 @@ static const char *const helptext[] = { " --environment Write results to environment variables (RISC OS)", #endif " -f, --fail Fail silently (no output at all) on HTTP errors (H)", + " --false-start Enable TLS False Start.", " -F, --form CONTENT Specify HTTP multipart POST data (H)", " --form-string STRING Specify HTTP multipart POST data (H)", " --ftp-account DATA Account data string (F)", diff --git a/src/tool_operate.c b/src/tool_operate.c index 35a0dd3..dd0293a 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1041,6 +1041,9 @@ static CURLcode operate_do(struct GlobalConfig *global, if(config->verifystatus) my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L); + + if(config->falsestart) + my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L); } if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) { -- 2.1.4
signature.asc
Description: Digital signature
------------------------------------------------------------------- List admin: http://cool.haxx.se/list/listinfo/curl-library Etiquette: http://curl.haxx.se/mail/etiquette.html
