summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/vtls
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls')
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c866
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.h (renamed from Utilities/cmcurl/lib/vtls/polarssl.h)16
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.c102
-rw-r--r--Utilities/cmcurl/lib/vtls/gskit.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c12
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c23
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.h2
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c (renamed from Utilities/cmcurl/lib/vtls/polarssl_threadlock.c)38
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h (renamed from Utilities/cmcurl/lib/vtls/polarssl_threadlock.h)28
-rw-r--r--Utilities/cmcurl/lib/vtls/mesalink.c71
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c51
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c451
-rw-r--r--Utilities/cmcurl/lib/vtls/polarssl.c931
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c22
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel_verify.c177
-rw-r--r--Utilities/cmcurl/lib/vtls/sectransp.c37
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.c76
-rw-r--r--Utilities/cmcurl/lib/vtls/vtls.h9
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.c (renamed from Utilities/cmcurl/lib/vtls/cyassl.c)231
-rw-r--r--Utilities/cmcurl/lib/vtls/wolfssl.h (renamed from Utilities/cmcurl/lib/vtls/cyassl.h)14
20 files changed, 1676 insertions, 1483 deletions
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c
new file mode 100644
index 0000000..67f9458
--- /dev/null
+++ b/Utilities/cmcurl/lib/vtls/bearssl.c
@@ -0,0 +1,866 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Michael Forney, <mforney@mforney.org>
+ *
+ * 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 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
+ * 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.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#ifdef USE_BEARSSL
+
+#include <bearssl.h>
+
+#include "bearssl.h"
+#include "urldata.h"
+#include "sendf.h"
+#include "inet_pton.h"
+#include "vtls.h"
+#include "connect.h"
+#include "select.h"
+#include "multiif.h"
+#include "curl_printf.h"
+#include "curl_memory.h"
+
+struct x509_context {
+ const br_x509_class *vtable;
+ br_x509_minimal_context minimal;
+ bool verifyhost;
+ bool verifypeer;
+};
+
+struct ssl_backend_data {
+ br_ssl_client_context ctx;
+ struct x509_context x509;
+ unsigned char buf[BR_SSL_BUFSIZE_BIDI];
+ br_x509_trust_anchor *anchors;
+ size_t anchors_len;
+ const char *protocols[2];
+ /* SSL client context is active */
+ bool active;
+ /* size of pending write, yet to be flushed */
+ size_t pending_write;
+};
+
+#define BACKEND connssl->backend
+
+struct cafile_parser {
+ CURLcode err;
+ bool in_cert;
+ br_x509_decoder_context xc;
+ /* array of trust anchors loaded from CAfile */
+ br_x509_trust_anchor *anchors;
+ size_t anchors_len;
+ /* buffer for DN data */
+ unsigned char dn[1024];
+ size_t dn_len;
+};
+
+static void append_dn(void *ctx, const void *buf, size_t len)
+{
+ struct cafile_parser *ca = ctx;
+
+ if(ca->err != CURLE_OK || !ca->in_cert)
+ return;
+ if(sizeof(ca->dn) - ca->dn_len < len) {
+ ca->err = CURLE_FAILED_INIT;
+ return;
+ }
+ memcpy(ca->dn + ca->dn_len, buf, len);
+ ca->dn_len += len;
+}
+
+static void x509_push(void *ctx, const void *buf, size_t len)
+{
+ struct cafile_parser *ca = ctx;
+
+ if(ca->in_cert)
+ br_x509_decoder_push(&ca->xc, buf, len);
+}
+
+static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
+ size_t *anchors_len)
+{
+ struct cafile_parser ca;
+ br_pem_decoder_context pc;
+ br_x509_trust_anchor *ta;
+ size_t ta_size;
+ br_x509_trust_anchor *new_anchors;
+ size_t new_anchors_len;
+ br_x509_pkey *pkey;
+ FILE *fp;
+ unsigned char buf[BUFSIZ], *p;
+ const char *name;
+ size_t n, i, pushed;
+
+ fp = fopen(path, "rb");
+ if(!fp)
+ return CURLE_SSL_CACERT_BADFILE;
+
+ ca.err = CURLE_OK;
+ ca.in_cert = FALSE;
+ ca.anchors = NULL;
+ ca.anchors_len = 0;
+ br_pem_decoder_init(&pc);
+ br_pem_decoder_setdest(&pc, x509_push, &ca);
+ for(;;) {
+ n = fread(buf, 1, sizeof(buf), fp);
+ if(n == 0)
+ break;
+ p = buf;
+ while(n) {
+ pushed = br_pem_decoder_push(&pc, p, n);
+ if(ca.err)
+ goto fail;
+ p += pushed;
+ n -= pushed;
+
+ switch(br_pem_decoder_event(&pc)) {
+ case 0:
+ break;
+ case BR_PEM_BEGIN_OBJ:
+ name = br_pem_decoder_name(&pc);
+ if(strcmp(name, "CERTIFICATE") && strcmp(name, "X509 CERTIFICATE"))
+ break;
+ br_x509_decoder_init(&ca.xc, append_dn, &ca);
+ if(ca.anchors_len == SIZE_MAX / sizeof(ca.anchors[0])) {
+ ca.err = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ new_anchors_len = ca.anchors_len + 1;
+ new_anchors = realloc(ca.anchors,
+ new_anchors_len * sizeof(ca.anchors[0]));
+ if(!new_anchors) {
+ ca.err = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ ca.anchors = new_anchors;
+ ca.anchors_len = new_anchors_len;
+ ca.in_cert = TRUE;
+ ca.dn_len = 0;
+ ta = &ca.anchors[ca.anchors_len - 1];
+ ta->dn.data = NULL;
+ break;
+ case BR_PEM_END_OBJ:
+ if(!ca.in_cert)
+ break;
+ ca.in_cert = FALSE;
+ if(br_x509_decoder_last_error(&ca.xc)) {
+ ca.err = CURLE_SSL_CACERT_BADFILE;
+ goto fail;
+ }
+ ta->flags = 0;
+ if(br_x509_decoder_isCA(&ca.xc))
+ ta->flags |= BR_X509_TA_CA;
+ pkey = br_x509_decoder_get_pkey(&ca.xc);
+ if(!pkey) {
+ ca.err = CURLE_SSL_CACERT_BADFILE;
+ goto fail;
+ }
+ ta->pkey = *pkey;
+
+ /* calculate space needed for trust anchor data */
+ ta_size = ca.dn_len;
+ switch(pkey->key_type) {
+ case BR_KEYTYPE_RSA:
+ ta_size += pkey->key.rsa.nlen + pkey->key.rsa.elen;
+ break;
+ case BR_KEYTYPE_EC:
+ ta_size += pkey->key.ec.qlen;
+ break;
+ default:
+ ca.err = CURLE_FAILED_INIT;
+ goto fail;
+ }
+
+ /* fill in trust anchor DN and public key data */
+ ta->dn.data = malloc(ta_size);
+ if(!ta->dn.data) {
+ ca.err = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ memcpy(ta->dn.data, ca.dn, ca.dn_len);
+ ta->dn.len = ca.dn_len;
+ switch(pkey->key_type) {
+ case BR_KEYTYPE_RSA:
+ ta->pkey.key.rsa.n = ta->dn.data + ta->dn.len;
+ memcpy(ta->pkey.key.rsa.n, pkey->key.rsa.n, pkey->key.rsa.nlen);
+ ta->pkey.key.rsa.e = ta->pkey.key.rsa.n + ta->pkey.key.rsa.nlen;
+ memcpy(ta->pkey.key.rsa.e, pkey->key.rsa.e, pkey->key.rsa.elen);
+ break;
+ case BR_KEYTYPE_EC:
+ ta->pkey.key.ec.q = ta->dn.data + ta->dn.len;
+ memcpy(ta->pkey.key.ec.q, pkey->key.ec.q, pkey->key.ec.qlen);
+ break;
+ }
+ break;
+ default:
+ ca.err = CURLE_SSL_CACERT_BADFILE;
+ goto fail;
+ }
+ }
+ }
+ if(ferror(fp))
+ ca.err = CURLE_READ_ERROR;
+
+fail:
+ fclose(fp);
+ if(ca.err == CURLE_OK) {
+ *anchors = ca.anchors;
+ *anchors_len = ca.anchors_len;
+ }
+ else {
+ for(i = 0; i < ca.anchors_len; ++i)
+ free(ca.anchors[i].dn.data);
+ free(ca.anchors);
+ }
+
+ return ca.err;
+}
+
+static void x509_start_chain(const br_x509_class **ctx,
+ const char *server_name)
+{
+ struct x509_context *x509 = (struct x509_context *)ctx;
+
+ if(!x509->verifyhost)
+ server_name = NULL;
+ x509->minimal.vtable->start_chain(&x509->minimal.vtable, server_name);
+}
+
+static void x509_start_cert(const br_x509_class **ctx, uint32_t length)
+{
+ struct x509_context *x509 = (struct x509_context *)ctx;
+
+ x509->minimal.vtable->start_cert(&x509->minimal.vtable, length);
+}
+
+static void x509_append(const br_x509_class **ctx, const unsigned char *buf,
+ size_t len)
+{
+ struct x509_context *x509 = (struct x509_context *)ctx;
+
+ x509->minimal.vtable->append(&x509->minimal.vtable, buf, len);
+}
+
+static void x509_end_cert(const br_x509_class **ctx)
+{
+ struct x509_context *x509 = (struct x509_context *)ctx;
+
+ x509->minimal.vtable->end_cert(&x509->minimal.vtable);
+}
+
+static unsigned x509_end_chain(const br_x509_class **ctx)
+{
+ struct x509_context *x509 = (struct x509_context *)ctx;
+ unsigned err;
+
+ err = x509->minimal.vtable->end_chain(&x509->minimal.vtable);
+ if(err && !x509->verifypeer) {
+ /* ignore any X.509 errors */
+ err = BR_ERR_OK;
+ }
+
+ return err;
+}
+
+static const br_x509_pkey *x509_get_pkey(const br_x509_class *const *ctx,
+ unsigned *usages)
+{
+ struct x509_context *x509 = (struct x509_context *)ctx;
+
+ return x509->minimal.vtable->get_pkey(&x509->minimal.vtable, usages);
+}
+
+static const br_x509_class x509_vtable = {
+ sizeof(struct x509_context),
+ x509_start_chain,
+ x509_start_cert,
+ x509_append,
+ x509_end_cert,
+ x509_end_chain,
+ x509_get_pkey
+};
+
+static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const char *hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+ conn->host.name;
+ const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+ const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
+ CURLcode ret;
+ unsigned version_min, version_max;
+#ifdef ENABLE_IPV6
+ struct in6_addr addr;
+#else
+ struct in_addr addr;
+#endif
+
+ switch(SSL_CONN_CONFIG(version)) {
+ case CURL_SSLVERSION_SSLv2:
+ failf(data, "BearSSL does not support SSLv2");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_SSLv3:
+ failf(data, "BearSSL does not support SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_TLSv1_0:
+ version_min = BR_TLS10;
+ version_max = BR_TLS10;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ version_min = BR_TLS11;
+ version_max = BR_TLS11;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ version_min = BR_TLS12;
+ version_max = BR_TLS12;
+ break;
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1:
+ version_min = BR_TLS10;
+ version_max = BR_TLS12;
+ break;
+ default:
+ failf(data, "BearSSL: unknown CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(ssl_cafile) {
+ ret = load_cafile(ssl_cafile, &BACKEND->anchors, &BACKEND->anchors_len);
+ if(ret != CURLE_OK) {
+ if(verifypeer) {
+ failf(data, "error setting certificate verify locations:\n"
+ " CAfile: %s\n", ssl_cafile);
+ return ret;
+ }
+ infof(data, "error setting certificate verify locations,"
+ " continuing anyway:\n");
+ }
+ }
+
+ /* initialize SSL context */
+ br_ssl_client_init_full(&BACKEND->ctx, &BACKEND->x509.minimal,
+ BACKEND->anchors, BACKEND->anchors_len);
+ br_ssl_engine_set_versions(&BACKEND->ctx.eng, version_min, version_max);
+ br_ssl_engine_set_buffer(&BACKEND->ctx.eng, BACKEND->buf,
+ sizeof(BACKEND->buf), 1);
+
+ /* initialize X.509 context */
+ BACKEND->x509.vtable = &x509_vtable;
+ BACKEND->x509.verifypeer = verifypeer;
+ BACKEND->x509.verifyhost = verifyhost;
+ br_ssl_engine_set_x509(&BACKEND->ctx.eng, &BACKEND->x509.vtable);
+
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ void *session;
+
+ Curl_ssl_sessionid_lock(conn);
+ if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) {
+ br_ssl_engine_set_session_parameters(&BACKEND->ctx.eng, session);
+ infof(data, "BearSSL: re-using session ID\n");
+ }
+ Curl_ssl_sessionid_unlock(conn);
+ }
+
+ if(conn->bits.tls_enable_alpn) {
+ int cur = 0;
+
+ /* NOTE: when adding more protocols here, increase the size of the
+ * protocols array in `struct ssl_backend_data`.
+ */
+
+#ifdef USE_NGHTTP2
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+ (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ BACKEND->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
+ infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+ }
+#endif
+
+ BACKEND->protocols[cur++] = ALPN_HTTP_1_1;
+ infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+ br_ssl_engine_set_protocol_names(&BACKEND->ctx.eng,
+ BACKEND->protocols, cur);
+ }
+
+ if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
+#ifdef ENABLE_IPV6
+ || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
+#endif
+ ) {
+ if(verifyhost) {
+ failf(data, "BearSSL: "
+ "host verification of IP address is not supported");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ hostname = NULL;
+ }
+
+ if(!br_ssl_client_reset(&BACKEND->ctx, hostname, 0))
+ return CURLE_FAILED_INIT;
+ BACKEND->active = TRUE;
+
+ connssl->connecting_state = ssl_connect_2;
+
+ return CURLE_OK;
+}
+
+static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,
+ unsigned target)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ unsigned state;
+ unsigned char *buf;
+ size_t len;
+ ssize_t ret;
+ int err;
+
+ for(;;) {
+ state = br_ssl_engine_current_state(&BACKEND->ctx.eng);
+ if(state & BR_SSL_CLOSED) {
+ err = br_ssl_engine_last_error(&BACKEND->ctx.eng);
+ switch(err) {
+ case BR_ERR_OK:
+ /* TLS close notify */
+ if(connssl->state != ssl_connection_complete) {
+ failf(data, "SSL: connection closed during handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ return CURLE_OK;
+ case BR_ERR_X509_EXPIRED:
+ failf(data, "SSL: X.509 verification: "
+ "certificate is expired or not yet valid");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ case BR_ERR_X509_BAD_SERVER_NAME:
+ failf(data, "SSL: X.509 verification: "
+ "expected server name was not found in the chain");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ case BR_ERR_X509_NOT_TRUSTED:
+ failf(data, "SSL: X.509 verification: "
+ "chain could not be linked to a trust anchor");
+ return CURLE_PEER_FAILED_VERIFICATION;
+ }
+ /* X.509 errors are documented to have the range 32..63 */
+ if(err >= 32 && err < 64)
+ return CURLE_PEER_FAILED_VERIFICATION;
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ if(state & target)
+ return CURLE_OK;
+ if(state & BR_SSL_SENDREC) {
+ buf = br_ssl_engine_sendrec_buf(&BACKEND->ctx.eng, &len);
+ ret = swrite(sockfd, buf, len);
+ if(ret == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ if(connssl->state != ssl_connection_complete)
+ connssl->connecting_state = ssl_connect_2_writing;
+ return CURLE_AGAIN;
+ }
+ return CURLE_WRITE_ERROR;
+ }
+ br_ssl_engine_sendrec_ack(&BACKEND->ctx.eng, ret);
+ }
+ else if(state & BR_SSL_RECVREC) {
+ buf = br_ssl_engine_recvrec_buf(&BACKEND->ctx.eng, &len);
+ ret = sread(sockfd, buf, len);
+ if(ret == 0) {
+ failf(data, "SSL: EOF without close notify");
+ return CURLE_READ_ERROR;
+ }
+ if(ret == -1) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ if(connssl->state != ssl_connection_complete)
+ connssl->connecting_state = ssl_connect_2_reading;
+ return CURLE_AGAIN;
+ }
+ return CURLE_READ_ERROR;
+ }
+ br_ssl_engine_recvrec_ack(&BACKEND->ctx.eng, ret);
+ }
+ }
+}
+
+static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode ret;
+
+ ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
+ if(ret == CURLE_AGAIN)
+ return CURLE_OK;
+ if(ret == CURLE_OK) {
+ if(br_ssl_engine_current_state(&BACKEND->ctx.eng) == BR_SSL_CLOSED) {
+ failf(data, "SSL: connection closed during handshake");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ connssl->connecting_state = ssl_connect_3;
+ }
+ return ret;
+}
+
+static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ CURLcode ret;
+
+ DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
+
+ if(conn->bits.tls_enable_alpn) {
+ const char *protocol;
+
+ protocol = br_ssl_engine_get_selected_protocol(&BACKEND->ctx.eng);
+ if(protocol) {
+ infof(data, "ALPN, server accepted to use %s\n", protocol);
+
+#ifdef USE_NGHTTP2
+ if(!strcmp(protocol, NGHTTP2_PROTO_VERSION_ID))
+ conn->negnpn = CURL_HTTP_VERSION_2;
+ else
+#endif
+ if(!strcmp(protocol, ALPN_HTTP_1_1))
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ else
+ infof(data, "ALPN, unrecognized protocol %s\n", protocol);
+ Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
+ BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
+ }
+ else
+ infof(data, "ALPN, server did not agree to a protocol\n");
+ }
+
+ if(SSL_SET_OPTION(primary.sessionid)) {
+ bool incache;
+ void *oldsession;
+ br_ssl_session_parameters *session;
+
+ session = malloc(sizeof(*session));
+ if(!session)
+ return CURLE_OUT_OF_MEMORY;
+ br_ssl_engine_get_session_parameters(&BACKEND->ctx.eng, session);
+ Curl_ssl_sessionid_lock(conn);
+ incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex));
+ if(incache)
+ Curl_ssl_delsessionid(conn, oldsession);
+ ret = Curl_ssl_addsessionid(conn, session, 0, sockindex);
+ Curl_ssl_sessionid_unlock(conn);
+ if(ret) {
+ free(session);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+
+ return CURLE_OK;
+}
+
+static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
+ const void *buf, size_t len, CURLcode *err)
+{
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ unsigned char *app;
+ size_t applen;
+
+ for(;;) {
+ *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP);
+ if (*err != CURLE_OK)
+ return -1;
+ app = br_ssl_engine_sendapp_buf(&BACKEND->ctx.eng, &applen);
+ if(!app) {
+ failf(data, "SSL: connection closed during write");
+ *err = CURLE_SEND_ERROR;
+ return -1;
+ }
+ if(BACKEND->pending_write) {
+ applen = BACKEND->pending_write;
+ BACKEND->pending_write = 0;
+ return applen;
+ }
+ if(applen > len)
+ applen = len;
+ memcpy(app, buf, applen);
+ br_ssl_engine_sendapp_ack(&BACKEND->ctx.eng, applen);
+ br_ssl_engine_flush(&BACKEND->ctx.eng, 0);
+ BACKEND->pending_write = applen;
+ }
+}
+
+static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
+ char *buf, size_t len, CURLcode *err)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ unsigned char *app;
+ size_t applen;
+
+ *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP);
+ if(*err != CURLE_OK)
+ return -1;
+ app = br_ssl_engine_recvapp_buf(&BACKEND->ctx.eng, &applen);
+ if(!app)
+ return 0;
+ if(applen > len)
+ applen = len;
+ memcpy(buf, app, applen);
+ br_ssl_engine_recvapp_ack(&BACKEND->ctx.eng, applen);
+
+ return applen;
+}
+
+static CURLcode bearssl_connect_common(struct connectdata *conn,
+ int sockindex,
+ bool nonblocking,
+ bool *done)
+{
+ CURLcode ret;
+ struct Curl_easy *data = conn->data;
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ curl_socket_t sockfd = conn->sock[sockindex];
+ time_t timeout_ms;
+ int what;
+
+ /* check if the connection has already been established */
+ if(ssl_connection_complete == connssl->state) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+
+ if(ssl_connect_1 == connssl->connecting_state) {
+ ret = bearssl_connect_step1(conn, sockindex);
+ if(ret)
+ return ret;
+ }
+
+ while(ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+
+ /* if ssl is expecting something, check if it's available. */
+ if(ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state) {
+
+ curl_socket_t writefd = ssl_connect_2_writing ==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = ssl_connect_2_reading ==
+ connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking?0:timeout_ms);
+ if(what < 0) {
+ /* fatal error */
+ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ else if(0 == what) {
+ if(nonblocking) {
+ *done = FALSE;
+ return CURLE_OK;
+ }
+ else {
+ /* timeout */
+ failf(data, "SSL connection timeout");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ }
+ /* socket is readable or writable */
+ }
+
+ /* Run transaction, and return to the caller if it failed or if this
+ * connection is done nonblocking and this loop would execute again. This
+ * permits the owner of a multi handle to abort a connection attempt
+ * before step2 has completed while ensuring that a client using select()
+ * or epoll() will always have a valid fdset to wait on.
+ */
+ ret = bearssl_connect_step2(conn, sockindex);
+ if(ret || (nonblocking &&
+ (ssl_connect_2 == connssl->connecting_state ||
+ ssl_connect_2_reading == connssl->connecting_state ||
+ ssl_connect_2_writing == connssl->connecting_state)))
+ return ret;
+ }
+
+ if(ssl_connect_3 == connssl->connecting_state) {
+ ret = bearssl_connect_step3(conn, sockindex);
+ if(ret)
+ return ret;
+ }
+
+ if(ssl_connect_done == connssl->connecting_state) {
+ connssl->state = ssl_connection_complete;
+ conn->recv[sockindex] = bearssl_recv;
+ conn->send[sockindex] = bearssl_send;
+ *done = TRUE;
+ }
+ else
+ *done = FALSE;
+
+ /* Reset our connect state machine */
+ connssl->connecting_state = ssl_connect_1;
+
+ return CURLE_OK;
+}
+
+static size_t Curl_bearssl_version(char *buffer, size_t size)
+{
+ return msnprintf(buffer, size, "BearSSL");
+}
+
+static bool Curl_bearssl_data_pending(const struct connectdata *conn,
+ int connindex)
+{
+ const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+
+ return br_ssl_engine_current_state(&BACKEND->ctx.eng) & BR_SSL_RECVAPP;
+}
+
+static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
+ unsigned char *entropy, size_t length)
+{
+ static br_hmac_drbg_context ctx;
+ static bool seeded = FALSE;
+
+ if(!seeded) {
+ br_prng_seeder seeder;
+
+ br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
+ seeder = br_prng_seeder_system(NULL);
+ if(!seeder || !seeder(&ctx.vtable))
+ return CURLE_FAILED_INIT;
+ seeded = TRUE;
+ }
+ br_hmac_drbg_generate(&ctx, entropy, length);
+
+ return CURLE_OK;
+}
+
+static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
+{
+ CURLcode ret;
+ bool done = FALSE;
+
+ ret = bearssl_connect_common(conn, sockindex, FALSE, &done);
+ if(ret)
+ return ret;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn,
+ int sockindex, bool *done)
+{
+ return bearssl_connect_common(conn, sockindex, TRUE, done);
+}
+
+static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl,
+ CURLINFO info UNUSED_PARAM)
+{
+ return &BACKEND->ctx;
+}
+
+static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
+{
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ size_t i;
+
+ if(BACKEND->active) {
+ br_ssl_engine_close(&BACKEND->ctx.eng);
+ (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED);
+ }
+ for(i = 0; i < BACKEND->anchors_len; ++i)
+ free(BACKEND->anchors[i].dn.data);
+ free(BACKEND->anchors);
+}
+
+static void Curl_bearssl_session_free(void *ptr)
+{
+ free(ptr);
+}
+
+static CURLcode Curl_bearssl_md5sum(unsigned char *input,
+ size_t inputlen,
+ unsigned char *md5sum,
+ size_t md5len UNUSED_PARAM)
+{
+ br_md5_context ctx;
+
+ br_md5_init(&ctx);
+ br_md5_update(&ctx, input, inputlen);
+ br_md5_out(&ctx, md5sum);
+ return CURLE_OK;
+}
+
+static CURLcode Curl_bearssl_sha256sum(const unsigned char *input,
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len UNUSED_PARAM)
+{
+ br_sha256_context ctx;
+
+ br_sha256_init(&ctx);
+ br_sha256_update(&ctx, input, inputlen);
+ br_sha256_out(&ctx, sha256sum);
+ return CURLE_OK;
+}
+
+const struct Curl_ssl Curl_ssl_bearssl = {
+ { CURLSSLBACKEND_BEARSSL, "bearssl" },
+
+ 0,
+
+ sizeof(struct ssl_backend_data),
+
+ Curl_none_init,
+ Curl_none_cleanup,
+ Curl_bearssl_version,
+ Curl_none_check_cxn,
+ Curl_none_shutdown,
+ Curl_bearssl_data_pending,
+ Curl_bearssl_random,
+ Curl_none_cert_status_request,
+ Curl_bearssl_connect,
+ Curl_bearssl_connect_nonblocking,
+ Curl_bearssl_get_internals,
+ Curl_bearssl_close,
+ Curl_none_close_all,
+ Curl_bearssl_session_free,
+ Curl_none_set_engine,
+ Curl_none_set_engine_default,
+ Curl_none_engines_list,
+ Curl_none_false_start,
+ Curl_bearssl_md5sum,
+ Curl_bearssl_sha256sum
+};
+
+#endif /* USE_BEARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.h b/Utilities/cmcurl/lib/vtls/bearssl.h
index 23c3636..5f94922 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl.h
+++ b/Utilities/cmcurl/lib/vtls/bearssl.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_POLARSSL_H
-#define HEADER_CURL_POLARSSL_H
+#ifndef HEADER_CURL_BEARSSL_H
+#define HEADER_CURL_BEARSSL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,8 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
+ * Copyright (C) 2019, Michael Forney, <mforney@mforney.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,11 +21,12 @@
* KIND, either express or implied.
*
***************************************************************************/
+
#include "curl_setup.h"
-#ifdef USE_POLARSSL
+#ifdef USE_BEARSSL
-extern const struct Curl_ssl Curl_ssl_polarssl;
+extern const struct Curl_ssl Curl_ssl_bearssl;
-#endif /* USE_POLARSSL */
-#endif /* HEADER_CURL_POLARSSL_H */
+#endif /* USE_BEARSSL */
+#endif /* HEADER_CURL_BEARSSL_H */
diff --git a/Utilities/cmcurl/lib/vtls/gskit.c b/Utilities/cmcurl/lib/vtls/gskit.c
index b93ff5d..32153dd 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.c
+++ b/Utilities/cmcurl/lib/vtls/gskit.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, 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
@@ -26,6 +26,8 @@
#include <gskssl.h>
#include <qsoasync.h>
+#undef HAVE_SOCKETPAIR /* because the native one isn't good enough */
+#include "socketpair.h"
/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
@@ -511,100 +513,6 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
BACKEND->iocport = -1;
}
-/* SSL over SSL
- * Problems:
- * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
- * pipe an SSL stream into another, it is therefore needed to have a pair
- * of such communicating sockets and handle the pipelining explicitly.
- * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
- * be used to produce the pipeline.
- * The solution is to simulate socketpair() for AF_INET with low-level API
- * listen(), bind() and connect().
- */
-
-static int
-inetsocketpair(int sv[2])
-{
- int lfd; /* Listening socket. */
- int sfd; /* Server socket. */
- int cfd; /* Client socket. */
- int len;
- struct sockaddr_in addr1;
- struct sockaddr_in addr2;
-
- /* Create listening socket on a local dynamic port. */
- lfd = socket(AF_INET, SOCK_STREAM, 0);
- if(lfd < 0)
- return -1;
- memset((char *) &addr1, 0, sizeof(addr1));
- addr1.sin_family = AF_INET;
- addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr1.sin_port = 0;
- if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) ||
- listen(lfd, 2) < 0) {
- close(lfd);
- return -1;
- }
-
- /* Get the allocated port. */
- len = sizeof(addr1);
- if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
- close(lfd);
- return -1;
- }
-
- /* Create the client socket. */
- cfd = socket(AF_INET, SOCK_STREAM, 0);
- if(cfd < 0) {
- close(lfd);
- return -1;
- }
-
- /* Request unblocking connection to the listening socket. */
- curlx_nonblock(cfd, TRUE);
- if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 &&
- errno != EINPROGRESS) {
- close(lfd);
- close(cfd);
- return -1;
- }
-
- /* Get the client dynamic port for intrusion check below. */
- len = sizeof(addr2);
- if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
- close(lfd);
- close(cfd);
- return -1;
- }
-
- /* Accept the incoming connection and get the server socket. */
- curlx_nonblock(lfd, TRUE);
- for(;;) {
- len = sizeof(addr1);
- sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
- if(sfd < 0) {
- close(lfd);
- close(cfd);
- return -1;
- }
-
- /* Check for possible intrusion from an external process. */
- if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
- addr1.sin_port == addr2.sin_port)
- break;
-
- /* Intrusion: reject incoming connection. */
- close(sfd);
- }
-
- /* Done, return sockets and succeed. */
- close(lfd);
- curlx_nonblock(cfd, FALSE);
- sv[0] = cfd;
- sv[1] = sfd;
- return 0;
-}
-
static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
int directions)
{
@@ -855,7 +763,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
/* Establish a pipelining socket pair for SSL over SSL. */
if(conn->proxy_ssl[sockindex].use) {
- if(inetsocketpair(sockpair))
+ if(Curl_socketpair(0, 0, 0, sockpair))
return CURLE_SSL_CONNECT_ERROR;
BACKEND->localfd = sockpair[0];
BACKEND->remotefd = sockpair[1];
@@ -1157,7 +1065,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
{
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- long timeout_ms;
+ timediff_t timeout_ms;
CURLcode result = CURLE_OK;
*done = connssl->state == ssl_connection_complete;
diff --git a/Utilities/cmcurl/lib/vtls/gskit.h b/Utilities/cmcurl/lib/vtls/gskit.h
index 466ee4d..b06b5e1 100644
--- a/Utilities/cmcurl/lib/vtls/gskit.h
+++ b/Utilities/cmcurl/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, 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
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 8693cdc..5f740ee 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -288,7 +288,7 @@ static CURLcode handshake(struct connectdata *conn,
curl_socket_t sockfd = conn->sock[sockindex];
for(;;) {
- time_t timeout_ms;
+ timediff_t timeout_ms;
int rc;
/* check allowed time left */
@@ -311,7 +311,7 @@ static CURLcode handshake(struct connectdata *conn,
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:
- timeout_ms?timeout_ms:1000);
+ timeout_ms?(time_t)timeout_ms:1000);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -666,6 +666,10 @@ gtls_connect_step1(struct connectdata *conn,
/* Initialize TLS session as a client */
init_flags = GNUTLS_CLIENT;
+#if defined(GNUTLS_FORCE_CLIENT_CERT)
+ init_flags |= GNUTLS_FORCE_CLIENT_CERT;
+#endif
+
#if defined(GNUTLS_NO_TICKETS)
/* Disable TLS session tickets */
init_flags |= GNUTLS_NO_TICKETS;
@@ -1608,7 +1612,7 @@ static ssize_t gtls_send(struct connectdata *conn,
static void close_one(struct ssl_connect_data *connssl)
{
if(BACKEND->session) {
- gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
+ gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
gnutls_deinit(BACKEND->session);
BACKEND->session = NULL;
}
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 63d1f4c..f057315 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, 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
@@ -55,7 +55,7 @@
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "multiif.h"
-#include "polarssl_threadlock.h"
+#include "mbedtls_threadlock.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -91,12 +91,12 @@ static int entropy_init_initialized = 0;
static void entropy_init_mutex(mbedtls_entropy_context *ctx)
{
/* lock 0 = entropy_init_mutex() */
- Curl_polarsslthreadlock_lock_function(0);
+ Curl_mbedtlsthreadlock_lock_function(0);
if(entropy_init_initialized == 0) {
mbedtls_entropy_init(ctx);
entropy_init_initialized = 1;
}
- Curl_polarsslthreadlock_unlock_function(0);
+ Curl_mbedtlsthreadlock_unlock_function(0);
}
/* end of entropy_init_mutex() */
@@ -105,9 +105,9 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
{
int ret;
/* lock 1 = entropy_func_mutex() */
- Curl_polarsslthreadlock_lock_function(1);
+ Curl_mbedtlsthreadlock_lock_function(1);
ret = mbedtls_entropy_func(data, output, len);
- Curl_polarsslthreadlock_unlock_function(1);
+ Curl_mbedtlsthreadlock_unlock_function(1);
return ret;
}
@@ -588,6 +588,9 @@ mbed_connect_step2(struct connectdata *conn,
else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
+ else if(ret & MBEDTLS_X509_BADCERT_FUTURE)
+ failf(data, "Cert verify failed: BADCERT_FUTURE");
+
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -884,7 +887,7 @@ mbed_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
+ timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -930,7 +933,7 @@ mbed_connect_common(struct connectdata *conn,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking ? 0 : timeout_ms);
+ nonblocking ? 0 : (time_t)timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -1014,12 +1017,12 @@ static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
*/
static int Curl_mbedtls_init(void)
{
- return Curl_polarsslthreadlock_thread_setup();
+ return Curl_mbedtlsthreadlock_thread_setup();
}
static void Curl_mbedtls_cleanup(void)
{
- (void)Curl_polarsslthreadlock_thread_cleanup();
+ (void)Curl_mbedtlsthreadlock_thread_cleanup();
}
static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.h b/Utilities/cmcurl/lib/vtls/mbedtls.h
index 4a93860..0cc64b3 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
diff --git a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
index 27c94b1..4d672f1 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013-2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -22,19 +22,19 @@
***************************************************************************/
#include "curl_setup.h"
-#if (defined(USE_POLARSSL) || defined(USE_MBEDTLS)) && \
- ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
- (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)))
+#if defined(USE_MBEDTLS) && \
+ ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
+ (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)))
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
# include <pthread.h>
-# define POLARSSL_MUTEX_T pthread_mutex_t
+# define MBEDTLS_MUTEX_T pthread_mutex_t
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
# include <process.h>
-# define POLARSSL_MUTEX_T HANDLE
+# define MBEDTLS_MUTEX_T HANDLE
#endif
-#include "polarssl_threadlock.h"
+#include "mbedtls_threadlock.h"
#include "curl_printf.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -43,14 +43,14 @@
/* number of thread locks */
#define NUMT 2
-/* This array will store all of the mutexes available to PolarSSL. */
-static POLARSSL_MUTEX_T *mutex_buf = NULL;
+/* This array will store all of the mutexes available to Mbedtls. */
+static MBEDTLS_MUTEX_T *mutex_buf = NULL;
-int Curl_polarsslthreadlock_thread_setup(void)
+int Curl_mbedtlsthreadlock_thread_setup(void)
{
int i;
- mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1);
+ mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1);
if(!mutex_buf)
return 0; /* error, no number of threads defined */
@@ -70,7 +70,7 @@ int Curl_polarsslthreadlock_thread_setup(void)
return 1; /* OK */
}
-int Curl_polarsslthreadlock_thread_cleanup(void)
+int Curl_mbedtlsthreadlock_thread_cleanup(void)
{
int i;
@@ -95,7 +95,7 @@ int Curl_polarsslthreadlock_thread_cleanup(void)
return 1; /* OK */
}
-int Curl_polarsslthreadlock_lock_function(int n)
+int Curl_mbedtlsthreadlock_lock_function(int n)
{
if(n < NUMT) {
int ret;
@@ -103,14 +103,14 @@ int Curl_polarsslthreadlock_lock_function(int n)
ret = pthread_mutex_lock(&mutex_buf[n]);
if(ret) {
DEBUGF(fprintf(stderr,
- "Error: polarsslthreadlock_lock_function failed\n"));
+ "Error: mbedtlsthreadlock_lock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
}
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
if(ret) {
DEBUGF(fprintf(stderr,
- "Error: polarsslthreadlock_lock_function failed\n"));
+ "Error: mbedtlsthreadlock_lock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
}
#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
@@ -118,7 +118,7 @@ int Curl_polarsslthreadlock_lock_function(int n)
return 1; /* OK */
}
-int Curl_polarsslthreadlock_unlock_function(int n)
+int Curl_mbedtlsthreadlock_unlock_function(int n)
{
if(n < NUMT) {
int ret;
@@ -126,14 +126,14 @@ int Curl_polarsslthreadlock_unlock_function(int n)
ret = pthread_mutex_unlock(&mutex_buf[n]);
if(ret) {
DEBUGF(fprintf(stderr,
- "Error: polarsslthreadlock_unlock_function failed\n"));
+ "Error: mbedtlsthreadlock_unlock_function failed\n"));
return 0; /* pthread_mutex_unlock failed */
}
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
ret = ReleaseMutex(mutex_buf[n]);
if(!ret) {
DEBUGF(fprintf(stderr,
- "Error: polarsslthreadlock_unlock_function failed\n"));
+ "Error: mbedtlsthreadlock_unlock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
}
#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
@@ -141,4 +141,4 @@ int Curl_polarsslthreadlock_unlock_function(int n)
return 1; /* OK */
}
-#endif /* USE_POLARSSL || USE_MBEDTLS */
+#endif /* USE_MBEDTLS */
diff --git a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.h b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
index 1226475..96a787d 100644
--- a/Utilities/cmcurl/lib/vtls/polarssl_threadlock.h
+++ b/Utilities/cmcurl/lib/vtls/mbedtls_threadlock.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H
-#define HEADER_CURL_POLARSSL_THREADLOCK_H
+#ifndef HEADER_CURL_MBEDTLS_THREADLOCK_H
+#define HEADER_CURL_MBEDTLS_THREADLOCK_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013-2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
@@ -24,25 +24,25 @@
***************************************************************************/
#include "curl_setup.h"
-#if (defined USE_POLARSSL) || (defined USE_MBEDTLS)
+#ifdef USE_MBEDTLS
#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
(defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))
-int Curl_polarsslthreadlock_thread_setup(void);
-int Curl_polarsslthreadlock_thread_cleanup(void);
-int Curl_polarsslthreadlock_lock_function(int n);
-int Curl_polarsslthreadlock_unlock_function(int n);
+int Curl_mbedtlsthreadlock_thread_setup(void);
+int Curl_mbedtlsthreadlock_thread_cleanup(void);
+int Curl_mbedtlsthreadlock_lock_function(int n);
+int Curl_mbedtlsthreadlock_unlock_function(int n);
#else
-#define Curl_polarsslthreadlock_thread_setup() 1
-#define Curl_polarsslthreadlock_thread_cleanup() 1
-#define Curl_polarsslthreadlock_lock_function(x) 1
-#define Curl_polarsslthreadlock_unlock_function(x) 1
+#define Curl_mbedtlsthreadlock_thread_setup() 1
+#define Curl_mbedtlsthreadlock_thread_cleanup() 1
+#define Curl_mbedtlsthreadlock_lock_function(x) 1
+#define Curl_mbedtlsthreadlock_unlock_function(x) 1
#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
-#endif /* USE_POLARSSL */
+#endif /* USE_MBEDTLS */
-#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */
+#endif /* HEADER_CURL_MBEDTLS_THREADLOCK_H */
diff --git a/Utilities/cmcurl/lib/vtls/mesalink.c b/Utilities/cmcurl/lib/vtls/mesalink.c
index 718c282..cab1e39 100644
--- a/Utilities/cmcurl/lib/vtls/mesalink.c
+++ b/Utilities/cmcurl/lib/vtls/mesalink.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, 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
@@ -73,6 +73,17 @@ struct ssl_backend_data
static Curl_recv mesalink_recv;
static Curl_send mesalink_send;
+static int do_file_type(const char *type)
+{
+ if(!type || !type[0])
+ return SSL_FILETYPE_PEM;
+ if(strcasecompare(type, "PEM"))
+ return SSL_FILETYPE_PEM;
+ if(strcasecompare(type, "DER"))
+ return SSL_FILETYPE_ASN1;
+ return -1;
+}
+
/*
* This function loads all the client/CA certificates and CRLs. Setup the TLS
* layer and do all necessary magic.
@@ -83,9 +94,6 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
char *ciphers;
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char *const ssl_cafile = SSL_CONN_CONFIG(CAfile);
- const char *const ssl_capath = SSL_CONN_CONFIG(CApath);
struct in_addr addr4;
#ifdef ENABLE_IPV6
struct in6_addr addr6;
@@ -142,21 +150,25 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
}
SSL_CTX_set_verify(
- BACKEND->ctx, verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
+ BACKEND->ctx, SSL_CONN_CONFIG(verifypeer) ?
+ SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
- if(ssl_cafile || ssl_capath) {
- if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) {
- if(verifypeer) {
+ if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath)) {
+ if(!SSL_CTX_load_verify_locations(BACKEND->ctx, SSL_CONN_CONFIG(CAfile),
+ SSL_CONN_CONFIG(CApath))) {
+ if(SSL_CONN_CONFIG(verifypeer)) {
failf(data,
"error setting certificate verify locations:\n"
" CAfile: %s\n CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
+ SSL_CONN_CONFIG(CAfile) ?
+ SSL_CONN_CONFIG(CAfile) : "none",
+ SSL_CONN_CONFIG(CApath) ?
+ SSL_CONN_CONFIG(CApath) : "none");
return CURLE_SSL_CACERT_BADFILE;
}
infof(data,
- "error setting certificate verify locations,"
- " continuing anyway:\n");
+ "error setting certificate verify locations,"
+ " continuing anyway:\n");
}
else {
infof(data, "successfully set certificate verify locations:\n");
@@ -164,8 +176,32 @@ mesalink_connect_step1(struct connectdata *conn, int sockindex)
infof(data,
" CAfile: %s\n"
" CApath: %s\n",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
+ SSL_CONN_CONFIG(CAfile)?
+ SSL_CONN_CONFIG(CAfile): "none",
+ SSL_CONN_CONFIG(CApath)?
+ SSL_CONN_CONFIG(CApath): "none");
+ }
+
+ if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+ int file_type = do_file_type(SSL_SET_OPTION(cert_type));
+
+ if(SSL_CTX_use_certificate_chain_file(BACKEND->ctx, SSL_SET_OPTION(cert),
+ file_type) != 1) {
+ failf(data, "unable to use client certificate (no key or wrong pass"
+ " phrase?)");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ file_type = do_file_type(SSL_SET_OPTION(key_type));
+ if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key),
+ file_type) != 1) {
+ failf(data, "unable to set private key");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ infof(data,
+ "client cert: %s\n",
+ SSL_CONN_CONFIG(clientcert)?
+ SSL_CONN_CONFIG(clientcert): "none");
}
ciphers = SSL_CONN_CONFIG(cipher_list);
@@ -265,7 +301,6 @@ mesalink_connect_step2(struct connectdata *conn, int sockindex)
ret = SSL_connect(BACKEND->handle);
if(ret != SSL_SUCCESS) {
- char error_buffer[MESALINK_MAX_ERROR_SZ];
int detail = SSL_get_error(BACKEND->handle, ret);
if(SSL_ERROR_WANT_CONNECT == detail || SSL_ERROR_WANT_READ == detail) {
@@ -273,6 +308,7 @@ mesalink_connect_step2(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
else {
+ char error_buffer[MESALINK_MAX_ERROR_SZ];
failf(data,
"SSL_connect failed with error %d: %s",
detail,
@@ -458,7 +494,7 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- time_t timeout_ms;
+ timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -507,7 +543,8 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
: CURL_SOCKET_BAD;
what = Curl_socket_check(
- readfd, CURL_SOCKET_BAD, writefd, nonblocking ? 0 : timeout_ms);
+ readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking ? 0 : (time_t)timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 491def1..ef51b0d 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -113,7 +113,7 @@ typedef struct {
ptr->type = (_type); \
ptr->pValue = (_val); \
ptr->ulValueLen = (_len); \
-} WHILE_FALSE
+} while(0)
#define CERT_NewTempCertificate __CERT_NewTempCertificate
@@ -216,11 +216,19 @@ static const cipher_s cipherlist[] = {
{"dhe_rsa_chacha20_poly1305_sha_256",
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
#endif
+#ifdef TLS_AES_256_GCM_SHA384
+ {"aes_128_gcm_sha_256", TLS_AES_128_GCM_SHA256},
+ {"aes_256_gcm_sha_384", TLS_AES_256_GCM_SHA384},
+ {"chacha20_poly1305_sha_256", TLS_CHACHA20_POLY1305_SHA256},
+#endif
};
-#ifdef WIN32
+#if defined(WIN32)
static const char *pem_library = "nsspem.dll";
static const char *trust_library = "nssckbi.dll";
+#elif defined(__APPLE__)
+static const char *pem_library = "libnsspem.dylib";
+static const char *trust_library = "libnssckbi.dylib";
#else
static const char *pem_library = "libnsspem.so";
static const char *trust_library = "libnssckbi.so";
@@ -573,17 +581,19 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
/* acquire lock before call of CERT_CacheCRL() and accessing nss_crl_list */
PR_Lock(nss_crllock);
- /* store the CRL item so that we can free it in Curl_nss_cleanup() */
- if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
+ if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
+ /* unable to cache CRL */
SECITEM_FreeItem(crl_der, PR_TRUE);
PR_Unlock(nss_crllock);
- return CURLE_OUT_OF_MEMORY;
+ return CURLE_SSL_CRL_BADFILE;
}
- if(SECSuccess != CERT_CacheCRL(db, crl_der)) {
- /* unable to cache CRL */
+ /* store the CRL item so that we can free it in Curl_nss_cleanup() */
+ if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
+ if(SECSuccess == CERT_UncacheCRL(db, crl_der))
+ SECITEM_FreeItem(crl_der, PR_TRUE);
PR_Unlock(nss_crllock);
- return CURLE_SSL_CRL_BADFILE;
+ return CURLE_OUT_OF_MEMORY;
}
/* we need to clear session cache, so that the CRL could take effect */
@@ -681,7 +691,10 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
if(tmp)
PK11_FreeSlot(tmp);
- PK11_IsPresent(slot);
+ if(!PK11_IsPresent(slot)) {
+ PK11_FreeSlot(slot);
+ return CURLE_SSL_CERTPROBLEM;
+ }
status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
PK11_FreeSlot(slot);
@@ -1416,7 +1429,7 @@ static int Curl_nss_init(void)
{
/* curl_global_init() is not thread-safe so this test is ok */
if(nss_initlock == NULL) {
- PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
nss_findslot_lock = PR_NewLock();
@@ -1721,20 +1734,16 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
CURLcode result;
const long min = SSL_CONN_CONFIG(version);
const long max = SSL_CONN_CONFIG(version_max);
-
- /* map CURL_SSLVERSION_DEFAULT to NSS default */
- if(min == CURL_SSLVERSION_DEFAULT || max == CURL_SSLVERSION_MAX_DEFAULT) {
- /* map CURL_SSLVERSION_DEFAULT to NSS default */
- if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
- return CURLE_SSL_CONNECT_ERROR;
- /* ... but make sure we use at least TLSv1.0 according to libcurl API */
- if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
- sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
- }
+ SSLVersionRange vrange;
switch(min) {
case CURL_SSLVERSION_TLSv1:
case CURL_SSLVERSION_DEFAULT:
+ /* Bump our minimum TLS version if NSS has stricter requirements. */
+ if(SSL_VersionRangeGetDefault(ssl_variant_stream, &vrange) != SECSuccess)
+ return CURLE_SSL_CONNECT_ERROR;
+ if(sslver->min < vrange.min)
+ sslver->min = vrange.min;
break;
default:
result = nss_sslver_from_curl(&sslver->min, min);
@@ -2118,7 +2127,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
/* check timeout situation */
- const time_t time_left = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t time_left = Curl_timeleft(data, NULL, TRUE);
if(time_left < 0) {
failf(data, "timed out before SSL handshake");
result = CURLE_OPERATION_TIMEDOUT;
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 85e9be6..1d09cad 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -25,11 +25,6 @@
* but vtls.c should ever call or use these functions.
*/
-/*
- * The original SSLeay-using code for curl was written by Linas Vepstas and
- * Sampo Kellomaki 1998.
- */
-
#include "curl_setup.h"
#ifdef USE_OPENSSL
@@ -49,6 +44,7 @@
#include "strcase.h"
#include "hostcheck.h"
#include "multiif.h"
+#include "strerror.h"
#include "curl_printf.h"
#include <openssl/ssl.h>
#include <openssl/rand.h>
@@ -75,7 +71,7 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */ \
- !defined(OPENSSL_NO_ENGINE)
+ !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_UI_CONSOLE)
#define USE_OPENSSL_ENGINE
#include <openssl/engine.h>
#endif
@@ -146,16 +142,16 @@
#endif
#endif
-#ifdef LIBRESSL_VERSION_NUMBER
-#define OpenSSL_version_num() LIBRESSL_VERSION_NUMBER
-#endif
-
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \
!(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define HAVE_X509_GET0_SIGNATURE 1
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */
+#define HAVE_SSL_GET_SHUTDOWN 1
+#endif
+
#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \
OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \
!defined(OPENSSL_NO_COMP)
@@ -392,7 +388,20 @@ static const char *SSL_ERROR_to_str(int err)
*/
static char *ossl_strerror(unsigned long error, char *buf, size_t size)
{
+ if(size)
+ *buf = '\0';
+
+#ifdef OPENSSL_IS_BORINGSSL
+ ERR_error_string_n((uint32_t)error, buf, size);
+#else
ERR_error_string_n(error, buf, size);
+#endif
+
+ if(size > 1 && !*buf) {
+ strncpy(buf, (error ? "Unknown error" : "No error"), size);
+ buf[size - 1] = '\0';
+ }
+
return buf;
}
@@ -1022,14 +1031,8 @@ static int Curl_ossl_init(void)
ENGINE_load_builtin_engines();
#endif
- /* OPENSSL_config(NULL); is "strongly recommended" to use but unfortunately
- that function makes an exit() call on wrongly formatted config files
- which makes it hard to use in some situations. OPENSSL_config() itself
- calls CONF_modules_load_file() and we use that instead and we ignore
- its return code! */
-
- /* CONF_MFLAGS_DEFAULT_SECTION introduced some time between 0.9.8b and
- 0.9.8e */
+/* CONF_MFLAGS_DEFAULT_SECTION was introduced some time between 0.9.8b and
+ 0.9.8e */
#ifndef CONF_MFLAGS_DEFAULT_SECTION
#define CONF_MFLAGS_DEFAULT_SECTION 0x0
#endif
@@ -1536,8 +1539,13 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
if(altnames) {
+#ifdef OPENSSL_IS_BORINGSSL
+ size_t numalts;
+ size_t i;
+#else
int numalts;
int i;
+#endif
bool dnsmatched = FALSE;
bool ipmatched = FALSE;
@@ -1567,11 +1575,10 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
assumed that the data returned by ASN1_STRING_data() is null
terminated or does not contain embedded nulls." But also that
"The actual format of the data will depend on the actual string
- type itself: for example for and IA5String the data will be ASCII"
+ type itself: for example for an IA5String the data will be ASCII"
- Gisle researched the OpenSSL sources:
- "I checked the 0.9.6 and 0.9.8 sources before my patch and
- it always 0-terminates an IA5String."
+ It has been however verified that in 0.9.6 and 0.9.7, IA5String
+ is always zero-terminated.
*/
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
@@ -1635,8 +1642,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
/* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
is already UTF-8 encoded. We check for this case and copy the raw
string manually to avoid the problem. This code can be made
- conditional in the future when OpenSSL has been fixed. Work-around
- brought by Alexis S. L. Carvalho. */
+ conditional in the future when OpenSSL has been fixed. */
if(tmp) {
if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
j = ASN1_STRING_length(tmp);
@@ -2156,9 +2162,100 @@ get_ssl_version_txt(SSL *ssl)
}
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
static CURLcode
-set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
- int sockindex)
+set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
+{
+ /* first, TLS min version... */
+ long curl_ssl_version_min = SSL_CONN_CONFIG(version);
+ long curl_ssl_version_max;
+
+ /* convert cURL min SSL version option to OpenSSL constant */
+#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
+ uint16_t ossl_ssl_version_min = 0;
+ uint16_t ossl_ssl_version_max = 0;
+#else
+ long ossl_ssl_version_min = 0;
+ long ossl_ssl_version_max = 0;
+#endif
+ switch(curl_ssl_version_min) {
+ case CURL_SSLVERSION_TLSv1: /* TLS 1.x */
+ case CURL_SSLVERSION_TLSv1_0:
+ ossl_ssl_version_min = TLS1_VERSION;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ ossl_ssl_version_min = TLS1_1_VERSION;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ ossl_ssl_version_min = TLS1_2_VERSION;
+ break;
+#ifdef TLS1_3_VERSION
+ case CURL_SSLVERSION_TLSv1_3:
+ ossl_ssl_version_min = TLS1_3_VERSION;
+ break;
+#endif
+ }
+
+ /* CURL_SSLVERSION_DEFAULT means that no option was selected.
+ We don't want to pass 0 to SSL_CTX_set_min_proto_version as
+ it would enable all versions down to the lowest supported by
+ the library.
+ So we skip this, and stay with the OS default
+ */
+ if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) {
+ if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) {
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ }
+
+ /* ... then, TLS max version */
+ curl_ssl_version_max = SSL_CONN_CONFIG(version_max);
+
+ /* convert cURL max SSL version option to OpenSSL constant */
+ switch(curl_ssl_version_max) {
+ case CURL_SSLVERSION_MAX_TLSv1_0:
+ ossl_ssl_version_max = TLS1_VERSION;
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_1:
+ ossl_ssl_version_max = TLS1_1_VERSION;
+ break;
+ case CURL_SSLVERSION_MAX_TLSv1_2:
+ ossl_ssl_version_max = TLS1_2_VERSION;
+ break;
+#ifdef TLS1_3_VERSION
+ case CURL_SSLVERSION_MAX_TLSv1_3:
+ ossl_ssl_version_max = TLS1_3_VERSION;
+ break;
+#endif
+ case CURL_SSLVERSION_MAX_NONE: /* none selected */
+ case CURL_SSLVERSION_MAX_DEFAULT: /* max selected */
+ default:
+ /* SSL_CTX_set_max_proto_version states that:
+ setting the maximum to 0 will enable
+ protocol versions up to the highest version
+ supported by the library */
+ ossl_ssl_version_max = 0;
+ break;
+ }
+
+ if(!SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max)) {
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ return CURLE_OK;
+}
+#endif
+
+#ifdef OPENSSL_IS_BORINGSSL
+typedef uint32_t ctx_option_t;
+#else
+typedef long ctx_option_t;
+#endif
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
+static CURLcode
+set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
+ struct connectdata *conn, int sockindex)
{
#if (OPENSSL_VERSION_NUMBER < 0x1000100FL) || !defined(TLS1_3_VERSION)
/* convoluted #if condition just to avoid compiler warnings on unused
@@ -2230,6 +2327,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
}
return CURLE_OK;
}
+#endif
/* The "new session" callback must return zero if the session can be removed
* or non-zero if the session has been put into the session cache.
@@ -2296,7 +2394,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
X509_LOOKUP *lookup = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- long ctx_options = 0;
+ ctx_option_t ctx_options = 0;
+
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
@@ -2459,48 +2558,66 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#endif
switch(ssl_version) {
- case CURL_SSLVERSION_SSLv3:
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_TLSv1;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
-#endif
+ /* "--sslv2" option means SSLv2 only, disable all others */
+ case CURL_SSLVERSION_SSLv2:
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */
+ SSL_CTX_set_min_proto_version(BACKEND->ctx, SSL2_VERSION);
+ SSL_CTX_set_max_proto_version(BACKEND->ctx, SSL2_VERSION);
+#else
+ ctx_options |= SSL_OP_NO_SSLv3;
+ ctx_options |= SSL_OP_NO_TLSv1;
+# if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+# ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+# endif
+# endif
#endif
- break;
-
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- /* asking for any TLS version as the minimum, means no SSL versions
- allowed */
- ctx_options |= SSL_OP_NO_SSLv2;
- ctx_options |= SSL_OP_NO_SSLv3;
- result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
- if(result != CURLE_OK)
- return result;
- break;
+ break;
- case CURL_SSLVERSION_SSLv2:
- ctx_options |= SSL_OP_NO_SSLv3;
- ctx_options |= SSL_OP_NO_TLSv1;
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
- ctx_options |= SSL_OP_NO_TLSv1_1;
- ctx_options |= SSL_OP_NO_TLSv1_2;
-#ifdef TLS1_3_VERSION
- ctx_options |= SSL_OP_NO_TLSv1_3;
+ /* "--sslv3" option means SSLv3 only, disable all others */
+ case CURL_SSLVERSION_SSLv3:
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */
+ SSL_CTX_set_min_proto_version(BACKEND->ctx, SSL3_VERSION);
+ SSL_CTX_set_max_proto_version(BACKEND->ctx, SSL3_VERSION);
+#else
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_TLSv1;
+# if OPENSSL_VERSION_NUMBER >= 0x1000100FL
+ ctx_options |= SSL_OP_NO_TLSv1_1;
+ ctx_options |= SSL_OP_NO_TLSv1_2;
+# ifdef TLS1_3_VERSION
+ ctx_options |= SSL_OP_NO_TLSv1_3;
+# endif
+# endif
#endif
+ break;
+
+ /* "--tlsv<x.y>" options mean TLS >= version <x.y> */
+ case CURL_SSLVERSION_DEFAULT:
+ case CURL_SSLVERSION_TLSv1: /* TLS >= version 1.0 */
+ case CURL_SSLVERSION_TLSv1_0: /* TLS >= version 1.0 */
+ case CURL_SSLVERSION_TLSv1_1: /* TLS >= version 1.1 */
+ case CURL_SSLVERSION_TLSv1_2: /* TLS >= version 1.2 */
+ case CURL_SSLVERSION_TLSv1_3: /* TLS >= version 1.3 */
+ /* asking for any TLS version as the minimum, means no SSL versions
+ allowed */
+ ctx_options |= SSL_OP_NO_SSLv2;
+ ctx_options |= SSL_OP_NO_SSLv3;
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
+ result = set_ssl_version_min_max(BACKEND->ctx, conn);
+#else
+ result = set_ssl_version_min_max_legacy(&ctx_options, conn, sockindex);
#endif
- break;
+ if(result != CURLE_OK)
+ return result;
+ break;
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
+ default:
+ failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+ return CURLE_SSL_CONNECT_ERROR;
}
SSL_CTX_set_options(BACKEND->ctx, ctx_options);
@@ -2655,19 +2772,29 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
infof(data, " CRLfile: %s\n", ssl_crlfile);
}
- /* Try building a chain using issuers in the trusted store first to avoid
- problems with server-sent legacy intermediates.
- Newer versions of OpenSSL do alternate chain checking by default which
- gives us the same fix without as much of a performance hit (slight), so we
- prefer that if available.
- https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
- */
-#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
if(verifypeer) {
+ /* Try building a chain using issuers in the trusted store first to avoid
+ problems with server-sent legacy intermediates. Newer versions of
+ OpenSSL do alternate chain checking by default which gives us the same
+ fix without as much of a performance hit (slight), so we prefer that if
+ available.
+ https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
+ */
+#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
X509_V_FLAG_TRUSTED_FIRST);
- }
#endif
+#ifdef X509_V_FLAG_PARTIAL_CHAIN
+ if(!SSL_SET_OPTION(no_partialchain)) {
+ /* Have intermediate certificates in the trust store be treated as
+ trust-anchors, in the same way as self-signed root CA certificates
+ are. This allows users to verify servers using the intermediate cert
+ only, instead of needing the whole chain. */
+ X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
+ X509_V_FLAG_PARTIAL_CHAIN);
+ }
+#endif
+ }
/* SSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
@@ -2693,8 +2820,10 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
+ Curl_set_in_callback(data, true);
result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
data->set.ssl.fsslctxp);
+ Curl_set_in_callback(data, false);
if(result) {
failf(data, "error signaled by ssl ctx callback");
return result;
@@ -2875,8 +3004,13 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
const char * const hostname = SSL_IS_PROXY() ?
conn->http_proxy.host.name : conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+ char extramsg[80]="";
+ int sockerr = SOCKERRNO;
+ if(sockerr && detail == SSL_ERROR_SYSCALL)
+ Curl_strerror(sockerr, extramsg, sizeof(extramsg));
failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%ld ",
- SSL_ERROR_to_str(detail), hostname, port);
+ extramsg[0] ? extramsg : SSL_ERROR_to_str(detail),
+ hostname, port);
return result;
}
@@ -2952,7 +3086,7 @@ do { \
Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
if(1 != BIO_reset(mem)) \
break; \
-} WHILE_FALSE
+} while(0)
static void pubkey_show(struct Curl_easy *data,
BIO *mem,
@@ -2984,31 +3118,28 @@ do { \
if(_type->_name) { \
pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \
} \
-} WHILE_FALSE
+} while(0)
#endif
-static int X509V3_ext(struct Curl_easy *data,
+static void X509V3_ext(struct Curl_easy *data,
int certnum,
CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
{
int i;
- size_t j;
if((int)sk_X509_EXTENSION_num(exts) <= 0)
/* no extensions, bail out */
- return 1;
+ return;
for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
ASN1_OBJECT *obj;
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
BUF_MEM *biomem;
- char buf[512];
- char *ptr = buf;
char namebuf[128];
BIO *bio_out = BIO_new(BIO_s_mem());
if(!bio_out)
- return 1;
+ return;
obj = X509_EXTENSION_get_object(ext);
@@ -3018,28 +3149,18 @@ static int X509V3_ext(struct Curl_easy *data,
ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
BIO_get_mem_ptr(bio_out, &biomem);
-
- for(j = 0; j < (size_t)biomem->length; j++) {
- const char *sep = "";
- if(biomem->data[j] == '\n') {
- sep = ", ";
- j++; /* skip the newline */
- };
- while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
- j++;
- if(j<(size_t)biomem->length)
- ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
- biomem->data[j]);
- }
-
- Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
-
+ Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
+ biomem->length);
BIO_free(bio_out);
-
}
- return 0; /* all is fine */
}
+#ifdef OPENSSL_IS_BORINGSSL
+typedef size_t numcert_t;
+#else
+typedef int numcert_t;
+#endif
+
static CURLcode get_cert_chain(struct connectdata *conn,
struct ssl_connect_data *connssl)
@@ -3048,7 +3169,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
STACK_OF(X509) *sk;
int i;
struct Curl_easy *data = conn->data;
- int numcerts;
+ numcert_t numcerts;
BIO *mem;
sk = SSL_get_peer_cert_chain(BACKEND->handle);
@@ -3058,14 +3179,14 @@ static CURLcode get_cert_chain(struct connectdata *conn,
numcerts = sk_X509_num(sk);
- result = Curl_ssl_init_certinfo(data, numcerts);
+ result = Curl_ssl_init_certinfo(data, (int)numcerts);
if(result) {
return result;
}
mem = BIO_new(BIO_s_mem());
- for(i = 0; i < numcerts; i++) {
+ for(i = 0; i < (int)numcerts; i++) {
ASN1_INTEGER *num;
X509 *x = sk_X509_value(sk, i);
EVP_PKEY *pubkey = NULL;
@@ -3091,18 +3212,25 @@ static CURLcode get_cert_chain(struct connectdata *conn,
#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS)
{
- const X509_ALGOR *palg = NULL;
- ASN1_STRING *a = ASN1_STRING_new();
- if(a) {
- X509_get0_signature(&psig, &palg, x);
- X509_signature_print(mem, ARG2_X509_signature_print palg, a);
- ASN1_STRING_free(a);
-
- if(palg) {
- i2a_ASN1_OBJECT(mem, palg->algorithm);
+ const X509_ALGOR *sigalg = NULL;
+ X509_PUBKEY *xpubkey = NULL;
+ ASN1_OBJECT *pubkeyoid = NULL;
+
+ X509_get0_signature(&psig, &sigalg, x);
+ if(sigalg) {
+ i2a_ASN1_OBJECT(mem, sigalg->algorithm);
+ push_certinfo("Signature Algorithm", i);
+ }
+
+ xpubkey = X509_get_X509_PUBKEY(x);
+ if(xpubkey) {
+ X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey);
+ if(pubkeyoid) {
+ i2a_ASN1_OBJECT(mem, pubkeyoid);
push_certinfo("Public Key Algorithm", i);
}
}
+
X509V3_ext(data, i, X509_get0_extensions(x));
}
#else
@@ -3154,7 +3282,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
const BIGNUM *e;
RSA_get0_key(rsa, &n, &e, NULL);
- BN_print(mem, n);
+ BIO_printf(mem, "%d", BN_num_bits(n));
push_certinfo("RSA Public Key", i);
print_pubkey_BN(rsa, n, i);
print_pubkey_BN(rsa, e, i);
@@ -3279,7 +3407,6 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
if(len1 < 1)
break; /* failed */
- /* https://www.openssl.org/docs/crypto/buffer.html */
buff1 = temp = malloc(len1);
if(!buff1)
break; /* failed */
@@ -3301,7 +3428,6 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
} while(0);
- /* https://www.openssl.org/docs/crypto/buffer.html */
if(buff1)
free(buff1);
@@ -3531,7 +3657,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- time_t timeout_ms;
+ timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -3578,7 +3704,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:timeout_ms);
+ nonblocking?0:(time_t)timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -3702,10 +3828,22 @@ static ssize_t ossl_send(struct connectdata *conn,
*curlcode = CURLE_AGAIN;
return -1;
case SSL_ERROR_SYSCALL:
- failf(conn->data, "SSL_write() returned SYSCALL, errno = %d",
- SOCKERRNO);
- *curlcode = CURLE_SEND_ERROR;
- return -1;
+ {
+ int sockerr = SOCKERRNO;
+ sslerror = ERR_get_error();
+ if(sslerror)
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
+ else if(sockerr)
+ Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
+ else {
+ strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
+ error_buffer[sizeof(error_buffer) - 1] = '\0';
+ }
+ failf(conn->data, OSSL_PACKAGE " SSL_write: %s, errno %d",
+ error_buffer, sockerr);
+ *curlcode = CURLE_SEND_ERROR;
+ return -1;
+ }
case SSL_ERROR_SSL:
/* A failure in the SSL library occurred, usually a protocol error.
The OpenSSL error queue contains more information on the error. */
@@ -3760,7 +3898,10 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
break;
case SSL_ERROR_ZERO_RETURN: /* no more data */
/* close_notify alert */
- connclose(conn, "TLS close_notify");
+ if(num == FIRSTSOCKET)
+ /* mark the connection for close if it is indeed the control
+ connection */
+ connclose(conn, "TLS close_notify");
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
@@ -3775,14 +3916,44 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
if((nread < 0) || sslerror) {
/* If the return code was negative or there actually is an error in the
queue */
+ int sockerr = SOCKERRNO;
+ if(sslerror)
+ ossl_strerror(sslerror, error_buffer, sizeof(error_buffer));
+ else if(sockerr && err == SSL_ERROR_SYSCALL)
+ Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
+ else {
+ strncpy(error_buffer, SSL_ERROR_to_str(err), sizeof(error_buffer));
+ error_buffer[sizeof(error_buffer) - 1] = '\0';
+ }
failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d",
- (sslerror ?
- ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)) :
- SSL_ERROR_to_str(err)),
- SOCKERRNO);
+ error_buffer, sockerr);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
+ /* For debug builds be a little stricter and error on any
+ SSL_ERROR_SYSCALL. For example a server may have closed the connection
+ abruptly without a close_notify alert. For compatibility with older
+ peers we don't do this by default. #4624
+
+ We can use this to gauge how many users may be affected, and
+ if it goes ok eventually transition to allow in dev and release with
+ the newest OpenSSL: #if (OPENSSL_VERSION_NUMBER >= 0x10101000L) */
+#ifdef DEBUGBUILD
+ if(err == SSL_ERROR_SYSCALL) {
+ int sockerr = SOCKERRNO;
+ if(sockerr)
+ Curl_strerror(sockerr, error_buffer, sizeof(error_buffer));
+ else {
+ msnprintf(error_buffer, sizeof(error_buffer),
+ "Connection closed abruptly");
+ }
+ failf(conn->data, OSSL_PACKAGE " SSL_read: %s, errno %d"
+ " (Fatal because this is a curl debug build)",
+ error_buffer, sockerr);
*curlcode = CURLE_RECV_ERROR;
return -1;
}
+#endif
}
}
return nread;
@@ -3790,13 +3961,35 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
static size_t Curl_ossl_version(char *buffer, size_t size)
{
-#ifdef OPENSSL_IS_BORINGSSL
+#ifdef LIBRESSL_VERSION_NUMBER
+#if LIBRESSL_VERSION_NUMBER < 0x2070100fL
+ return msnprintf(buffer, size, "%s/%lx.%lx.%lx",
+ OSSL_PACKAGE,
+ (LIBRESSL_VERSION_NUMBER>>28)&0xf,
+ (LIBRESSL_VERSION_NUMBER>>20)&0xff,
+ (LIBRESSL_VERSION_NUMBER>>12)&0xff);
+#else /* OpenSSL_version() first appeared in LibreSSL 2.7.1 */
+ char *p;
+ int count;
+ const char *ver = OpenSSL_version(OPENSSL_VERSION);
+ const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */
+ if(Curl_strncasecompare(ver, expected, sizeof(expected) - 1)) {
+ ver += sizeof(expected) - 1;
+ }
+ count = msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver);
+ for(p = buffer; *p; ++p) {
+ if(ISSPACE(*p))
+ *p = '_';
+ }
+ return count;
+#endif
+#elif defined(OPENSSL_IS_BORINGSSL)
return msnprintf(buffer, size, OSSL_PACKAGE);
#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING)
return msnprintf(buffer, size, "%s/%s",
OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING));
#else
- /* not BoringSSL and not using OpenSSL_version */
+ /* not LibreSSL, BoringSSL and not using OpenSSL_version */
char sub[3];
unsigned long ssleay_value;
diff --git a/Utilities/cmcurl/lib/vtls/polarssl.c b/Utilities/cmcurl/lib/vtls/polarssl.c
deleted file mode 100644
index 7ea26b4..0000000
--- a/Utilities/cmcurl/lib/vtls/polarssl.c
+++ /dev/null
@@ -1,931 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
- * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
- *
- * 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 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
- * 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.
- *
- ***************************************************************************/
-
-/*
- * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code
- * but vtls.c should ever call or use these functions.
- *
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_POLARSSL
-#include <polarssl/net.h>
-#include <polarssl/ssl.h>
-#include <polarssl/certs.h>
-#include <polarssl/x509.h>
-#include <polarssl/version.h>
-#include <polarssl/sha256.h>
-
-#if POLARSSL_VERSION_NUMBER < 0x01030000
-#error too old PolarSSL
-#endif
-
-#include <polarssl/error.h>
-#include <polarssl/entropy.h>
-#include <polarssl/ctr_drbg.h>
-
-#include "urldata.h"
-#include "sendf.h"
-#include "inet_pton.h"
-#include "polarssl.h"
-#include "vtls.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "select.h"
-#include "strcase.h"
-#include "polarssl_threadlock.h"
-#include "multiif.h"
-#include "curl_printf.h"
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/* See https://tls.mbed.org/discussions/generic/
- howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
-*/
-#define RSA_PUB_DER_MAX_BYTES (38 + 2 * POLARSSL_MPI_MAX_SIZE)
-#define ECP_PUB_DER_MAX_BYTES (30 + 2 * POLARSSL_ECP_MAX_BYTES)
-
-#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
- RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
-
-struct ssl_backend_data {
- ctr_drbg_context ctr_drbg;
- entropy_context entropy;
- ssl_context ssl;
- int server_fd;
- x509_crt cacert;
- x509_crt clicert;
- x509_crl crl;
- rsa_context rsa;
-};
-
-#define BACKEND connssl->backend
-
-/* apply threading? */
-#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
-#define THREADING_SUPPORT
-#endif
-
-#ifndef POLARSSL_ERROR_C
-#define error_strerror(x,y,z)
-#endif /* POLARSSL_ERROR_C */
-
-
-#if defined(THREADING_SUPPORT)
-static entropy_context entropy;
-
-static int entropy_init_initialized = 0;
-
-/* start of entropy_init_mutex() */
-static void entropy_init_mutex(entropy_context *ctx)
-{
- /* lock 0 = entropy_init_mutex() */
- Curl_polarsslthreadlock_lock_function(0);
- if(entropy_init_initialized == 0) {
- entropy_init(ctx);
- entropy_init_initialized = 1;
- }
- Curl_polarsslthreadlock_unlock_function(0);
-}
-/* end of entropy_init_mutex() */
-
-/* start of entropy_func_mutex() */
-static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
-{
- int ret;
- /* lock 1 = entropy_func_mutex() */
- Curl_polarsslthreadlock_lock_function(1);
- ret = entropy_func(data, output, len);
- Curl_polarsslthreadlock_unlock_function(1);
-
- return ret;
-}
-/* end of entropy_func_mutex() */
-
-#endif /* THREADING_SUPPORT */
-
-/* Define this to enable lots of debugging for PolarSSL */
-#undef POLARSSL_DEBUG
-
-#ifdef POLARSSL_DEBUG
-static void polarssl_debug(void *context, int level, const char *line)
-{
- struct Curl_easy *data = NULL;
-
- if(!context)
- return;
-
- data = (struct Curl_easy *)context;
-
- infof(data, "%s", line);
- (void) level;
-}
-#else
-#endif
-
-/* ALPN for http2? */
-#ifdef POLARSSL_SSL_ALPN
-# define HAS_ALPN
-#endif
-
-static Curl_recv polarssl_recv;
-static Curl_send polarssl_send;
-
-static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version)
-{
- switch(ssl_version) {
- case CURL_SSLVERSION_TLSv1_0:
- *polarver = SSL_MINOR_VERSION_1;
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_1:
- *polarver = SSL_MINOR_VERSION_2;
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_2:
- *polarver = SSL_MINOR_VERSION_3;
- return CURLE_OK;
- case CURL_SSLVERSION_TLSv1_3:
- break;
- }
- return CURLE_SSL_CONNECT_ERROR;
-}
-
-static CURLcode
-set_ssl_version_min_max(struct connectdata *conn, int sockindex)
-{
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
- long ssl_version = SSL_CONN_CONFIG(version);
- long ssl_version_max = SSL_CONN_CONFIG(version_max);
- int ssl_min_ver = SSL_MINOR_VERSION_1;
- int ssl_max_ver = SSL_MINOR_VERSION_1;
- CURLcode result = CURLE_OK;
-
- switch(ssl_version) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- ssl_version = CURL_SSLVERSION_TLSv1_0;
- break;
- }
-
- switch(ssl_version_max) {
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_DEFAULT:
- ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
- break;
- }
-
- result = polarssl_version_from_curl(&ssl_min_ver, ssl_version);
- if(result) {
- failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
- return result;
- }
- result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16);
- if(result) {
- failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
- return result;
- }
-
- ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
- ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
-
- return result;
-}
-
-static CURLcode
-polarssl_connect_step1(struct connectdata *conn,
- int sockindex)
-{
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
- const char *capath = SSL_CONN_CONFIG(CApath);
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
- const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
- int ret = -1;
- char errorbuf[128];
- errorbuf[0] = 0;
-
- /* PolarSSL only supports SSLv3 and TLSv1 */
- if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
- failf(data, "PolarSSL does not support SSLv2");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
-#ifdef THREADING_SUPPORT
- entropy_init_mutex(&entropy);
-
- if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy,
- NULL, 0)) != 0) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
- -ret, errorbuf);
- }
-#else
- entropy_init(&BACKEND->entropy);
-
- if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy,
- NULL, 0)) != 0) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
- -ret, errorbuf);
- }
-#endif /* THREADING_SUPPORT */
-
- /* Load the trusted CA */
- memset(&BACKEND->cacert, 0, sizeof(x509_crt));
-
- if(SSL_CONN_CONFIG(CAfile)) {
- ret = x509_crt_parse_file(&BACKEND->cacert,
- SSL_CONN_CONFIG(CAfile));
-
- if(ret<0) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
- SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
-
- if(SSL_CONN_CONFIG(verifypeer))
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
-
- if(capath) {
- ret = x509_crt_parse_path(&BACKEND->cacert, capath);
-
- if(ret<0) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
- capath, -ret, errorbuf);
-
- if(SSL_CONN_CONFIG(verifypeer))
- return CURLE_SSL_CACERT_BADFILE;
- }
- }
-
- /* Load the client certificate */
- memset(&BACKEND->clicert, 0, sizeof(x509_crt));
-
- if(SSL_SET_OPTION(cert)) {
- ret = x509_crt_parse_file(&BACKEND->clicert,
- SSL_SET_OPTION(cert));
-
- if(ret) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
- SSL_SET_OPTION(cert), -ret, errorbuf);
-
- return CURLE_SSL_CERTPROBLEM;
- }
- }
-
- /* Load the client private key */
- if(SSL_SET_OPTION(key)) {
- pk_context pk;
- pk_init(&pk);
- ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
- SSL_SET_OPTION(key_passwd));
- if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
- ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
- if(ret == 0)
- rsa_copy(&BACKEND->rsa, pk_rsa(pk));
- else
- rsa_free(&BACKEND->rsa);
- pk_free(&pk);
-
- if(ret) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
- SSL_SET_OPTION(key), -ret, errorbuf);
-
- return CURLE_SSL_CERTPROBLEM;
- }
- }
-
- /* Load the CRL */
- memset(&BACKEND->crl, 0, sizeof(x509_crl));
-
- if(SSL_SET_OPTION(CRLfile)) {
- ret = x509_crl_parse_file(&BACKEND->crl,
- SSL_SET_OPTION(CRLfile));
-
- if(ret) {
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
- SSL_SET_OPTION(CRLfile), -ret, errorbuf);
-
- return CURLE_SSL_CRL_BADFILE;
- }
- }
-
- infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
-
- if(ssl_init(&BACKEND->ssl)) {
- failf(data, "PolarSSL: ssl_init failed");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- switch(SSL_CONN_CONFIG(version)) {
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_1);
- break;
- case CURL_SSLVERSION_SSLv3:
- ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_0);
- ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
- SSL_MINOR_VERSION_0);
- infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
- break;
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2:
- case CURL_SSLVERSION_TLSv1_3:
- {
- CURLcode result = set_ssl_version_min_max(conn, sockindex);
- if(result != CURLE_OK)
- return result;
- break;
- }
- default:
- failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
- ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
-
- ssl_set_rng(&BACKEND->ssl, ctr_drbg_random,
- &BACKEND->ctr_drbg);
- ssl_set_bio(&BACKEND->ssl,
- net_recv, &conn->sock[sockindex],
- net_send, &conn->sock[sockindex]);
-
- ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites());
-
- /* Check if there's a cached ID we can/should use here! */
- if(SSL_SET_OPTION(primary.sessionid)) {
- void *old_session = NULL;
-
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
- ret = ssl_set_session(&BACKEND->ssl, old_session);
- if(ret) {
- Curl_ssl_sessionid_unlock(conn);
- failf(data, "ssl_set_session returned -0x%x", -ret);
- return CURLE_SSL_CONNECT_ERROR;
- }
- infof(data, "PolarSSL re-using session\n");
- }
- Curl_ssl_sessionid_unlock(conn);
- }
-
- ssl_set_ca_chain(&BACKEND->ssl,
- &BACKEND->cacert,
- &BACKEND->crl,
- hostname);
-
- ssl_set_own_cert_rsa(&BACKEND->ssl,
- &BACKEND->clicert, &BACKEND->rsa);
-
- if(ssl_set_hostname(&BACKEND->ssl, hostname)) {
- /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
- to set in the SNI extension. So even if curl connects to a host
- specified as an IP address, this function must be used. */
- failf(data, "couldn't set hostname in PolarSSL");
- return CURLE_SSL_CONNECT_ERROR;
- }
-
-#ifdef HAS_ALPN
- if(conn->bits.tls_enable_alpn) {
- static const char *protocols[3];
- int cur = 0;
-
-#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
- protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
- infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
- }
-#endif
-
- protocols[cur++] = ALPN_HTTP_1_1;
- infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
-
- protocols[cur] = NULL;
-
- ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
- }
-#endif
-
-#ifdef POLARSSL_DEBUG
- ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
-#endif
-
- connssl->connecting_state = ssl_connect_2;
-
- return CURLE_OK;
-}
-
-static CURLcode
-polarssl_connect_step2(struct connectdata *conn,
- int sockindex)
-{
- int ret;
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
- char buffer[1024];
- const char * const pinnedpubkey = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-
-
- char errorbuf[128];
- errorbuf[0] = 0;
-
- conn->recv[sockindex] = polarssl_recv;
- conn->send[sockindex] = polarssl_send;
-
- ret = ssl_handshake(&BACKEND->ssl);
-
- switch(ret) {
- case 0:
- break;
-
- case POLARSSL_ERR_NET_WANT_READ:
- connssl->connecting_state = ssl_connect_2_reading;
- return CURLE_OK;
-
- case POLARSSL_ERR_NET_WANT_WRITE:
- connssl->connecting_state = ssl_connect_2_writing;
- return CURLE_OK;
-
- default:
- error_strerror(ret, errorbuf, sizeof(errorbuf));
- failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
- -ret, errorbuf);
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
- ssl_get_ciphersuite(&BACKEND->ssl) );
-
- ret = ssl_get_verify_result(&BACKEND->ssl);
-
- if(ret && SSL_CONN_CONFIG(verifypeer)) {
- if(ret & BADCERT_EXPIRED)
- failf(data, "Cert verify failed: BADCERT_EXPIRED");
-
- if(ret & BADCERT_REVOKED) {
- failf(data, "Cert verify failed: BADCERT_REVOKED");
- return CURLE_PEER_FAILED_VERIFICATION;
- }
-
- if(ret & BADCERT_CN_MISMATCH)
- failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
-
- if(ret & BADCERT_NOT_TRUSTED)
- failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
-
- return CURLE_PEER_FAILED_VERIFICATION;
- }
-
- if(ssl_get_peer_cert(&(BACKEND->ssl))) {
- /* If the session was resumed, there will be no peer certs */
- memset(buffer, 0, sizeof(buffer));
-
- if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
- ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
- infof(data, "Dumping cert info:\n%s\n", buffer);
- }
-
- /* adapted from mbedtls.c */
- if(pinnedpubkey) {
- int size;
- CURLcode result;
- x509_crt *p;
- unsigned char pubkey[PUB_DER_MAX_BYTES];
- const x509_crt *peercert;
-
- peercert = ssl_get_peer_cert(&BACKEND->ssl);
-
- if(!peercert || !peercert->raw.p || !peercert->raw.len) {
- failf(data, "Failed due to missing peer certificate");
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- }
-
- p = calloc(1, sizeof(*p));
-
- if(!p)
- return CURLE_OUT_OF_MEMORY;
-
- x509_crt_init(p);
-
- /* Make a copy of our const peercert because pk_write_pubkey_der
- needs a non-const key, for now.
- https://github.com/ARMmbed/mbedtls/issues/396 */
- if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
- failf(data, "Failed copying peer certificate");
- x509_crt_free(p);
- free(p);
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- }
-
- size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
-
- if(size <= 0) {
- failf(data, "Failed copying public key from peer certificate");
- x509_crt_free(p);
- free(p);
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
- }
-
- /* pk_write_pubkey_der writes data at the end of the buffer. */
- result = Curl_pin_peer_pubkey(data,
- pinnedpubkey,
- &pubkey[PUB_DER_MAX_BYTES - size], size);
- if(result) {
- x509_crt_free(p);
- free(p);
- return result;
- }
-
- x509_crt_free(p);
- free(p);
- }
-
-#ifdef HAS_ALPN
- if(conn->bits.tls_enable_alpn) {
- const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl);
-
- if(next_protocol != NULL) {
- infof(data, "ALPN, server accepted to use %s\n", next_protocol);
-
-#ifdef USE_NGHTTP2
- if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
- conn->negnpn = CURL_HTTP_VERSION_2;
- }
- else
-#endif
- if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
- }
- else
- infof(data, "ALPN, server did not agree to a protocol\n");
- Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
- BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
- }
-#endif
-
- connssl->connecting_state = ssl_connect_3;
- infof(data, "SSL connected\n");
-
- return CURLE_OK;
-}
-
-static CURLcode
-polarssl_connect_step3(struct connectdata *conn,
- int sockindex)
-{
- CURLcode retcode = CURLE_OK;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct Curl_easy *data = conn->data;
-
- DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
-
- if(SSL_SET_OPTION(primary.sessionid)) {
- int ret;
- ssl_session *our_ssl_sessionid;
- void *old_ssl_sessionid = NULL;
-
- our_ssl_sessionid = calloc(1, sizeof(ssl_session));
- if(!our_ssl_sessionid)
- return CURLE_OUT_OF_MEMORY;
-
- ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
- if(ret) {
- failf(data, "ssl_get_session returned -0x%x", -ret);
- return CURLE_SSL_CONNECT_ERROR;
- }
-
- /* If there's already a matching session in the cache, delete it */
- Curl_ssl_sessionid_lock(conn);
- if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
- Curl_ssl_delsessionid(conn, old_ssl_sessionid);
-
- retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
- Curl_ssl_sessionid_unlock(conn);
- if(retcode) {
- free(our_ssl_sessionid);
- failf(data, "failed to store ssl session");
- return retcode;
- }
- }
-
- connssl->connecting_state = ssl_connect_done;
-
- return CURLE_OK;
-}
-
-static ssize_t polarssl_send(struct connectdata *conn,
- int sockindex,
- const void *mem,
- size_t len,
- CURLcode *curlcode)
-{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- int ret = -1;
-
- ret = ssl_write(&BACKEND->ssl,
- (unsigned char *)mem, len);
-
- if(ret < 0) {
- *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
- CURLE_AGAIN : CURLE_SEND_ERROR;
- ret = -1;
- }
-
- return ret;
-}
-
-static void Curl_polarssl_close(struct connectdata *conn, int sockindex)
-{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- rsa_free(&BACKEND->rsa);
- x509_crt_free(&BACKEND->clicert);
- x509_crt_free(&BACKEND->cacert);
- x509_crl_free(&BACKEND->crl);
- ssl_free(&BACKEND->ssl);
-}
-
-static ssize_t polarssl_recv(struct connectdata *conn,
- int num,
- char *buf,
- size_t buffersize,
- CURLcode *curlcode)
-{
- struct ssl_connect_data *connssl = &conn->ssl[num];
- int ret = -1;
- ssize_t len = -1;
-
- memset(buf, 0, buffersize);
- ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize);
-
- if(ret <= 0) {
- if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
- return 0;
-
- *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
- CURLE_AGAIN : CURLE_RECV_ERROR;
- return -1;
- }
-
- len = ret;
-
- return len;
-}
-
-static void Curl_polarssl_session_free(void *ptr)
-{
- ssl_session_free(ptr);
- free(ptr);
-}
-
-/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
- higher) will be mbed TLS branded.. */
-
-static size_t Curl_polarssl_version(char *buffer, size_t size)
-{
- unsigned int version = version_get_number();
- return msnprintf(buffer, size, "%s/%d.%d.%d",
- version >= 0x01030A00?"mbedTLS":"PolarSSL",
- version>>24, (version>>16)&0xff, (version>>8)&0xff);
-}
-
-static CURLcode
-polarssl_connect_common(struct connectdata *conn,
- int sockindex,
- bool nonblocking,
- bool *done)
-{
- CURLcode result;
- struct Curl_easy *data = conn->data;
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
- int what;
-
- /* check if the connection has already been established */
- if(ssl_connection_complete == connssl->state) {
- *done = TRUE;
- return CURLE_OK;
- }
-
- if(ssl_connect_1 == connssl->connecting_state) {
- /* Find out how much more time we're allowed */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
- if(timeout_ms < 0) {
- /* no need to continue if time already is up */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
-
- result = polarssl_connect_step1(conn, sockindex);
- if(result)
- return result;
- }
-
- while(ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state) {
-
- /* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
- if(timeout_ms < 0) {
- /* no need to continue if time already is up */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
-
- /* if ssl is expecting something, check if it's available. */
- if(connssl->connecting_state == ssl_connect_2_reading ||
- connssl->connecting_state == ssl_connect_2_writing) {
-
- curl_socket_t writefd = ssl_connect_2_writing ==
- connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- curl_socket_t readfd = ssl_connect_2_reading ==
- connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
-
- what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:timeout_ms);
- if(what < 0) {
- /* fatal error */
- failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
- return CURLE_SSL_CONNECT_ERROR;
- }
- else if(0 == what) {
- if(nonblocking) {
- *done = FALSE;
- return CURLE_OK;
- }
- else {
- /* timeout */
- failf(data, "SSL connection timeout");
- return CURLE_OPERATION_TIMEDOUT;
- }
- }
- /* socket is readable or writable */
- }
-
- /* Run transaction, and return to the caller if it failed or if
- * this connection is part of a multi handle and this loop would
- * execute again. This permits the owner of a multi handle to
- * abort a connection attempt before step2 has completed while
- * ensuring that a client using select() or epoll() will always
- * have a valid fdset to wait on.
- */
- result = polarssl_connect_step2(conn, sockindex);
- if(result || (nonblocking &&
- (ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state)))
- return result;
-
- } /* repeat step2 until all transactions are done. */
-
- if(ssl_connect_3 == connssl->connecting_state) {
- result = polarssl_connect_step3(conn, sockindex);
- if(result)
- return result;
- }
-
- if(ssl_connect_done == connssl->connecting_state) {
- connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = polarssl_recv;
- conn->send[sockindex] = polarssl_send;
- *done = TRUE;
- }
- else
- *done = FALSE;
-
- /* Reset our connect state machine */
- connssl->connecting_state = ssl_connect_1;
-
- return CURLE_OK;
-}
-
-static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
- int sockindex, bool *done)
-{
- return polarssl_connect_common(conn, sockindex, TRUE, done);
-}
-
-
-static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex)
-{
- CURLcode result;
- bool done = FALSE;
-
- result = polarssl_connect_common(conn, sockindex, FALSE, &done);
- if(result)
- return result;
-
- DEBUGASSERT(done);
-
- return CURLE_OK;
-}
-
-/*
- * return 0 error initializing SSL
- * return 1 SSL initialized successfully
- */
-static int Curl_polarssl_init(void)
-{
- return Curl_polarsslthreadlock_thread_setup();
-}
-
-static void Curl_polarssl_cleanup(void)
-{
- (void)Curl_polarsslthreadlock_thread_cleanup();
-}
-
-static bool Curl_polarssl_data_pending(const struct connectdata *conn,
- int sockindex)
-{
- const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
-}
-
-static CURLcode Curl_polarssl_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len UNUSED_PARAM)
-{
- (void)sha256len;
- sha256(input, inputlen, sha256sum, 0);
- return CURLE_OK;
-}
-
-static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
- CURLINFO info UNUSED_PARAM)
-{
- (void)info;
- return &BACKEND->ssl;
-}
-
-const struct Curl_ssl Curl_ssl_polarssl = {
- { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
-
- SSLSUPP_CA_PATH |
- SSLSUPP_PINNEDPUBKEY,
-
- sizeof(struct ssl_backend_data),
-
- Curl_polarssl_init, /* init */
- Curl_polarssl_cleanup, /* cleanup */
- Curl_polarssl_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
- Curl_none_shutdown, /* shutdown */
- Curl_polarssl_data_pending, /* data_pending */
- /* This might cause libcurl to use a weeker random! */
- Curl_none_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
- Curl_polarssl_connect, /* connect */
- Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
- Curl_polarssl_get_internals, /* get_internals */
- Curl_polarssl_close, /* close_one */
- Curl_none_close_all, /* close_all */
- Curl_polarssl_session_free, /* session_free */
- Curl_none_set_engine, /* set_engine */
- Curl_none_set_engine_default, /* set_engine_default */
- Curl_none_engines_list, /* engines_list */
- Curl_none_false_start, /* false_start */
- Curl_none_md5sum, /* md5sum */
- Curl_polarssl_sha256sum /* sha256sum */
-};
-
-#endif /* USE_POLARSSL */
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index 0f6f734..0818d94 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, 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
@@ -554,10 +554,6 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
switch(conn->ssl_config.version) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
- schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
- SP_PROT_TLS1_1_CLIENT |
- SP_PROT_TLS1_2_CLIENT;
- break;
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
@@ -722,7 +718,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
unsigned short* list_len = NULL;
/* The first four bytes will be an unsigned int indicating number
- of bytes of data in the rest of the the buffer. */
+ of bytes of data in the rest of the buffer. */
extension_len = (unsigned int *)(&alpn_buffer[cur]);
cur += sizeof(unsigned int);
@@ -1181,6 +1177,7 @@ struct Adder_args
struct connectdata *conn;
CURLcode result;
int idx;
+ int certs_count;
};
static bool
@@ -1191,7 +1188,9 @@ add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
if(valid_cert_encoding(ccert_context)) {
const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded;
- args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end);
+ int insert_index = (args->certs_count - 1) - args->idx;
+ args->result = Curl_extract_certinfo(args->conn, insert_index, beg, end);
+ args->idx++;
}
return args->result == CURLE_OK;
}
@@ -1326,6 +1325,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
struct Adder_args args;
args.conn = conn;
args.idx = 0;
+ args.certs_count = certs_count;
traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
result = args.result;
}
@@ -1347,7 +1347,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- time_t timeout_ms;
+ timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -1394,7 +1394,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking ? 0 : timeout_ms);
+ nonblocking ? 0 : (time_t)timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
@@ -1544,7 +1544,7 @@ schannel_send(struct connectdata *conn, int sockindex,
/* send entire message or fail */
while(len > (size_t)written) {
ssize_t this_write;
- time_t timeleft;
+ timediff_t timeleft;
int what;
this_write = 0;
@@ -1855,7 +1855,9 @@ schannel_recv(struct connectdata *conn, int sockindex,
goto cleanup;
}
else {
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
char buffer[STRERROR_LEN];
+#endif
*err = CURLE_RECV_ERROR;
infof(data, "schannel: failed to read data from server: %s\n",
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
diff --git a/Utilities/cmcurl/lib/vtls/schannel_verify.c b/Utilities/cmcurl/lib/vtls/schannel_verify.c
index 5a09e96..e75132c 100644
--- a/Utilities/cmcurl/lib/vtls/schannel_verify.c
+++ b/Utilities/cmcurl/lib/vtls/schannel_verify.c
@@ -7,7 +7,7 @@
*
* Copyright (C) 2012 - 2016, Marc Hoersken, <info@marc-hoersken.de>
* Copyright (C) 2012, Mark Salisbury, <mark.salisbury@hp.com>
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, 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
@@ -99,7 +99,8 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
char buffer[STRERROR_LEN];
failf(data,
"schannel: invalid path name for CA file '%s': %s",
- ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ ca_file,
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
@@ -111,7 +112,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
*/
ca_file_handle = CreateFile(ca_file_tstr,
GENERIC_READ,
- 0,
+ FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
@@ -120,7 +121,8 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
char buffer[STRERROR_LEN];
failf(data,
"schannel: failed to open CA file '%s': %s",
- ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ ca_file,
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
@@ -129,7 +131,8 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
char buffer[STRERROR_LEN];
failf(data,
"schannel: failed to determine size of CA file '%s': %s",
- ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ ca_file,
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
@@ -159,7 +162,8 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
char buffer[STRERROR_LEN];
failf(data,
"schannel: failed to read from CA file '%s': %s",
- ca_file, Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ ca_file,
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
goto cleanup;
}
@@ -223,7 +227,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
"schannel: failed to extract certificate from CA file "
"'%s': %s",
ca_file,
- Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
more_certs = 0;
}
@@ -252,7 +256,8 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
"schannel: failed to add certificate from CA file '%s' "
"to certificate store: %s",
ca_file,
- Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ Curl_winapi_strerror(GetLastError(), buffer,
+ sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
more_certs = 0;
}
@@ -288,6 +293,133 @@ cleanup:
return result;
}
+/*
+ * Returns the number of characters necessary to populate all the host_names.
+ * If host_names is not NULL, populate it with all the host names. Each string
+ * in the host_names is null-terminated and the last string is double
+ * null-terminated. If no DNS names are found, a single null-terminated empty
+ * string is returned.
+ */
+static DWORD cert_get_name_string(struct Curl_easy *data,
+ CERT_CONTEXT *cert_context,
+ LPTSTR host_names,
+ DWORD length)
+{
+ DWORD actual_length = 0;
+ BOOL compute_content = FALSE;
+ CERT_INFO *cert_info = NULL;
+ CERT_EXTENSION *extension = NULL;
+ CRYPT_DECODE_PARA decode_para = {0, 0, 0};
+ CERT_ALT_NAME_INFO *alt_name_info = NULL;
+ DWORD alt_name_info_size = 0;
+ BOOL ret_val = FALSE;
+ LPTSTR current_pos = NULL;
+ DWORD i;
+
+ /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */
+ if(Curl_verify_windows_version(6, 2, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL)) {
+#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
+ /* CertGetNameString will provide the 8-bit character string without
+ * any decoding */
+ DWORD name_flags =
+ CERT_NAME_DISABLE_IE4_UTF8_FLAG | CERT_NAME_SEARCH_ALL_NAMES_FLAG;
+ actual_length = CertGetNameString(cert_context,
+ CERT_NAME_DNS_TYPE,
+ name_flags,
+ NULL,
+ host_names,
+ length);
+ return actual_length;
+#endif
+ }
+
+ compute_content = host_names != NULL && length != 0;
+
+ /* Initialize default return values. */
+ actual_length = 1;
+ if(compute_content) {
+ *host_names = '\0';
+ }
+
+ if(!cert_context) {
+ failf(data, "schannel: Null certificate context.");
+ return actual_length;
+ }
+
+ cert_info = cert_context->pCertInfo;
+ if(!cert_info) {
+ failf(data, "schannel: Null certificate info.");
+ return actual_length;
+ }
+
+ extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
+ cert_info->cExtension,
+ cert_info->rgExtension);
+ if(!extension) {
+ failf(data, "schannel: CertFindExtension() returned no extension.");
+ return actual_length;
+ }
+
+ decode_para.cbSize = sizeof(CRYPT_DECODE_PARA);
+
+ ret_val =
+ CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ szOID_SUBJECT_ALT_NAME2,
+ extension->Value.pbData,
+ extension->Value.cbData,
+ CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
+ &decode_para,
+ &alt_name_info,
+ &alt_name_info_size);
+ if(!ret_val) {
+ failf(data,
+ "schannel: CryptDecodeObjectEx() returned no alternate name "
+ "information.");
+ return actual_length;
+ }
+
+ current_pos = host_names;
+
+ /* Iterate over the alternate names and populate host_names. */
+ for(i = 0; i < alt_name_info->cAltEntry; i++) {
+ const CERT_ALT_NAME_ENTRY *entry = &alt_name_info->rgAltEntry[i];
+ wchar_t *dns_w = NULL;
+ size_t current_length = 0;
+
+ if(entry->dwAltNameChoice != CERT_ALT_NAME_DNS_NAME) {
+ continue;
+ }
+ if(entry->pwszDNSName == NULL) {
+ infof(data, "schannel: Empty DNS name.");
+ continue;
+ }
+ current_length = wcslen(entry->pwszDNSName) + 1;
+ if(!compute_content) {
+ actual_length += (DWORD)current_length;
+ continue;
+ }
+ /* Sanity check to prevent buffer overrun. */
+ if((actual_length + current_length) > length) {
+ failf(data, "schannel: Not enough memory to list all host names.");
+ break;
+ }
+ dns_w = entry->pwszDNSName;
+ /* pwszDNSName is in ia5 string format and hence doesn't contain any
+ * non-ascii characters. */
+ while(*dns_w != '\0') {
+ *current_pos++ = (char)(*dns_w++);
+ }
+ *current_pos++ = '\0';
+ actual_length += (DWORD)current_length;
+ }
+ if(compute_content) {
+ /* Last string has double null-terminator. */
+ *current_pos = '\0';
+ }
+ return actual_length;
+}
+
static CURLcode verify_host(struct Curl_easy *data,
CERT_CONTEXT *pCertContextServer,
const char * const conn_hostname)
@@ -298,21 +430,8 @@ static CURLcode verify_host(struct Curl_easy *data,
DWORD len = 0;
DWORD actual_len = 0;
- /* CertGetNameString will provide the 8-bit character string without
- * any decoding */
- DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG;
-
-#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
- name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG;
-#endif
-
/* Determine the size of the string needed for the cert hostname */
- len = CertGetNameString(pCertContextServer,
- CERT_NAME_DNS_TYPE,
- name_flags,
- NULL,
- NULL,
- 0);
+ len = cert_get_name_string(data, pCertContextServer, NULL, 0);
if(len == 0) {
failf(data,
"schannel: CertGetNameString() returned no "
@@ -329,12 +448,8 @@ static CURLcode verify_host(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
goto cleanup;
}
- actual_len = CertGetNameString(pCertContextServer,
- CERT_NAME_DNS_TYPE,
- name_flags,
- NULL,
- (LPTSTR) cert_hostname_buff,
- len);
+ actual_len = cert_get_name_string(
+ data, pCertContextServer, (LPTSTR)cert_hostname_buff, len);
/* Sanity check */
if(actual_len != len) {
@@ -460,7 +575,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
if(!trust_store) {
char buffer[STRERROR_LEN];
failf(data, "schannel: failed to create certificate store: %s",
- Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
}
else {
@@ -489,7 +604,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
char buffer[STRERROR_LEN];
failf(data,
"schannel: failed to create certificate chain engine: %s",
- Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
result = CURLE_SSL_CACERT_BADFILE;
}
}
@@ -512,7 +627,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
&pChainContext)) {
char buffer[STRERROR_LEN];
failf(data, "schannel: CertGetCertificateChain failed: %s",
- Curl_strerror(GetLastError(), buffer, sizeof(buffer)));
+ Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
pChainContext = NULL;
result = CURLE_PEER_FAILED_VERIFICATION;
}
diff --git a/Utilities/cmcurl/lib/vtls/sectransp.c b/Utilities/cmcurl/lib/vtls/sectransp.c
index 2fdf662..7dd028f 100644
--- a/Utilities/cmcurl/lib/vtls/sectransp.c
+++ b/Utilities/cmcurl/lib/vtls/sectransp.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2020, 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
@@ -79,7 +79,7 @@
/* These macros mean "the following code is present to allow runtime backward
compatibility with at least this cat or earlier":
(You set this at build-time using the compiler command line option
- "-mmacos-version-min.") */
+ "-mmacosx-version-min.") */
#define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
#define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
#define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
@@ -1164,7 +1164,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
* the Keychain.
*
* As this doesn't match iOS, and apps may not want to see their client
- * certificate saved in the the user's keychain, we use SecItemImport
+ * certificate saved in the user's keychain, we use SecItemImport
* with a NULL keychain to avoid importing it.
*
* This returns a SecCertificateRef from which we can construct a
@@ -2111,8 +2111,8 @@ static int append_cert_to_array(struct Curl_easy *data,
return CURLE_OK;
}
-static int verify_cert(const char *cafile, struct Curl_easy *data,
- SSLContextRef ctx)
+static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
+ SSLContextRef ctx)
{
int n = 0, rc;
long res;
@@ -2370,10 +2370,10 @@ sectransp_connect_step2(struct connectdata *conn, int sockindex)
Leopard's headers */
case -9841:
if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
- int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
- BACKEND->ssl_ctx);
- if(res != CURLE_OK)
- return res;
+ CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
+ BACKEND->ssl_ctx);
+ if(result)
+ return result;
}
/* the documentation says we need to call SSLHandshake() again */
return sectransp_connect_step2(conn, sockindex);
@@ -2805,7 +2805,7 @@ sectransp_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- long timeout_ms;
+ timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -2852,7 +2852,7 @@ sectransp_connect_common(struct connectdata *conn,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:timeout_ms);
+ nonblocking?0:(time_t)timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -3186,7 +3186,10 @@ static ssize_t sectransp_recv(struct connectdata *conn,
/*struct Curl_easy *data = conn->data;*/
struct ssl_connect_data *connssl = &conn->ssl[num];
size_t processed = 0UL;
- OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed);
+ OSStatus err;
+
+ again:
+ err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed);
if(err != noErr) {
switch(err) {
@@ -3207,6 +3210,16 @@ static ssize_t sectransp_recv(struct connectdata *conn,
return -1L;
break;
+ /* The below is errSSLPeerAuthCompleted; it's not defined in
+ Leopard's headers */
+ case -9841:
+ if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
+ CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data,
+ BACKEND->ssl_ctx);
+ if(result)
+ return result;
+ }
+ goto again;
default:
failf(conn->data, "SSLRead() return error %d", err);
*curlcode = CURLE_RECV_ERROR;
diff --git a/Utilities/cmcurl/lib/vtls/vtls.c b/Utilities/cmcurl/lib/vtls/vtls.c
index a7452dc..dfefa1b 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.c
+++ b/Utilities/cmcurl/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -97,7 +97,8 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
- Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13))
+ Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13) &&
+ Curl_safe_strcasecompare(data->pinned_key, needle->pinned_key))
return TRUE;
return FALSE;
@@ -121,6 +122,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
CLONE_STRING(egdsocket);
CLONE_STRING(cipher_list);
CLONE_STRING(cipher_list13);
+ CLONE_STRING(pinned_key);
return TRUE;
}
@@ -134,6 +136,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
Curl_safefree(sslc->egdsocket);
Curl_safefree(sslc->cipher_list);
Curl_safefree(sslc->cipher_list13);
+ Curl_safefree(sslc->pinned_key);
}
#ifdef USE_SSL
@@ -513,16 +516,12 @@ void Curl_ssl_close_all(struct Curl_easy *data)
}
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
- defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \
- defined(USE_MBEDTLS) || defined(USE_CYASSL)
-int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
- int numsocks)
+ defined(USE_SECTRANSP) || defined(USE_NSS) || \
+ defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_BEARSSL)
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
{
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
- if(!numsocks)
- return GETSOCK_BLANK;
-
if(connssl->connecting_state == ssl_connect_2_writing) {
/* write mode */
socks[0] = conn->sock[FIRSTSOCKET];
@@ -538,12 +537,10 @@ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
}
#else
int Curl_ssl_getsock(struct connectdata *conn,
- curl_socket_t *socks,
- int numsocks)
+ curl_socket_t *socks)
{
(void)conn;
(void)socks;
- (void)numsocks;
return GETSOCK_BLANK;
}
/* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL || USE_SECTRANSP || USE_NSS */
@@ -1172,8 +1169,8 @@ static const struct Curl_ssl Curl_ssl_multi = {
const struct Curl_ssl *Curl_ssl =
#if defined(CURL_WITH_MULTI_SSL)
&Curl_ssl_multi;
-#elif defined(USE_CYASSL)
- &Curl_ssl_cyassl;
+#elif defined(USE_WOLFSSL)
+ &Curl_ssl_wolfssl;
#elif defined(USE_SECTRANSP)
&Curl_ssl_sectransp;
#elif defined(USE_GNUTLS)
@@ -1186,19 +1183,19 @@ const struct Curl_ssl *Curl_ssl =
&Curl_ssl_nss;
#elif defined(USE_OPENSSL)
&Curl_ssl_openssl;
-#elif defined(USE_POLARSSL)
- &Curl_ssl_polarssl;
#elif defined(USE_SCHANNEL)
&Curl_ssl_schannel;
#elif defined(USE_MESALINK)
&Curl_ssl_mesalink;
+#elif defined(USE_BEARSSL)
+ &Curl_ssl_bearssl;
#else
#error "Missing struct Curl_ssl for selected SSL backend"
#endif
static const struct Curl_ssl *available_backends[] = {
-#if defined(USE_CYASSL)
- &Curl_ssl_cyassl,
+#if defined(USE_WOLFSSL)
+ &Curl_ssl_wolfssl,
#endif
#if defined(USE_SECTRANSP)
&Curl_ssl_sectransp,
@@ -1218,15 +1215,15 @@ static const struct Curl_ssl *available_backends[] = {
#if defined(USE_OPENSSL)
&Curl_ssl_openssl,
#endif
-#if defined(USE_POLARSSL)
- &Curl_ssl_polarssl,
-#endif
#if defined(USE_SCHANNEL)
&Curl_ssl_schannel,
#endif
#if defined(USE_MESALINK)
&Curl_ssl_mesalink,
#endif
+#if defined(USE_BEARSSL)
+ &Curl_ssl_bearssl,
+#endif
NULL
};
@@ -1234,7 +1231,7 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
{
static const struct Curl_ssl *selected;
static char backends[200];
- static size_t total;
+ static size_t backends_len;
const struct Curl_ssl *current;
current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
@@ -1246,27 +1243,32 @@ static size_t Curl_multissl_version(char *buffer, size_t size)
selected = current;
- for(i = 0; available_backends[i] && p < (end - 4); i++) {
- if(i)
- *(p++) = ' ';
- if(selected != available_backends[i])
- *(p++) = '(';
- p += available_backends[i]->version(p, end - p - 2);
- if(selected != available_backends[i])
- *(p++) = ')';
+ backends[0] = '\0';
+
+ for(i = 0; available_backends[i]; ++i) {
+ char vb[200];
+ bool paren = (selected != available_backends[i]);
+
+ if(available_backends[i]->version(vb, sizeof(vb))) {
+ p += msnprintf(p, end - p, "%s%s%s%s", (p != backends ? " " : ""),
+ (paren ? "(" : ""), vb, (paren ? ")" : ""));
+ }
}
- *p = '\0';
- total = p - backends;
+
+ backends_len = p - backends;
}
- if(size > total)
- memcpy(buffer, backends, total + 1);
- else {
- memcpy(buffer, backends, size - 1);
+ if(!size)
+ return 0;
+
+ if(size <= backends_len) {
+ strncpy(buffer, backends, size - 1);
buffer[size - 1] = '\0';
+ return size - 1;
}
- return CURLMIN(size - 1, total);
+ strcpy(buffer, backends);
+ return backends_len;
}
static int multissl_init(const struct Curl_ssl *backend)
diff --git a/Utilities/cmcurl/lib/vtls/vtls.h b/Utilities/cmcurl/lib/vtls/vtls.h
index 2a87ca1..f58adee 100644
--- a/Utilities/cmcurl/lib/vtls/vtls.h
+++ b/Utilities/cmcurl/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -102,12 +102,12 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
#include "gtls.h" /* GnuTLS versions */
#include "nssg.h" /* NSS versions */
#include "gskit.h" /* Global Secure ToolKit versions */
-#include "polarssl.h" /* PolarSSL versions */
-#include "cyassl.h" /* CyaSSL versions */
+#include "wolfssl.h" /* wolfSSL versions */
#include "schannel.h" /* Schannel SSPI version */
#include "sectransp.h" /* SecureTransport (Darwin) version */
#include "mbedtls.h" /* mbedTLS versions */
#include "mesalink.h" /* MesaLink versions */
+#include "bearssl.h" /* BearSSL versions */
#ifndef MAX_PINNED_PUBKEY_SIZE
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
@@ -143,8 +143,7 @@ bool Curl_ssl_config_matches(struct ssl_primary_config* data,
bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest);
void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc);
-int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
- int numsocks);
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
int Curl_ssl_backend(void);
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/wolfssl.c
index 44a2bdd..8c2d3f4 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -21,31 +21,21 @@
***************************************************************************/
/*
- * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code
+ * Source file for all wolfSSL specific code for the TLS/SSL layer. No code
* but vtls.c should ever call or use these functions.
*
*/
#include "curl_setup.h"
-#ifdef USE_CYASSL
+#ifdef USE_WOLFSSL
#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. 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)
-/* Safety measure. If either is defined some API include was already included
-and that's a problem since options.h hasn't been included yet. */
-#error "CyaSSL API was included before the CyaSSL build options."
-#endif
-#include <cyassl/options.h>
-#endif
+#include <wolfssl/version.h>
+#include <wolfssl/options.h>
/* To determine what functions are available we rely on one or both of:
- - the user's options.h generated by CyaSSL/wolfSSL
+ - the user's options.h generated by 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. */
@@ -61,8 +51,8 @@ and that's a problem since options.h hasn't been included yet. */
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)
+#if (LIBWOLFSSL_VERSION_HEX < 0x03006006) || \
+ defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
#define WOLFSSL_ALLOW_SSLV3
#endif
#endif
@@ -81,33 +71,21 @@ and that's a problem since options.h hasn't been included yet. */
#include "curl_printf.h"
#include "multiif.h"
-#include <cyassl/openssl/ssl.h>
-#include <cyassl/ssl.h>
-#ifdef HAVE_CYASSL_ERROR_SSL_H
-#include <cyassl/error-ssl.h>
-#else
-#include <cyassl/error.h>
-#endif
-#include <cyassl/ctaocrypt/random.h>
-#include <cyassl/ctaocrypt/sha256.h>
-
-#include "cyassl.h"
+#include <wolfssl/openssl/ssl.h>
+#include <wolfssl/ssl.h>
+#include <wolfssl/error-ssl.h>
+#include "wolfssl.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
-#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */
-#define CYASSL_MAX_ERROR_SZ 80
-#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) || \
+#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
(defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
#define KEEP_PEER_CERT
#endif
@@ -120,8 +98,8 @@ struct ssl_backend_data {
#define BACKEND connssl->backend
-static Curl_recv cyassl_recv;
-static Curl_send cyassl_send;
+static Curl_recv wolfssl_recv;
+static Curl_send wolfssl_send;
static int do_file_type(const char *type)
@@ -140,7 +118,7 @@ static int do_file_type(const char *type)
* layer and do all necessary magic.
*/
static CURLcode
-cyassl_connect_step1(struct connectdata *conn,
+wolfssl_connect_step1(struct connectdata *conn,
int sockindex)
{
char *ciphers;
@@ -159,7 +137,7 @@ cyassl_connect_step1(struct connectdata *conn,
return CURLE_OK;
if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
- failf(data, "CyaSSL does not support to set maximum SSL/TLS version");
+ failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -167,11 +145,11 @@ cyassl_connect_step1(struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
-#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
+#if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
/* minimum protocol version is set later after the CTX object is created */
req_method = SSLv23_client_method();
#else
- infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
+ infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
"TLS 1.0 is used exclusively\n");
req_method = TLSv1_client_method();
#endif
@@ -182,7 +160,7 @@ cyassl_connect_step1(struct connectdata *conn,
req_method = TLSv1_client_method();
use_sni(TRUE);
#else
- failf(data, "CyaSSL does not support TLS 1.0");
+ failf(data, "wolfSSL does not support TLS 1.0");
return CURLE_NOT_BUILT_IN;
#endif
break;
@@ -200,7 +178,7 @@ cyassl_connect_step1(struct connectdata *conn,
use_sni(TRUE);
break;
#else
- failf(data, "CyaSSL: TLS 1.3 is not yet supported");
+ failf(data, "wolfSSL: TLS 1.3 is not yet supported");
return CURLE_SSL_CONNECT_ERROR;
#endif
case CURL_SSLVERSION_SSLv3:
@@ -208,12 +186,12 @@ cyassl_connect_step1(struct connectdata *conn,
req_method = SSLv3_client_method();
use_sni(FALSE);
#else
- failf(data, "CyaSSL does not support SSLv3");
+ failf(data, "wolfSSL does not support SSLv3");
return CURLE_NOT_BUILT_IN;
#endif
break;
case CURL_SSLVERSION_SSLv2:
- failf(data, "CyaSSL does not support SSLv2");
+ failf(data, "wolfSSL does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
default:
failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@@ -237,13 +215,12 @@ cyassl_connect_step1(struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
-#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
- /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever
- minimum version of TLS was built in and at least TLS 1.0. For later library
- versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so
- we have this short circuit evaluation to find the minimum supported TLS
- version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
- because only the former will work before the user's CTX callback is called.
+#if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
+ /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is
+ * whatever minimum version of TLS was built in and at least TLS 1.0. For
+ * later library versions that could change (eg TLS 1.0 built in but
+ * defaults to TLS 1.1) so we have this short circuit evaluation to find
+ * the minimum supported TLS version.
*/
if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
(wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
@@ -347,7 +324,7 @@ cyassl_connect_step1(struct connectdata *conn,
#ifdef ENABLE_IPV6
(0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
#endif
- (CyaSSL_CTX_UseSNI(BACKEND->ctx, CYASSL_SNI_HOST_NAME, hostname,
+ (wolfSSL_CTX_UseSNI(BACKEND->ctx, WOLFSSL_SNI_HOST_NAME, hostname,
(unsigned short)hostname_len) != 1)) {
infof(data, "WARNING: failed to configure server name indication (SNI) "
"TLS extension\n");
@@ -357,9 +334,8 @@ cyassl_connect_step1(struct connectdata *conn,
/* give application a chance to interfere with SSL set up. */
if(data->set.ssl.fsslctx) {
- CURLcode result = CURLE_OK;
- result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
- data->set.ssl.fsslctxp);
+ CURLcode result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
+ data->set.ssl.fsslctxp);
if(result) {
failf(data, "error signaled by ssl ctx callback");
return result;
@@ -367,7 +343,7 @@ cyassl_connect_step1(struct connectdata *conn,
}
#ifdef NO_FILESYSTEM
else if(SSL_CONN_CONFIG(verifypeer)) {
- failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
+ failf(data, "SSL: Certificates can't be loaded because wolfSSL was built"
" with \"no filesystem\". Either disable peer verification"
" (insecure) or if you are building an application with libcurl you"
" can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
@@ -419,11 +395,11 @@ cyassl_connect_step1(struct connectdata *conn,
if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
/* we got a session id, use it! */
if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
- char error_buffer[CYASSL_MAX_ERROR_SZ];
+ char error_buffer[WOLFSSL_MAX_ERROR_SZ];
Curl_ssl_sessionid_unlock(conn);
failf(data, "SSL: SSL_set_session failed: %s",
ERR_error_string(SSL_get_error(BACKEND->handle, 0),
- error_buffer));
+ error_buffer));
return CURLE_SSL_CONNECT_ERROR;
}
/* Informational message */
@@ -444,7 +420,7 @@ cyassl_connect_step1(struct connectdata *conn,
static CURLcode
-cyassl_connect_step2(struct connectdata *conn,
+wolfssl_connect_step2(struct connectdata *conn,
int sockindex)
{
int ret = -1;
@@ -458,19 +434,19 @@ cyassl_connect_step2(struct connectdata *conn,
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
- conn->recv[sockindex] = cyassl_recv;
- conn->send[sockindex] = cyassl_send;
+ conn->recv[sockindex] = wolfssl_recv;
+ conn->send[sockindex] = wolfssl_send;
/* Enable RFC2818 checks */
if(SSL_CONN_CONFIG(verifyhost)) {
- ret = CyaSSL_check_domain_name(BACKEND->handle, hostname);
+ ret = wolfSSL_check_domain_name(BACKEND->handle, hostname);
if(ret == SSL_FAILURE)
return CURLE_OUT_OF_MEMORY;
}
ret = SSL_connect(BACKEND->handle);
if(ret != 1) {
- char error_buffer[CYASSL_MAX_ERROR_SZ];
+ char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int detail = SSL_get_error(BACKEND->handle, ret);
if(SSL_ERROR_WANT_READ == detail) {
@@ -490,11 +466,12 @@ cyassl_connect_step2(struct connectdata *conn,
dispname);
return CURLE_PEER_FAILED_VERIFICATION;
#else
- /* When the CyaSSL_check_domain_name() is used and you desire to continue
- * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0',
- * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
- * way to do this is currently to switch the CyaSSL_check_domain_name()
- * in and out based on the 'conn->ssl_config.verifyhost' value. */
+ /* When the wolfssl_check_domain_name() is used and you desire to
+ * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost
+ * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
+ * error. The only way to do this is currently to switch the
+ * Wolfssl_check_domain_name() in and out based on the
+ * 'conn->ssl_config.verifyhost' value. */
if(SSL_CONN_CONFIG(verifyhost)) {
failf(data,
"\tsubject alt name(s) or common name do not match \"%s\"\n",
@@ -509,7 +486,7 @@ cyassl_connect_step2(struct connectdata *conn,
}
#endif
}
-#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
+#if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
else if(ASN_NO_SIGNER_E == detail) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "\tCA signer not available for verification\n");
@@ -545,7 +522,7 @@ cyassl_connect_step2(struct connectdata *conn,
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
}
- x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len);
+ x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
if(!x509_der) {
failf(data, "SSL: failed retrieving ASN.1 server certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -613,7 +590,7 @@ cyassl_connect_step2(struct connectdata *conn,
#endif /* HAVE_ALPN */
connssl->connecting_state = ssl_connect_3;
-#if (LIBCYASSL_VERSION_HEX >= 0x03009010)
+#if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
infof(data, "SSL connection using %s / %s\n",
wolfSSL_get_version(BACKEND->handle),
wolfSSL_get_cipher_name(BACKEND->handle));
@@ -626,7 +603,7 @@ cyassl_connect_step2(struct connectdata *conn,
static CURLcode
-cyassl_connect_step3(struct connectdata *conn,
+wolfssl_connect_step3(struct connectdata *conn,
int sockindex)
{
CURLcode result = CURLE_OK;
@@ -671,14 +648,14 @@ cyassl_connect_step3(struct connectdata *conn,
}
-static ssize_t cyassl_send(struct connectdata *conn,
+static ssize_t wolfssl_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- char error_buffer[CYASSL_MAX_ERROR_SZ];
+ char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
int rc = SSL_write(BACKEND->handle, mem, memlen);
@@ -702,7 +679,7 @@ static ssize_t cyassl_send(struct connectdata *conn,
return rc;
}
-static void Curl_cyassl_close(struct connectdata *conn, int sockindex)
+static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -717,14 +694,14 @@ static void Curl_cyassl_close(struct connectdata *conn, int sockindex)
}
}
-static ssize_t cyassl_recv(struct connectdata *conn,
+static ssize_t wolfssl_recv(struct connectdata *conn,
int num,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
struct ssl_connect_data *connssl = &conn->ssl[num];
- char error_buffer[CYASSL_MAX_ERROR_SZ];
+ char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
int nread = SSL_read(BACKEND->handle, buf, buffsize);
@@ -751,40 +728,36 @@ static ssize_t cyassl_recv(struct connectdata *conn,
}
-static void Curl_cyassl_session_free(void *ptr)
+static void Curl_wolfssl_session_free(void *ptr)
{
(void)ptr;
- /* CyaSSL reuses sessions on own, no free */
+ /* wolfSSL reuses sessions on own, no free */
}
-static size_t Curl_cyassl_version(char *buffer, size_t size)
+static size_t Curl_wolfssl_version(char *buffer, size_t size)
{
-#if LIBCYASSL_VERSION_HEX >= 0x03006000
+#if LIBWOLFSSL_VERSION_HEX >= 0x03006000
return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
#elif defined(WOLFSSL_VERSION)
return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
-#elif defined(CYASSL_VERSION)
- return msnprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
-#else
- return msnprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
#endif
}
-static int Curl_cyassl_init(void)
+static int Curl_wolfssl_init(void)
{
- return (CyaSSL_Init() == SSL_SUCCESS);
+ return (wolfSSL_Init() == SSL_SUCCESS);
}
-static void Curl_cyassl_cleanup(void)
+static void Curl_wolfssl_cleanup(void)
{
- CyaSSL_Cleanup();
+ wolfSSL_Cleanup();
}
-static bool Curl_cyassl_data_pending(const struct connectdata* conn,
+static bool Curl_wolfssl_data_pending(const struct connectdata* conn,
int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
@@ -799,7 +772,7 @@ static bool Curl_cyassl_data_pending(const struct connectdata* conn,
* This function is called to shut down the SSL layer but keep the
* socket open (CCC - Clear Command Channel)
*/
-static int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)
{
int retval = 0;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -813,7 +786,7 @@ static int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
static CURLcode
-cyassl_connect_common(struct connectdata *conn,
+wolfssl_connect_common(struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
@@ -841,7 +814,7 @@ cyassl_connect_common(struct connectdata *conn,
return CURLE_OPERATION_TIMEDOUT;
}
- result = cyassl_connect_step1(conn, sockindex);
+ result = wolfssl_connect_step1(conn, sockindex);
if(result)
return result;
}
@@ -896,7 +869,7 @@ cyassl_connect_common(struct connectdata *conn,
* ensuring that a client using select() or epoll() will always
* have a valid fdset to wait on.
*/
- result = cyassl_connect_step2(conn, sockindex);
+ result = wolfssl_connect_step2(conn, sockindex);
if(result || (nonblocking &&
(ssl_connect_2 == connssl->connecting_state ||
ssl_connect_2_reading == connssl->connecting_state ||
@@ -905,15 +878,15 @@ cyassl_connect_common(struct connectdata *conn,
} /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = cyassl_connect_step3(conn, sockindex);
+ result = wolfssl_connect_step3(conn, sockindex);
if(result)
return result;
}
if(ssl_connect_done == connssl->connecting_state) {
connssl->state = ssl_connection_complete;
- conn->recv[sockindex] = cyassl_recv;
- conn->send[sockindex] = cyassl_send;
+ conn->recv[sockindex] = wolfssl_recv;
+ conn->send[sockindex] = wolfssl_send;
*done = TRUE;
}
else
@@ -926,19 +899,19 @@ cyassl_connect_common(struct connectdata *conn,
}
-static CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn,
int sockindex, bool *done)
{
- return cyassl_connect_common(conn, sockindex, TRUE, done);
+ return wolfssl_connect_common(conn, sockindex, TRUE, done);
}
-static CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
bool done = FALSE;
- result = cyassl_connect_common(conn, sockindex, FALSE, &done);
+ result = wolfssl_connect_common(conn, sockindex, FALSE, &done);
if(result)
return result;
@@ -947,43 +920,43 @@ static CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-static CURLcode Curl_cyassl_random(struct Curl_easy *data,
+static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
unsigned char *entropy, size_t length)
{
- RNG rng;
+ WC_RNG rng;
(void)data;
- if(InitRng(&rng))
+ if(wc_InitRng(&rng))
return CURLE_FAILED_INIT;
if(length > UINT_MAX)
return CURLE_FAILED_INIT;
- if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
+ if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
return CURLE_FAILED_INIT;
- if(FreeRng(&rng))
+ if(wc_FreeRng(&rng))
return CURLE_FAILED_INIT;
return CURLE_OK;
}
-static CURLcode Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
- size_t tmplen,
- unsigned char *sha256sum /* output */,
- size_t unused)
+static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum /* output */,
+ size_t unused)
{
- Sha256 SHA256pw;
+ wc_Sha256 SHA256pw;
(void)unused;
- InitSha256(&SHA256pw);
- Sha256Update(&SHA256pw, tmp, (word32)tmplen);
- Sha256Final(&SHA256pw, sha256sum);
+ wc_InitSha256(&SHA256pw);
+ wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
+ wc_Sha256Final(&SHA256pw, sha256sum);
return CURLE_OK;
}
-static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
+static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl,
CURLINFO info UNUSED_PARAM)
{
(void)info;
return BACKEND->handle;
}
-const struct Curl_ssl Curl_ssl_cyassl = {
+const struct Curl_ssl Curl_ssl_wolfssl = {
{ CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
#ifdef KEEP_PEER_CERT
@@ -993,26 +966,26 @@ const struct Curl_ssl Curl_ssl_cyassl = {
sizeof(struct ssl_backend_data),
- Curl_cyassl_init, /* init */
- Curl_cyassl_cleanup, /* cleanup */
- Curl_cyassl_version, /* version */
+ Curl_wolfssl_init, /* init */
+ Curl_wolfssl_cleanup, /* cleanup */
+ Curl_wolfssl_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_cyassl_shutdown, /* shutdown */
- Curl_cyassl_data_pending, /* data_pending */
- Curl_cyassl_random, /* random */
+ Curl_wolfssl_shutdown, /* shutdown */
+ Curl_wolfssl_data_pending, /* data_pending */
+ Curl_wolfssl_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
- Curl_cyassl_connect, /* connect */
- Curl_cyassl_connect_nonblocking, /* connect_nonblocking */
- Curl_cyassl_get_internals, /* get_internals */
- Curl_cyassl_close, /* close_one */
+ Curl_wolfssl_connect, /* connect */
+ Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */
+ Curl_wolfssl_get_internals, /* get_internals */
+ Curl_wolfssl_close, /* close_one */
Curl_none_close_all, /* close_all */
- Curl_cyassl_session_free, /* session_free */
+ Curl_wolfssl_session_free, /* session_free */
Curl_none_set_engine, /* set_engine */
Curl_none_set_engine_default, /* set_engine_default */
Curl_none_engines_list, /* engines_list */
Curl_none_false_start, /* false_start */
Curl_none_md5sum, /* md5sum */
- Curl_cyassl_sha256sum /* sha256sum */
+ Curl_wolfssl_sha256sum /* sha256sum */
};
#endif
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.h b/Utilities/cmcurl/lib/vtls/wolfssl.h
index 01e11cc..2b9673c 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.h
+++ b/Utilities/cmcurl/lib/vtls/wolfssl.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_CYASSL_H
-#define HEADER_CURL_CYASSL_H
+#ifndef HEADER_CURL_WOLFSSL_H
+#define HEADER_CURL_WOLFSSL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, 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
@@ -23,9 +23,9 @@
***************************************************************************/
#include "curl_setup.h"
-#ifdef USE_CYASSL
+#ifdef USE_WOLFSSL
-extern const struct Curl_ssl Curl_ssl_cyassl;
+extern const struct Curl_ssl Curl_ssl_wolfssl;
-#endif /* USE_CYASSL */
-#endif /* HEADER_CURL_CYASSL_H */
+#endif /* USE_WOLFSSL */
+#endif /* HEADER_CURL_WOLFSSL_H */