summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/vtls/cyassl.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/cyassl.c')
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c203
1 files changed, 166 insertions, 37 deletions
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 3ded7f1..7994b3e 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, 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.
+ * are also available at https://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
@@ -33,7 +33,7 @@
#define WOLFSSL_OPTIONS_IGNORE_SYS
/* CyaSSL's version.h, which should contain only the version, should come
before all other CyaSSL includes and be immediately followed by build config
-aka options.h. http://curl.haxx.se/mail/lib-2015-04/0069.html */
+aka options.h. https://curl.haxx.se/mail/lib-2015-04/0069.html */
#include <cyassl/version.h>
#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008)
#if defined(CYASSL_API) || defined(WOLFSSL_API)
@@ -51,7 +51,6 @@ and that's a problem since options.h hasn't been included yet. */
#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
-#include "cyassl.h"
#include "vtls.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
@@ -69,6 +68,8 @@ and that's a problem since options.h hasn't been included yet. */
#include <cyassl/ctaocrypt/random.h>
#include <cyassl/ctaocrypt/sha256.h>
+#include "cyassl.h"
+
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
@@ -77,6 +78,38 @@ 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
+
+/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
+ supported curve extension in options.h. Note ECC is enabled separately. */
+#ifndef HAVE_SUPPORTED_CURVES
+#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
+ defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
+#define HAVE_SUPPORTED_CURVES
+#endif
+#endif
+
static Curl_recv cyassl_recv;
static Curl_send cyassl_send;
@@ -101,10 +134,9 @@ cyassl_connect_step1(struct connectdata *conn,
int sockindex)
{
char error_buffer[CYASSL_MAX_ERROR_SZ];
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct ssl_connect_data* conssl = &conn->ssl[sockindex];
SSL_METHOD* req_method = NULL;
- void* ssl_sessionid = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
#ifdef HAVE_SNI
bool sni = FALSE;
@@ -143,8 +175,13 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
case CURL_SSLVERSION_SSLv3:
+#ifdef WOLFSSL_ALLOW_SSLV3
req_method = SSLv3_client_method();
use_sni(FALSE);
+#else
+ failf(data, "No support for SSLv3");
+ return CURLE_NOT_BUILT_IN;
+#endif
break;
case CURL_SSLVERSION_SSLv2:
failf(data, "CyaSSL does not support SSLv2");
@@ -273,6 +310,16 @@ cyassl_connect_step1(struct connectdata *conn,
}
#endif
+#ifdef HAVE_SUPPORTED_CURVES
+ /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically:
+ https://github.com/wolfSSL/wolfssl/issues/366
+ The supported curves below are those also supported by OpenSSL 1.0.2 and
+ in the same order. */
+ CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x17); /* secp256r1 */
+ CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19); /* secp521r1 */
+ CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18); /* secp384r1 */
+#endif
+
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
CURLcode result = CURLE_OK;
@@ -302,16 +349,51 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
- /* 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! */
- if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
- failf(data, "SSL: SSL_set_session failed: %s",
- ERR_error_string(SSL_get_error(conssl->handle, 0), error_buffer));
+#ifdef HAVE_ALPN
+ if(conn->bits.tls_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;
}
- /* Informational message */
- infof (data, "SSL re-using session ID\n");
+ }
+#endif /* HAVE_ALPN */
+
+ /* Check if there's a cached ID we can/should use here! */
+ if(conn->ssl_config.sessionid) {
+ void *ssl_sessionid = NULL;
+
+ Curl_ssl_sessionid_lock(conn);
+ if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+ /* we got a session id, use it! */
+ if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
+ Curl_ssl_sessionid_unlock(conn);
+ failf(data, "SSL: SSL_set_session failed: %s",
+ ERR_error_string(SSL_get_error(conssl->handle, 0),
+ error_buffer));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* Informational message */
+ infof (data, "SSL re-using session ID\n");
+ }
+ Curl_ssl_sessionid_unlock(conn);
}
/* pass the raw socket into the SSL layer */
@@ -330,7 +412,7 @@ cyassl_connect_step2(struct connectdata *conn,
int sockindex)
{
int ret = -1;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct ssl_connect_data* conssl = &conn->ssl[sockindex];
conn->recv[sockindex] = cyassl_recv;
@@ -406,6 +488,7 @@ cyassl_connect_step2(struct connectdata *conn,
}
if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+#ifdef KEEP_PEER_CERT
X509 *x509;
const char *x509_der;
int x509_der_len;
@@ -434,14 +517,54 @@ cyassl_connect_step2(struct connectdata *conn,
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
}
- result = Curl_pin_peer_pubkey(data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+ result = Curl_pin_peer_pubkey(data,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY],
(const unsigned char *)pubkey->header,
(size_t)(pubkey->end - pubkey->header));
if(result) {
failf(data, "SSL: public key does not match pinned public key!");
return result;
}
+#else
+ failf(data, "Library lacks pinning support built-in");
+ return CURLE_NOT_BUILT_IN;
+#endif
+ }
+
+#ifdef HAVE_ALPN
+ if(conn->bits.tls_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");
@@ -455,32 +578,38 @@ cyassl_connect_step3(struct connectdata *conn,
int sockindex)
{
CURLcode result = CURLE_OK;
- void *old_ssl_sessionid=NULL;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- bool incache;
- SSL_SESSION *our_ssl_sessionid;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- our_ssl_sessionid = SSL_get_session(connssl->handle);
+ if(conn->ssl_config.sessionid) {
+ bool incache;
+ SSL_SESSION *our_ssl_sessionid;
+ void *old_ssl_sessionid = NULL;
+
+ our_ssl_sessionid = SSL_get_session(connssl->handle);
- incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
- if(incache) {
- if(old_ssl_sessionid != our_ssl_sessionid) {
- infof(data, "old SSL session ID is stale, removing\n");
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
- incache = FALSE;
+ Curl_ssl_sessionid_lock(conn);
+ incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+ if(incache) {
+ if(old_ssl_sessionid != our_ssl_sessionid) {
+ infof(data, "old SSL session ID is stale, removing\n");
+ Curl_ssl_delsessionid(conn, old_ssl_sessionid);
+ incache = FALSE;
+ }
}
- }
- if(!incache) {
- result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
- 0 /* unknown size */);
- if(result) {
- failf(data, "failed to store ssl session");
- return result;
+ if(!incache) {
+ result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
+ 0 /* unknown size */);
+ if(result) {
+ Curl_ssl_sessionid_unlock(conn);
+ failf(data, "failed to store ssl session");
+ return result;
+ }
}
+ Curl_ssl_sessionid_unlock(conn);
}
connssl->connecting_state = ssl_connect_done;
@@ -625,7 +754,7 @@ cyassl_connect_common(struct connectdata *conn,
bool *done)
{
CURLcode result;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
long timeout_ms;
@@ -756,7 +885,7 @@ Curl_cyassl_connect(struct connectdata *conn,
return CURLE_OK;
}
-int Curl_cyassl_random(struct SessionHandle *data,
+int Curl_cyassl_random(struct Curl_easy *data,
unsigned char *entropy,
size_t length)
{
@@ -779,7 +908,7 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
Sha256 SHA256pw;
(void)unused;
InitSha256(&SHA256pw);
- Sha256Update(&SHA256pw, tmp, tmplen);
+ Sha256Update(&SHA256pw, tmp, (word32)tmplen);
Sha256Final(&SHA256pw, sha256sum);
}