Commit a43b22e0 authored by Jay Satiro's avatar Jay Satiro
Browse files

wolfssl: Add ALPN support

parent 67a76292
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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)
+3 −1
Original line number Diff line number Diff line
@@ -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
------------
+99 −5
Original line number Diff line number Diff line
@@ -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");

+3 −0
Original line number Diff line number Diff line
@@ -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
}