wolfssl: Add ALPN support

This commit is contained in:
Jay Satiro 2016-03-28 18:18:09 -04:00
parent 67a762928e
commit a43b22e05b
4 changed files with 107 additions and 7 deletions

View File

@ -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)

View File

@ -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
------------

View File

@ -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");

View File

@ -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
}