summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--docs/HTTP2.md4
-rw-r--r--lib/vtls/cyassl.c104
-rw-r--r--projects/wolfssl_options.h3
4 files changed, 107 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac
index b208d4d11..b3ad5816f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2206,7 +2206,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
dnl Recent WolfSSL versions build without SSLv3 by default
dnl WolfSSL needs configure --enable-opensslextra to have *get_peer*
AC_CHECK_FUNCS(wolfSSLv3_client_method \
- wolfSSL_get_peer_certificate)
+ wolfSSL_get_peer_certificate \
+ wolfSSL_UseALPN)
else
dnl Cyassl needs configure --enable-opensslextra to have *get_peer*
AC_CHECK_FUNCS(CyaSSL_get_peer_certificate)
diff --git a/docs/HTTP2.md b/docs/HTTP2.md
index 6f7ece431..331bcb0ae 100644
--- a/docs/HTTP2.md
+++ b/docs/HTTP2.md
@@ -7,7 +7,8 @@ HTTP/2 with curl
Build prerequisites
-------------------
- nghttp2
- - OpenSSL, NSS, GnutTLS, PolarSSL or SChannel with a new enough version
+ - OpenSSL, NSS, GnutTLS, PolarSSL, wolfSSL or SChannel with a new enough
+ version.
[nghttp2](https://nghttp2.org/)
-------------------------------
@@ -59,6 +60,7 @@ provide the necessary TLS features. Right now we support:
- GnuTLS: ALPN
- PolarSSL: ALPN
- SChannel: ALPN
+ - wolfSSL: ALPN
Multiplexing
------------
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index f6b57af68..7fa853678 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -77,6 +77,41 @@ and that's a problem since options.h hasn't been included yet. */
#define CYASSL_MAX_ERROR_SZ 80
#endif
+/* To determine what functions are available we rely on one or both of:
+ - the user's options.h generated by CyaSSL/wolfSSL
+ - the symbols detected by curl's configure
+ Since they are markedly different from one another, and one or the other may
+ not be available, we do some checking below to bring things in sync. */
+
+/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
+#ifndef HAVE_ALPN
+#ifdef HAVE_WOLFSSL_USEALPN
+#define HAVE_ALPN
+#endif
+#endif
+
+/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
+ options.h, but is only seen in >= 3.6.6 since that's when they started
+ disabling SSLv3 by default. */
+#ifndef WOLFSSL_ALLOW_SSLV3
+#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
+ defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
+#define WOLFSSL_ALLOW_SSLV3
+#endif
+#endif
+
+/* KEEP_PEER_CERT is a product of the presence of build time symbol
+ OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
+ in wolfSSL's settings.h, and the latter two are build time symbols in
+ options.h. */
+#ifndef KEEP_PEER_CERT
+#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
+ defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
+ (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
+#define KEEP_PEER_CERT
+#endif
+#endif
+
static Curl_recv cyassl_recv;
static Curl_send cyassl_send;
@@ -143,9 +178,7 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_SSLv3:
- /* before WolfSSL SSLv3 was enabled by default, and starting in WolfSSL
- we check for its presence since it is built without it by default */
-#if !defined(WOLFSSL_VERSION) || defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
+#ifdef WOLFSSL_ALLOW_SSLV3
req_method = SSLv3_client_method();
use_sni(FALSE);
#else
@@ -309,6 +342,33 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
+#ifdef HAVE_ALPN
+ if(data->set.ssl_enable_alpn) {
+ char protocols[128];
+ *protocols = '\0';
+
+ /* wolfSSL's ALPN protocol name list format is a comma separated string of
+ protocols in descending order of preference, eg: "h2,http/1.1" */
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
+ strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ",");
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ if(wolfSSL_UseALPN(conssl->handle, protocols,
+ (unsigned)strlen(protocols),
+ WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
+ failf(data, "SSL: failed setting ALPN protocols");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+#endif /* HAVE_ALPN */
+
/* Check if there's a cached ID we can/should use here! */
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
/* we got a session id, use it! */
@@ -413,8 +473,7 @@ cyassl_connect_step2(struct connectdata *conn,
}
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
-#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
- defined(HAVE_CYASSL_GET_PEER_CERTIFICATE)
+#ifdef KEEP_PEER_CERT
X509 *x509;
const char *x509_der;
int x509_der_len;
@@ -457,6 +516,41 @@ cyassl_connect_step2(struct connectdata *conn,
#endif
}
+#ifdef HAVE_ALPN
+ if(data->set.ssl_enable_alpn) {
+ int rc;
+ char *protocol = NULL;
+ unsigned short protocol_len = 0;
+
+ rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len);
+
+ if(rc == SSL_SUCCESS) {
+ infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
+ protocol);
+
+ if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+#ifdef USE_NGHTTP2
+ else if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
+ !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
+ NGHTTP2_PROTO_VERSION_ID_LEN))
+ conn->negnpn = CURL_HTTP_VERSION_2;
+#endif
+ else
+ infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
+ protocol);
+ }
+ else if(rc == SSL_ALPN_NOT_FOUND)
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ else {
+ failf(data, "ALPN, failure getting protocol, error %d", rc);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+#endif /* HAVE_ALPN */
+
conssl->connecting_state = ssl_connect_3;
infof(data, "SSL connected\n");
diff --git a/projects/wolfssl_options.h b/projects/wolfssl_options.h
index 61cc22593..40c34e5d7 100644
--- a/projects/wolfssl_options.h
+++ b/projects/wolfssl_options.h
@@ -19,6 +19,7 @@ These configure flags were used in MinGW to generate the options in this file:
--enable-sessioncerts
--enable-certgen
--enable-testcert
+--enable-alpn
C_EXTRA_FLAGS="-DFP_MAX_BITS=16384 -DTFM_TIMING_RESISTANT"
Two generated options HAVE_THREAD_LS and _POSIX_THREADS were removed since they
@@ -129,6 +130,8 @@ extern "C" {
#undef USE_FAST_MATH
#define USE_FAST_MATH
+#undef HAVE_ALPN
+#define HAVE_ALPN
#ifdef __cplusplus
}