summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/vtls
diff options
context:
space:
mode:
authordartraiden <wowemuh@gmail.com>2021-11-16 22:24:39 +0300
committerdartraiden <wowemuh@gmail.com>2021-11-16 22:26:13 +0300
commit53a0928794b1b7f3e9bbb7c09d939d32378379d6 (patch)
tree00b4b965972b4133dd56fcaa1e80b5c330687837 /libs/libcurl/src/vtls
parentaa3402bb65378066b00862547ebe7b6ce5c821c6 (diff)
libcurl: update to 7.80.0
Diffstat (limited to 'libs/libcurl/src/vtls')
-rw-r--r--libs/libcurl/src/vtls/bearssl.c88
-rw-r--r--libs/libcurl/src/vtls/gskit.c26
-rw-r--r--libs/libcurl/src/vtls/gtls.c45
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c97
-rw-r--r--libs/libcurl/src/vtls/mbedtls_threadlock.c27
-rw-r--r--libs/libcurl/src/vtls/mesalink.c2
-rw-r--r--libs/libcurl/src/vtls/nss.c7
-rw-r--r--libs/libcurl/src/vtls/openssl.c183
-rw-r--r--libs/libcurl/src/vtls/rustls.c10
-rw-r--r--libs/libcurl/src/vtls/schannel.c68
-rw-r--r--libs/libcurl/src/vtls/schannel_verify.c2
-rw-r--r--libs/libcurl/src/vtls/sectransp.c130
-rw-r--r--libs/libcurl/src/vtls/vtls.c10
-rw-r--r--libs/libcurl/src/vtls/vtls.h3
-rw-r--r--libs/libcurl/src/vtls/wolfssl.c90
15 files changed, 518 insertions, 270 deletions
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c
index cbbb3b5deb..9b772d064d 100644
--- a/libs/libcurl/src/vtls/bearssl.c
+++ b/libs/libcurl/src/vtls/bearssl.c
@@ -68,6 +68,14 @@ struct cafile_parser {
size_t dn_len;
};
+#define CAFILE_SOURCE_PATH 1
+#define CAFILE_SOURCE_BLOB 2
+struct cafile_source {
+ const int type;
+ const char * const data;
+ const size_t len;
+};
+
static void append_dn(void *ctx, const void *buf, size_t len)
{
struct cafile_parser *ca = ctx;
@@ -90,7 +98,8 @@ static void x509_push(void *ctx, const void *buf, size_t len)
br_x509_decoder_push(&ca->xc, buf, len);
}
-static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
+static CURLcode load_cafile(struct cafile_source *source,
+ br_x509_trust_anchor **anchors,
size_t *anchors_len)
{
struct cafile_parser ca;
@@ -100,13 +109,22 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
br_x509_trust_anchor *new_anchors;
size_t new_anchors_len;
br_x509_pkey *pkey;
- FILE *fp;
- unsigned char buf[BUFSIZ], *p;
+ FILE *fp = 0;
+ unsigned char buf[BUFSIZ];
+ const unsigned char *p;
const char *name;
size_t n, i, pushed;
- fp = fopen(path, "rb");
- if(!fp)
+ DEBUGASSERT(source->type == CAFILE_SOURCE_PATH
+ || source->type == CAFILE_SOURCE_BLOB);
+
+ if(source->type == CAFILE_SOURCE_PATH) {
+ fp = fopen(source->data, "rb");
+ if(!fp)
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+
+ if(source->type == CAFILE_SOURCE_BLOB && source->len > (size_t)INT_MAX)
return CURLE_SSL_CACERT_BADFILE;
ca.err = CURLE_OK;
@@ -115,11 +133,17 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
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;
+ do {
+ if(source->type == CAFILE_SOURCE_PATH) {
+ n = fread(buf, 1, sizeof(buf), fp);
+ if(n == 0)
+ break;
+ p = buf;
+ }
+ else if(source->type == CAFILE_SOURCE_BLOB) {
+ n = source->len;
+ p = (unsigned char *) source->data;
+ }
while(n) {
pushed = br_pem_decoder_push(&pc, p, n);
if(ca.err)
@@ -211,12 +235,13 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
goto fail;
}
}
- }
- if(ferror(fp))
+ } while(source->type != CAFILE_SOURCE_BLOB);
+ if(fp && ferror(fp))
ca.err = CURLE_READ_ERROR;
fail:
- fclose(fp);
+ if(fp)
+ fclose(fp);
if(ca.err == CURLE_OK) {
*anchors = ca.anchors;
*anchors_len = ca.anchors_len;
@@ -299,7 +324,10 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
- const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const char * const ssl_cafile =
+ /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
+ (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile));
const char *hostname = SSL_HOST_NAME();
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
@@ -340,8 +368,30 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
+ if(ca_info_blob) {
+ struct cafile_source source = {
+ CAFILE_SOURCE_BLOB,
+ ca_info_blob->data,
+ ca_info_blob->len,
+ };
+ ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
+ if(ret != CURLE_OK) {
+ if(verifypeer) {
+ failf(data, "error importing CA certificate blob");
+ return ret;
+ }
+ /* Only warn if no certificate verification is required. */
+ infof(data, "error importing CA certificate blob, continuing anyway");
+ }
+ }
+
if(ssl_cafile) {
- ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
+ struct cafile_source source = {
+ CAFILE_SOURCE_PATH,
+ ssl_cafile,
+ 0,
+ };
+ ret = load_cafile(&source, &backend->anchors, &backend->anchors_len);
if(ret != CURLE_OK) {
if(verifypeer) {
failf(data, "error setting certificate verify locations."
@@ -558,6 +608,7 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
+ bool added = FALSE;
void *oldsession;
br_ssl_session_parameters *session;
@@ -573,10 +624,11 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data,
Curl_ssl_delsessionid(data, oldsession);
ret = Curl_ssl_addsessionid(data, conn,
SSL_IS_PROXY() ? TRUE : FALSE,
- session, 0, sockindex);
+ session, 0, sockindex, &added);
Curl_ssl_sessionid_unlock(data);
- if(ret) {
+ if(!added)
free(session);
+ if(ret) {
return CURLE_OUT_OF_MEMORY;
}
}
@@ -841,7 +893,7 @@ static CURLcode bearssl_sha256sum(const unsigned char *input,
const struct Curl_ssl Curl_ssl_bearssl = {
{ CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */
- 0,
+ SSLSUPP_CAINFO_BLOB,
sizeof(struct ssl_backend_data),
Curl_none_init, /* init */
diff --git a/libs/libcurl/src/vtls/gskit.c b/libs/libcurl/src/vtls/gskit.c
index af8fc92b27..e451f6aebe 100644
--- a/libs/libcurl/src/vtls/gskit.c
+++ b/libs/libcurl/src/vtls/gskit.c
@@ -180,6 +180,7 @@ static bool is_separator(char c)
static CURLcode gskit_status(struct Curl_easy *data, int rc,
const char *procname, CURLcode defcode)
{
+ char buffer[STRERROR_LEN];
/* Process GSKit status and map it to a CURLcode. */
switch(rc) {
case GSK_OK:
@@ -208,7 +209,8 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
case ENOMEM:
return CURLE_OUT_OF_MEMORY;
default:
- failf(data, "%s I/O error: %s", procname, strerror(errno));
+ failf(data, "%s I/O error: %s", procname,
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
}
break;
@@ -223,13 +225,15 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_enum(h, id, value);
switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
+ failf(data, "gsk_attribute_set_enum() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
case GSK_ATTRIBUTE_INVALID_ID:
if(unsupported_ok)
@@ -245,13 +249,15 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+ failf(data, "gsk_attribute_set_buffer() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
case GSK_ATTRIBUTE_INVALID_ID:
if(unsupported_ok)
@@ -267,6 +273,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
static CURLcode set_numeric(struct Curl_easy *data,
gsk_handle h, GSK_NUM_ID id, int value)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_numeric_value(h, id, value);
switch(rc) {
@@ -274,7 +281,7 @@ static CURLcode set_numeric(struct Curl_easy *data,
return CURLE_OK;
case GSK_ERROR_IO:
failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
- strerror(errno));
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
default:
failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
@@ -287,13 +294,15 @@ static CURLcode set_numeric(struct Curl_easy *data,
static CURLcode set_callback(struct Curl_easy *data,
gsk_handle h, GSK_CALLBACK_ID id, void *info)
{
+ char buffer[STRERROR_LEN];
int rc = gsk_attribute_set_callback(h, id, info);
switch(rc) {
case GSK_OK:
return CURLE_OK;
case GSK_ERROR_IO:
- failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
+ failf(data, "gsk_attribute_set_callback() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
break;
default:
failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
@@ -966,7 +975,9 @@ static CURLcode gskit_connect_step2(struct Curl_easy *data,
continue; /* Retry. */
}
if(errno != ETIME) {
- failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
+ char buffer[STRERROR_LEN];
+ failf(data, "QsoWaitForIOCompletion() I/O error: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
cancel_async_handshake(conn, sockindex);
close_async_handshake(connssl);
return CURLE_SSL_CONNECT_ERROR;
@@ -1229,7 +1240,8 @@ static int gskit_shutdown(struct Curl_easy *data,
nread = read(conn->sock[sockindex], buf, sizeof(buf));
if(nread < 0) {
- failf(data, "read: %s", strerror(errno));
+ char buffer[STRERROR_LEN];
+ failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
rc = -1;
}
diff --git a/libs/libcurl/src/vtls/gtls.c b/libs/libcurl/src/vtls/gtls.c
index 1b145d8ebb..2053fd439d 100644
--- a/libs/libcurl/src/vtls/gtls.c
+++ b/libs/libcurl/src/vtls/gtls.c
@@ -404,6 +404,7 @@ gtls_connect_step1(struct Curl_easy *data,
const char * const hostname = SSL_HOST_NAME();
long * const certverifyresult = &SSL_SET_OPTION_LVALUE(certverifyresult);
const char *tls13support;
+ CURLcode result;
if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -557,31 +558,25 @@ gtls_connect_step1(struct Curl_easy *data,
/* Ensure +SRP comes at the *end* of all relevant strings so that it can be
* removed if a run-time error indicates that SRP is not supported by this
* GnuTLS version */
- switch(SSL_CONN_CONFIG(version)) {
- case CURL_SSLVERSION_TLSv1_3:
- if(!tls13support) {
- failf(data, "This GnuTLS installation does not support TLS 1.3");
- return CURLE_SSL_CONNECT_ERROR;
- }
- /* FALLTHROUGH */
- case CURL_SSLVERSION_DEFAULT:
- case CURL_SSLVERSION_TLSv1:
- case CURL_SSLVERSION_TLSv1_0:
- case CURL_SSLVERSION_TLSv1_1:
- case CURL_SSLVERSION_TLSv1_2: {
- CURLcode result = set_ssl_version_min_max(data, &prioritylist,
- tls13support);
- if(result)
- return result;
- break;
- }
- case CURL_SSLVERSION_SSLv2:
- case CURL_SSLVERSION_SSLv3:
- default:
- failf(data, "GnuTLS does not support SSLv2 or SSLv3");
+
+ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2 ||
+ SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3) {
+ failf(data, "GnuTLS does not support SSLv2 or SSLv3");
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_TLSv1_3) {
+ if(!tls13support) {
+ failf(data, "This GnuTLS installation does not support TLS 1.3");
return CURLE_SSL_CONNECT_ERROR;
+ }
}
+ /* At this point we know we have a supported TLS version, so set it */
+ result = set_ssl_version_min_max(data, &prioritylist, tls13support);
+ if(result)
+ return result;
+
#ifdef HAVE_GNUTLS_SRP
/* Only add SRP to the cipher list if SRP is requested. Otherwise
* GnuTLS will disable TLS 1.3 support. */
@@ -1287,6 +1282,7 @@ gtls_connect_step3(struct Curl_easy *data,
if(connect_sessionid) {
bool incache;
+ bool added = FALSE;
void *ssl_sessionid;
/* extract session ID to the allocated buffer */
@@ -1306,10 +1302,11 @@ gtls_connect_step3(struct Curl_easy *data,
result = Curl_ssl_addsessionid(data, conn,
SSL_IS_PROXY() ? TRUE : FALSE,
connect_sessionid, connect_idsize,
- sockindex);
+ sockindex, &added);
Curl_ssl_sessionid_unlock(data);
- if(result) {
+ if(!added)
free(connect_sessionid);
+ if(result) {
result = CURLE_OUT_OF_MEMORY;
}
}
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index e986bea82d..08c79e1624 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -41,7 +41,9 @@
#include <mbedtls/net.h>
#endif
#include <mbedtls/ssl.h>
+#if MBEDTLS_VERSION_NUMBER < 0x03000000
#include <mbedtls/certs.h>
+#endif
#include <mbedtls/x509.h>
#include <mbedtls/error.h>
@@ -183,6 +185,17 @@ static Curl_send mbed_send;
static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
{
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ switch(version) {
+ case CURL_SSLVERSION_TLSv1_0:
+ case CURL_SSLVERSION_TLSv1_1:
+ case CURL_SSLVERSION_TLSv1_2:
+ *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
+ return CURLE_OK;
+ case CURL_SSLVERSION_TLSv1_3:
+ break;
+ }
+#else
switch(version) {
case CURL_SSLVERSION_TLSv1_0:
*mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
@@ -196,6 +209,8 @@ static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
case CURL_SSLVERSION_TLSv1_3:
break;
}
+#endif
+
return CURLE_SSL_CONNECT_ERROR;
}
@@ -205,8 +220,13 @@ set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
{
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3;
+ int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3;
+#else
int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
+#endif
long ssl_version = SSL_CONN_CONFIG(version);
long ssl_version_max = SSL_CONN_CONFIG(version_max);
CURLcode result = CURLE_OK;
@@ -257,7 +277,9 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
const char * const hostname = SSL_HOST_NAME();
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
const long int port = SSL_HOST_PORT();
+#endif
int ret = -1;
char errorbuf[128];
@@ -354,8 +376,15 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
if(SSL_SET_OPTION(key) || SSL_SET_OPTION(key_blob)) {
if(SSL_SET_OPTION(key)) {
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
+ SSL_SET_OPTION(key_passwd),
+ mbedtls_ctr_drbg_random,
+ &backend->ctr_drbg);
+#else
ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
SSL_SET_OPTION(key_passwd));
+#endif
if(ret) {
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -369,9 +398,17 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
const unsigned char *key_data =
(const unsigned char *)ssl_key_blob->data;
const char *passwd = SSL_SET_OPTION(key_passwd);
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
+ (const unsigned char *)passwd,
+ passwd ? strlen(passwd) : 0,
+ mbedtls_ctr_drbg_random,
+ &backend->ctr_drbg);
+#else
ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len,
(const unsigned char *)passwd,
passwd ? strlen(passwd) : 0);
+#endif
if(ret) {
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -426,10 +463,12 @@ mbed_connect_step1(struct Curl_easy *data, struct connectdata *conn,
switch(SSL_CONN_CONFIG(version)) {
case CURL_SSLVERSION_DEFAULT:
case CURL_SSLVERSION_TLSv1:
+#if MBEDTLS_VERSION_NUMBER < 0x03000000
mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_1);
infof(data, "mbedTLS: Set min SSL version to TLS 1.0");
break;
+#endif
case CURL_SSLVERSION_TLSv1_0:
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
@@ -629,10 +668,15 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(pinnedpubkey) {
int size;
CURLcode result;
- mbedtls_x509_crt *p;
- unsigned char pubkey[PUB_DER_MAX_BYTES];
+ mbedtls_x509_crt *p = NULL;
+ unsigned char *pubkey = NULL;
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) ||
+ !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) {
+#else
if(!peercert || !peercert->raw.p || !peercert->raw.len) {
+#endif
failf(data, "Failed due to missing peer certificate");
return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
}
@@ -642,39 +686,54 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(!p)
return CURLE_OUT_OF_MEMORY;
+ pubkey = malloc(PUB_DER_MAX_BYTES);
+
+ if(!pubkey) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto pinnedpubkey_error;
+ }
+
mbedtls_x509_crt_init(p);
/* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
needs a non-const key, for now.
https://github.com/ARMmbed/mbedtls/issues/396 */
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ if(mbedtls_x509_crt_parse_der(p,
+ peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
+ peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) {
+#else
if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
+#endif
failf(data, "Failed copying peer certificate");
- mbedtls_x509_crt_free(p);
- free(p);
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ goto pinnedpubkey_error;
}
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey,
+ PUB_DER_MAX_BYTES);
+#else
size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
+#endif
if(size <= 0) {
failf(data, "Failed copying public key from peer certificate");
- mbedtls_x509_crt_free(p);
- free(p);
- return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+ goto pinnedpubkey_error;
}
/* mbedtls_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);
+ pinnedpubkey_error:
+ mbedtls_x509_crt_free(p);
+ free(p);
+ free(pubkey);
if(result) {
- mbedtls_x509_crt_free(p);
- free(p);
return result;
}
-
- mbedtls_x509_crt_free(p);
- free(p);
}
#ifdef HAS_ALPN
@@ -725,6 +784,7 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
mbedtls_ssl_session *our_ssl_sessionid;
void *old_ssl_sessionid = NULL;
bool isproxy = SSL_IS_PROXY() ? TRUE : FALSE;
+ bool added = FALSE;
our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
if(!our_ssl_sessionid)
@@ -748,11 +808,13 @@ mbed_connect_step3(struct Curl_easy *data, struct connectdata *conn,
Curl_ssl_delsessionid(data, old_ssl_sessionid);
retcode = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
- 0, sockindex);
+ 0, sockindex, &added);
Curl_ssl_sessionid_unlock(data);
- if(retcode) {
+ if(!added) {
mbedtls_ssl_session_free(our_ssl_sessionid);
free(our_ssl_sessionid);
+ }
+ if(retcode) {
failf(data, "failed to store ssl session");
return retcode;
}
@@ -1064,12 +1126,17 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input,
unsigned char *sha256sum,
size_t sha256len UNUSED_PARAM)
{
+ /* TODO: explain this for different mbedtls 2.x vs 3 version */
(void)sha256len;
#if MBEDTLS_VERSION_NUMBER < 0x02070000
mbedtls_sha256(input, inputlen, sha256sum, 0);
#else
/* returns 0 on success, otherwise failure */
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+ if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0)
+#else
if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
+#endif
return CURLE_BAD_FUNCTION_ARGUMENT;
#endif
return CURLE_OK;
diff --git a/libs/libcurl/src/vtls/mbedtls_threadlock.c b/libs/libcurl/src/vtls/mbedtls_threadlock.c
index 473f5171e2..751755c239 100644
--- a/libs/libcurl/src/vtls/mbedtls_threadlock.c
+++ b/libs/libcurl/src/vtls/mbedtls_threadlock.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2021, 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
@@ -55,10 +55,8 @@ int Curl_mbedtlsthreadlock_thread_setup(void)
return 0; /* error, no number of threads defined */
for(i = 0; i < NUMT; i++) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_init(&mutex_buf[i], NULL);
- if(ret)
+ if(pthread_mutex_init(&mutex_buf[i], NULL))
return 0; /* pthread_mutex_init failed */
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
mutex_buf[i] = CreateMutex(0, FALSE, 0);
@@ -78,14 +76,11 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void)
return 0; /* error, no threads locks defined */
for(i = 0; i < NUMT; i++) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_destroy(&mutex_buf[i]);
- if(ret)
+ if(pthread_mutex_destroy(&mutex_buf[i]))
return 0; /* pthread_mutex_destroy failed */
#elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
- ret = CloseHandle(mutex_buf[i]);
- if(!ret)
+ if(!CloseHandle(mutex_buf[i]))
return 0; /* CloseHandle failed */
#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
}
@@ -98,17 +93,14 @@ int Curl_mbedtlsthreadlock_thread_cleanup(void)
int Curl_mbedtlsthreadlock_lock_function(int n)
{
if(n < NUMT) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_lock(&mutex_buf[n]);
- if(ret) {
+ if(pthread_mutex_lock(&mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"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) {
+ if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_lock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
@@ -121,17 +113,14 @@ int Curl_mbedtlsthreadlock_lock_function(int n)
int Curl_mbedtlsthreadlock_unlock_function(int n)
{
if(n < NUMT) {
- int ret;
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
- ret = pthread_mutex_unlock(&mutex_buf[n]);
- if(ret) {
+ if(pthread_mutex_unlock(&mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"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) {
+ if(!ReleaseMutex(mutex_buf[n])) {
DEBUGF(fprintf(stderr,
"Error: mbedtlsthreadlock_unlock_function failed\n"));
return 0; /* pthread_mutex_lock failed */
diff --git a/libs/libcurl/src/vtls/mesalink.c b/libs/libcurl/src/vtls/mesalink.c
index 3db9184f79..0a1dea3ac0 100644
--- a/libs/libcurl/src/vtls/mesalink.c
+++ b/libs/libcurl/src/vtls/mesalink.c
@@ -365,7 +365,7 @@ mesalink_connect_step3(struct connectdata *conn, int sockindex)
if(!incache) {
result =
Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid, 0,
- sockindex);
+ sockindex, NULL);
if(result) {
Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
diff --git a/libs/libcurl/src/vtls/nss.c b/libs/libcurl/src/vtls/nss.c
index cf657895f6..1897b9ab1d 100644
--- a/libs/libcurl/src/vtls/nss.c
+++ b/libs/libcurl/src/vtls/nss.c
@@ -955,7 +955,7 @@ static void display_cert_info(struct Curl_easy *data,
subject = CERT_NameToAscii(&cert->subject);
issuer = CERT_NameToAscii(&cert->issuer);
common_name = CERT_GetCommonName(&cert->subject);
- infof(data, "subject: %s\n", subject);
+ infof(data, "subject: %s", subject);
CERT_GetCertTimes(cert, &notBefore, &notAfter);
PR_ExplodeTime(notBefore, PR_GMTParameters, &printableTime);
@@ -2250,10 +2250,11 @@ static CURLcode nss_connect_common(struct Curl_easy *data,
case CURLE_OK:
break;
case CURLE_AGAIN:
+ /* CURLE_AGAIN in non-blocking mode is not an error */
if(!blocking)
- /* CURLE_AGAIN in non-blocking mode is not an error */
return CURLE_OK;
- /* FALLTHROUGH */
+ else
+ return result;
default:
return result;
}
diff --git a/libs/libcurl/src/vtls/openssl.c b/libs/libcurl/src/vtls/openssl.c
index 8af23b783a..a1baef9c3f 100644
--- a/libs/libcurl/src/vtls/openssl.c
+++ b/libs/libcurl/src/vtls/openssl.c
@@ -194,7 +194,7 @@
!defined(OPENSSL_IS_BORINGSSL))
#define HAVE_SSL_CTX_SET_CIPHERSUITES
#define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
-/* SET_EC_CURVES available under the same preconditions: see
+/* SET_EC_CURVES is available under the same preconditions: see
* https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html
*/
#define HAVE_SSL_CTX_SET_EC_CURVES
@@ -209,8 +209,8 @@
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-/* up2date versions of OpenSSL maintain the default reasonably secure without
- * breaking compatibility, so it is better not to override the default by curl
+/* up2date versions of OpenSSL maintain reasonably secure defaults without
+ * breaking compatibility, so it is better not to override the defaults in curl
*/
#define DEFAULT_CIPHER_SELECTION NULL
#else
@@ -227,6 +227,10 @@
#endif
#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+#define HAVE_RANDOM_INIT_BY_DEFAULT 1
+#endif
+
struct ssl_backend_data {
struct Curl_easy *logger; /* transfer handle to pass trace logs to, only
using sockindex 0 */
@@ -435,18 +439,21 @@ static bool rand_enough(void)
static CURLcode ossl_seed(struct Curl_easy *data)
{
- char fname[256];
-
/* This might get called before it has been added to a multi handle */
if(data->multi && data->multi->ssl_seeded)
return CURLE_OK;
if(rand_enough()) {
- /* OpenSSL 1.1.0+ will return here */
+ /* OpenSSL 1.1.0+ should return here */
if(data->multi)
data->multi->ssl_seeded = TRUE;
return CURLE_OK;
}
+#ifdef HAVE_RANDOM_INIT_BY_DEFAULT
+ /* with OpenSSL 1.1.0+, a failed RAND_status is a showstopper */
+ failf(data, "Insufficient randomness");
+ return CURLE_SSL_CONNECT_ERROR;
+#else
#ifndef RANDOM_FILE
/* if RANDOM_FILE isn't defined, we only perform this if an option tells
@@ -507,19 +514,23 @@ static CURLcode ossl_seed(struct Curl_easy *data)
RAND_add(randb, (int)len, (double)len/2);
} while(!rand_enough());
- /* generates a default path for the random seed file */
- fname[0] = 0; /* blank it first */
- RAND_file_name(fname, sizeof(fname));
- if(fname[0]) {
- /* we got a file name to try */
- RAND_load_file(fname, RAND_LOAD_LENGTH);
- if(rand_enough())
- return CURLE_OK;
+ {
+ /* generates a default path for the random seed file */
+ char fname[256];
+ fname[0] = 0; /* blank it first */
+ RAND_file_name(fname, sizeof(fname));
+ if(fname[0]) {
+ /* we got a file name to try */
+ RAND_load_file(fname, RAND_LOAD_LENGTH);
+ if(rand_enough())
+ return CURLE_OK;
+ }
}
infof(data, "libcurl is now using a weak random seed!");
return (rand_enough() ? CURLE_OK :
- CURLE_SSL_CONNECT_ERROR /* confusing error code */);
+ CURLE_SSL_CONNECT_ERROR /* confusing error code */);
+#endif
}
#ifndef SSL_FILETYPE_ENGINE
@@ -1192,7 +1203,7 @@ static int ossl_init(void)
CONF_MFLAGS_IGNORE_MISSING_FILE);
#endif
- /* Lets get nice error messages */
+ /* Let's get nice error messages */
SSL_load_error_strings();
/* Init the global ciphers and digests */
@@ -1769,7 +1780,7 @@ static CURLcode verifyhost(struct Curl_easy *data, struct connectdata *conn,
/* we have the name entry and we will now convert this to a string
that we can use for comparison. Doing this we support BMPstring,
- UTF8 etc. */
+ UTF8, etc. */
if(i >= 0) {
ASN1_STRING *tmp =
@@ -2060,6 +2071,10 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
case SSL3_MT_ENCRYPTED_EXTENSIONS:
return "Encrypted Extensions";
#endif
+#ifdef SSL3_MT_SUPPLEMENTAL_DATA
+ case SSL3_MT_SUPPLEMENTAL_DATA:
+ return "Supplemental data";
+#endif
#ifdef SSL3_MT_END_OF_EARLY_DATA
case SSL3_MT_END_OF_EARLY_DATA:
return "End of early data";
@@ -2158,7 +2173,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
/* Log progress for interesting records only (like Handshake or Alert), skip
* all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0).
- * For TLS 1.3, skip notification of the decrypted inner Content Type.
+ * For TLS 1.3, skip notification of the decrypted inner Content-Type.
*/
if(ssl_ver
#ifdef SSL3_RT_INNER_CONTENT_TYPE
@@ -2299,7 +2314,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
long curl_ssl_version_min = SSL_CONN_CONFIG(version);
long curl_ssl_version_max;
- /* convert cURL min SSL version option to OpenSSL constant */
+ /* 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;
@@ -2329,7 +2344,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
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
+ So we skip this, and stay with the library default
*/
if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) {
if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) {
@@ -2340,7 +2355,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
/* ... then, TLS max version */
curl_ssl_version_max = SSL_CONN_CONFIG(version_max);
- /* convert cURL max SSL version option to OpenSSL constant */
+ /* 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;
@@ -2489,6 +2504,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
+ bool added = FALSE;
void *old_ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
@@ -2507,9 +2523,11 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
if(!incache) {
if(!Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
- 0 /* unknown size */, sockindex)) {
- /* the session has been put into the session cache */
- res = 1;
+ 0 /* unknown size */, sockindex, &added)) {
+ if(added) {
+ /* the session has been put into the session cache */
+ res = 1;
+ }
}
else
failf(data, "failed to store ssl session");
@@ -2523,7 +2541,7 @@ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
static CURLcode load_cacert_from_memory(SSL_CTX *ctx,
const struct curl_blob *ca_info_blob)
{
- /* these need freed at the end */
+ /* these need to be freed at the end */
BIO *cbio = NULL;
STACK_OF(X509_INFO) *inf = NULL;
@@ -2658,8 +2676,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CONNECT_ERROR;
}
- if(backend->ctx)
- SSL_CTX_free(backend->ctx);
+ DEBUGASSERT(!backend->ctx);
backend->ctx = SSL_CTX_new(req_method);
if(!backend->ctx) {
@@ -2681,23 +2698,23 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
}
#endif
- /* OpenSSL contains code to work-around lots of bugs and flaws in various
+ /* OpenSSL contains code to work around lots of bugs and flaws in various
SSL-implementations. SSL_CTX_set_options() is used to enabled those
work-arounds. The man page for this option states that SSL_OP_ALL enables
all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
enable the bug workaround options if compatibility with somewhat broken
implementations is desired."
- The "-no_ticket" option was introduced in Openssl0.9.8j. It's a flag to
+ The "-no_ticket" option was introduced in OpenSSL 0.9.8j. It's a flag to
disable "rfc4507bis session ticket support". rfc4507bis was later turned
into the proper RFC5077 it seems: https://tools.ietf.org/html/rfc5077
The enabled extension concerns the session management. I wonder how often
- libcurl stops a connection and then resumes a TLS session. also, sending
- the session data is some overhead. .I suggest that you just use your
+ libcurl stops a connection and then resumes a TLS session. Also, sending
+ the session data is some overhead. I suggest that you just use your
proposed patch (which explicitly disables TICKET).
- If someone writes an application with libcurl and openssl who wants to
+ If someone writes an application with libcurl and OpenSSL who wants to
enable the feature, one can do this in the SSL callback.
SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper
@@ -2733,7 +2750,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
- /* unless the user explicitly ask to allow the protocol vulnerability we
+ /* unless the user explicitly asks to allow the protocol vulnerability we
use the work-around */
if(!SSL_SET_OPTION(enable_beast))
ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
@@ -2933,7 +2950,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
NULL, cert_name, sizeof(cert_name))) {
strcpy(cert_name, "Unknown");
}
- infof(data, "SSL: Checking cert %s\"\n", cert_name);
+ infof(data, "SSL: Checking cert \"%s\"", cert_name);
#endif
encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
@@ -3030,9 +3047,9 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return result;
}
if(imported_native_ca)
- infof(data, "successfully imported windows ca store");
+ infof(data, "successfully imported Windows CA store");
else
- infof(data, "error importing windows ca store, continuing anyway");
+ infof(data, "error importing Windows CA store, continuing anyway");
}
#endif
@@ -3044,77 +3061,53 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
failf(data, "error importing CA certificate blob");
return result;
}
- /* Only warning if no certificate verification is required. */
+ /* Only warn if no certificate verification is required. */
infof(data, "error importing CA certificate blob, continuing anyway");
}
}
+ if(verifypeer && !imported_native_ca && (ssl_cafile || ssl_capath)) {
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
- {
- if(ssl_cafile) {
- if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
- if(verifypeer && !imported_native_ca) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate file: %s", ssl_cafile);
- return CURLE_SSL_CACERT_BADFILE;
- }
- /* Continue with a warning if no certificate verif is required. */
- infof(data, "error setting certificate file, continuing anyway");
- }
- infof(data, " CAfile: %s", ssl_cafile);
+ if(ssl_cafile &&
+ !SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate file: %s", ssl_cafile);
+ return CURLE_SSL_CACERT_BADFILE;
}
- if(ssl_capath) {
- if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
- if(verifypeer && !imported_native_ca) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate path: %s", ssl_capath);
- return CURLE_SSL_CACERT_BADFILE;
- }
- /* Continue with a warning if no certificate verif is required. */
- infof(data, "error setting certificate path, continuing anyway");
- }
- infof(data, " CApath: %s", ssl_capath);
+ if(ssl_capath &&
+ !SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate path: %s", ssl_capath);
+ return CURLE_SSL_CACERT_BADFILE;
}
- }
#else
- if(ssl_cafile || ssl_capath) {
- /* tell SSL where to find CA certificates that are used to verify
- the servers certificate. */
+ /* tell OpenSSL where to find CA certificates that are used to verify the
+ server's certificate. */
if(!SSL_CTX_load_verify_locations(backend->ctx, ssl_cafile, ssl_capath)) {
- if(verifypeer && !imported_native_ca) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate verify locations:"
- " CAfile: %s CApath: %s",
- ssl_cafile ? ssl_cafile : "none",
- ssl_capath ? ssl_capath : "none");
- return CURLE_SSL_CACERT_BADFILE;
- }
- /* Just continue with a warning if no strict certificate verification
- is required. */
- infof(data, "error setting certificate verify locations,"
- " continuing anyway:");
- }
- else {
- /* Everything is fine. */
- infof(data, "successfully set certificate verify locations:");
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate verify locations:"
+ " CAfile: %s CApath: %s",
+ ssl_cafile ? ssl_cafile : "none",
+ ssl_capath ? ssl_capath : "none");
+ return CURLE_SSL_CACERT_BADFILE;
}
+#endif
infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none");
infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none");
}
-#endif
#ifdef CURL_CA_FALLBACK
if(verifypeer &&
!ca_info_blob && !ssl_cafile && !ssl_capath && !imported_native_ca) {
/* verifying the peer without any CA certificates won't
- work so use openssl's built in default as fallback */
+ work so use openssl's built-in default as fallback */
SSL_CTX_set_default_verify_paths(backend->ctx);
}
#endif
if(ssl_crlfile) {
- /* tell SSL where to find CRL file that is used to check certificate
+ /* tell OpenSSL where to find CRL file that is used to check certificate
* revocation */
lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(backend->ctx),
X509_LOOKUP_file());
@@ -3124,7 +3117,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
return CURLE_SSL_CRL_BADFILE;
}
/* Everything is fine. */
- infof(data, "successfully load CRL file:");
+ infof(data, "successfully loaded CRL file:");
X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
@@ -3150,7 +3143,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
only, instead of needing the whole chain.
Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
- cannot do partial chains with CRL check.
+ cannot do partial chains with a CRL check.
*/
X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
X509_V_FLAG_PARTIAL_CHAIN);
@@ -3158,7 +3151,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
}
- /* SSL always tries to verify the peer, this only says whether it should
+ /* OpenSSL always tries to verify the peer, this only says whether it should
* fail to connect if the verification fails, or if it should continue
* anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
@@ -3173,7 +3166,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
#endif
/* Enable the session cache because it's a prerequisite for the "new session"
- * callback. Use the "external storage" mode to avoid that OpenSSL creates
+ * callback. Use the "external storage" mode to prevent OpenSSL from creating
* an internal session cache.
*/
SSL_CTX_set_session_cache_mode(backend->ctx,
@@ -3192,7 +3185,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
}
}
- /* Lets make an SSL structure */
+ /* Let's make an SSL structure */
if(backend->handle)
SSL_free(backend->handle);
backend->handle = SSL_new(backend->ctx);
@@ -3332,7 +3325,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
/* the connection failed, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_2;
- /* Get the earliest error code from the thread's error queue and removes
+ /* Get the earliest error code from the thread's error queue and remove
the entry. */
errdetail = ERR_get_error();
@@ -3361,7 +3354,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
!defined(LIBRESSL_VERSION_NUMBER) && \
!defined(OPENSSL_IS_BORINGSSL))
/* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on
- OpenSSL version above v1.1.1, not Libre SSL nor BoringSSL */
+ OpenSSL version above v1.1.1, not LibreSSL nor BoringSSL */
else if((lib == ERR_LIB_SSL) &&
(reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) {
/* If client certificate is required, communicate the
@@ -3378,7 +3371,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
/* detail is already set to the SSL error above */
/* If we e.g. use SSLv2 request-method and the server doesn't like us
- * (RST connection etc.), OpenSSL gives no explanation whatsoever and
+ * (RST connection, etc.), OpenSSL gives no explanation whatsoever and
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
@@ -3401,7 +3394,7 @@ static CURLcode ossl_connect_step2(struct Curl_easy *data,
}
}
else {
- /* we have been connected fine, we're not waiting for anything else. */
+ /* we connected fine, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
/* Informational message */
@@ -3820,7 +3813,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert,
}
/*
- * Get the server cert, verify it and show it etc, only call failf() if the
+ * Get the server cert, verify it and show it, etc., only call failf() if the
* 'strict' argument is TRUE as otherwise all this is for informational
* purposes only!
*
@@ -4021,7 +4014,7 @@ static CURLcode ossl_connect_step3(struct Curl_easy *data,
/*
* We check certificates to authenticate the server; otherwise we risk
* man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
- * verify the peer ignore faults and failures from the server cert
+ * verify the peer, ignore faults and failures from the server cert
* operations.
*/
@@ -4059,7 +4052,7 @@ static CURLcode ossl_connect_common(struct Curl_easy *data,
const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
- /* no need to continue if time already is up */
+ /* no need to continue if time is already up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
diff --git a/libs/libcurl/src/vtls/rustls.c b/libs/libcurl/src/vtls/rustls.c
index 94a1ca8861..2ac97ce28e 100644
--- a/libs/libcurl/src/vtls/rustls.c
+++ b/libs/libcurl/src/vtls/rustls.c
@@ -34,7 +34,7 @@
#include "sendf.h"
#include "vtls.h"
#include "select.h"
-
+#include "strerror.h"
#include "multiif.h"
struct ssl_backend_data
@@ -132,7 +132,9 @@ cr_recv(struct Curl_easy *data, int sockindex,
infof(data, "sread: EAGAIN or EWOULDBLOCK");
}
else if(io_error) {
- failf(data, "reading from socket: %s", strerror(io_error));
+ char buffer[STRERROR_LEN];
+ failf(data, "reading from socket: %s",
+ Curl_strerror(io_error, buffer, sizeof(buffer)));
*err = CURLE_READ_ERROR;
return -1;
}
@@ -244,7 +246,9 @@ cr_send(struct Curl_easy *data, int sockindex,
return -1;
}
else if(io_error) {
- failf(data, "writing to socket: %s", strerror(io_error));
+ char buffer[STRERROR_LEN];
+ failf(data, "writing to socket: %s",
+ Curl_strerror(io_error, buffer, sizeof(buffer)));
*err = CURLE_WRITE_ERROR;
return -1;
}
diff --git a/libs/libcurl/src/vtls/schannel.c b/libs/libcurl/src/vtls/schannel.c
index 7ffba6cc19..44c59e7796 100644
--- a/libs/libcurl/src/vtls/schannel.c
+++ b/libs/libcurl/src/vtls/schannel.c
@@ -141,6 +141,12 @@
# define CALG_SHA_256 0x0000800c
#endif
+/* Work around typo in classic MinGW's w32api up to version 5.0,
+ see https://osdn.net/projects/mingw/ticket/38391 */
+#if !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH)
+#define ALG_CLASS_DHASH ALG_CLASS_HASH
+#endif
+
#define BACKEND connssl->backend
static Curl_recv schannel_recv;
@@ -279,13 +285,7 @@ get_alg_id_by_name(char *name)
#ifdef CALG_HMAC
CIPHEROPTION(CALG_HMAC);
#endif
-#if !defined(__W32API_MAJOR_VERSION) || \
- !defined(__W32API_MINOR_VERSION) || \
- defined(__MINGW64_VERSION_MAJOR) || \
- (__W32API_MAJOR_VERSION > 5) || \
- ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
- /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
- see https://osdn.net/projects/mingw/ticket/38391 */
+#ifdef CALG_TLS1PRF
CIPHEROPTION(CALG_TLS1PRF);
#endif
#ifdef CALG_HASH_REPLACE_OWF
@@ -716,8 +716,6 @@ schannel_acquire_credential_handle(struct Curl_easy *data,
}
BACKEND->cred->refcount = 1;
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
- */
sspi_status =
s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
SECPKG_CRED_OUTBOUND, NULL,
@@ -1141,8 +1139,6 @@ schannel_connect_step2(struct Curl_easy *data, struct connectdata *conn,
if(!host_name)
return CURLE_OUT_OF_MEMORY;
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
- */
sspi_status = s_pSecFn->InitializeSecurityContext(
&BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle,
host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
@@ -1364,7 +1360,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
SECURITY_STATUS sspi_status = SEC_E_OK;
CERT_CONTEXT *ccert_context = NULL;
bool isproxy = SSL_IS_PROXY();
-#ifdef DEBUGBUILD
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
const char * const hostname = SSL_HOST_NAME();
#endif
#ifdef HAS_ALPN
@@ -1436,6 +1432,7 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
/* save the current session data for possible re-use */
if(SSL_SET_OPTION(primary.sessionid)) {
bool incache;
+ bool added = FALSE;
struct Curl_schannel_cred *old_cred = NULL;
Curl_ssl_sessionid_lock(data);
@@ -1453,13 +1450,13 @@ schannel_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(!incache) {
result = Curl_ssl_addsessionid(data, conn, isproxy, BACKEND->cred,
sizeof(struct Curl_schannel_cred),
- sockindex);
+ sockindex, &added);
if(result) {
Curl_ssl_sessionid_unlock(data);
failf(data, "schannel: failed to store credential handle");
return result;
}
- else {
+ else if(added) {
/* this cred session is now also referenced by sessionid cache */
BACKEND->cred->refcount++;
DEBUGF(infof(data,
@@ -1970,12 +1967,12 @@ schannel_recv(struct Curl_easy *data, int sockindex,
if(sspi_status == SEC_I_RENEGOTIATE) {
infof(data, "schannel: remote party requests renegotiation");
if(*err && *err != CURLE_AGAIN) {
- infof(data, "schannel: can't renogotiate, an error is pending");
+ infof(data, "schannel: can't renegotiate, an error is pending");
goto cleanup;
}
if(BACKEND->encdata_offset) {
*err = CURLE_RECV_ERROR;
- infof(data, "schannel: can't renogotiate, "
+ infof(data, "schannel: can't renegotiate, "
"encrypted data available");
goto cleanup;
}
@@ -2124,26 +2121,23 @@ static bool schannel_data_pending(const struct connectdata *conn,
return FALSE;
}
-static void schannel_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
-{
- if(conn->ssl[sockindex].use)
- /* if the SSL/TLS channel hasn't been shut down yet, do that now. */
- Curl_ssl_shutdown(data, conn, sockindex);
-}
-
static void schannel_session_free(void *ptr)
{
/* this is expected to be called under sessionid lock */
struct Curl_schannel_cred *cred = ptr;
- cred->refcount--;
- if(cred->refcount == 0) {
- s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
- Curl_safefree(cred);
+ if(cred) {
+ cred->refcount--;
+ if(cred->refcount == 0) {
+ s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+ Curl_safefree(cred);
+ }
}
}
+/* shut down the SSL connection and clean up related memory.
+ this function can be called multiple times on the same connection including
+ if the SSL connection failed (eg connection made but failed handshake). */
static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
@@ -2155,10 +2149,12 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
DEBUGASSERT(data);
- infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu",
- hostname, conn->remote_port);
+ if(connssl->use) {
+ infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu",
+ hostname, conn->remote_port);
+ }
- if(BACKEND->cred && BACKEND->ctxt) {
+ if(connssl->use && BACKEND->cred && BACKEND->ctxt) {
SecBufferDesc BuffDesc;
SecBuffer Buffer;
SECURITY_STATUS sspi_status;
@@ -2251,6 +2247,16 @@ static int schannel_shutdown(struct Curl_easy *data, struct connectdata *conn,
return CURLE_OK;
}
+static void schannel_close(struct Curl_easy *data, struct connectdata *conn,
+ int sockindex)
+{
+ if(conn->ssl[sockindex].use)
+ /* Curl_ssl_shutdown resets the socket state and calls schannel_shutdown */
+ Curl_ssl_shutdown(data, conn, sockindex);
+ else
+ schannel_shutdown(data, conn, sockindex);
+}
+
static int schannel_init(void)
{
return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
diff --git a/libs/libcurl/src/vtls/schannel_verify.c b/libs/libcurl/src/vtls/schannel_verify.c
index 12fccaa8ee..1b283d0453 100644
--- a/libs/libcurl/src/vtls/schannel_verify.c
+++ b/libs/libcurl/src/vtls/schannel_verify.c
@@ -80,7 +80,7 @@ static int is_cr_or_lf(char c)
/* Search the substring needle,needlelen into string haystack,haystacklen
* Strings don't need to be terminated by a '\0'.
* Similar of OSX/Linux memmem (not available on Visual Studio).
- * Return position of beginning of first occurence or NULL if not found
+ * Return position of beginning of first occurrence or NULL if not found
*/
static const char *c_memmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen)
diff --git a/libs/libcurl/src/vtls/sectransp.c b/libs/libcurl/src/vtls/sectransp.c
index 26b833dd2a..0bf515460d 100644
--- a/libs/libcurl/src/vtls/sectransp.c
+++ b/libs/libcurl/src/vtls/sectransp.c
@@ -33,6 +33,8 @@
#include "strtok.h"
#include "multiif.h"
#include "strcase.h"
+#include "x509asn1.h"
+#include "strerror.h"
#ifdef USE_SECTRANSP
@@ -2107,7 +2109,7 @@ static CURLcode sectransp_connect_step1(struct Curl_easy *data,
}
result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
- ssl_sessionid_len, sockindex);
+ ssl_sessionid_len, sockindex, NULL);
Curl_ssl_sessionid_unlock(data);
if(result) {
failf(data, "failed to store ssl session");
@@ -2854,13 +2856,60 @@ sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
}
}
+static CURLcode
+add_cert_to_certinfo(struct Curl_easy *data,
+ SecCertificateRef server_cert,
+ int idx)
+{
+ CURLcode result = CURLE_OK;
+ const char *beg;
+ const char *end;
+ CFDataRef cert_data = SecCertificateCopyData(server_cert);
+
+ if(!cert_data)
+ return CURLE_PEER_FAILED_VERIFICATION;
+
+ beg = (const char *)CFDataGetBytePtr(cert_data);
+ end = beg + CFDataGetLength(cert_data);
+ result = Curl_extract_certinfo(data, idx, beg, end);
+ CFRelease(cert_data);
+ return result;
+}
+
+static CURLcode
+collect_server_cert_single(struct Curl_easy *data,
+ SecCertificateRef server_cert,
+ CFIndex idx)
+{
+ CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ if(data->set.verbose) {
+ char *certp;
+ result = CopyCertSubject(data, server_cert, &certp);
+ if(!result) {
+ infof(data, "Server certificate: %s", certp);
+ free(certp);
+ }
+ }
+#endif
+ if(data->set.ssl.certinfo)
+ result = add_cert_to_certinfo(data, server_cert, (int)idx);
+ return result;
+}
+
/* This should be called during step3 of the connection at the earliest */
-static void
-show_verbose_server_cert(struct Curl_easy *data,
- struct connectdata *conn,
- int sockindex)
+static CURLcode
+collect_server_cert(struct Curl_easy *data,
+ struct connectdata *conn,
+ int sockindex)
{
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ const bool show_verbose_server_cert = data->set.verbose;
+#else
+ const bool show_verbose_server_cert = false;
+#endif
+ CURLcode result = data->set.ssl.certinfo ?
+ CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
CFArrayRef server_certs = NULL;
@@ -2869,8 +2918,11 @@ show_verbose_server_cert(struct Curl_easy *data,
CFIndex i, count;
SecTrustRef trust = NULL;
+ if(!show_verbose_server_cert && !data->set.ssl.certinfo)
+ return CURLE_OK;
+
if(!backend->ssl_ctx)
- return;
+ return result;
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
#if CURL_BUILD_IOS
@@ -2880,15 +2932,11 @@ show_verbose_server_cert(struct Curl_easy *data,
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
- for(i = 0L ; i < count ; i++) {
- CURLcode result;
- char *certp;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(trust);
}
@@ -2906,15 +2954,11 @@ show_verbose_server_cert(struct Curl_easy *data,
a null trust, so be on guard for that: */
if(err == noErr && trust) {
count = SecTrustGetCertificateCount(trust);
- for(i = 0L ; i < count ; i++) {
- char *certp;
- CURLcode result;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = SecTrustGetCertificateAtIndex(trust, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(trust);
}
@@ -2925,16 +2969,12 @@ show_verbose_server_cert(struct Curl_easy *data,
/* Just in case SSLCopyPeerCertificates() returns null too... */
if(err == noErr && server_certs) {
count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- char *certp;
- CURLcode result;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(server_certs);
}
@@ -2946,21 +2986,17 @@ show_verbose_server_cert(struct Curl_easy *data,
err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
if(err == noErr) {
count = CFArrayGetCount(server_certs);
- for(i = 0L ; i < count ; i++) {
- CURLcode result;
- char *certp;
+ if(data->set.ssl.certinfo)
+ result = Curl_ssl_init_certinfo(data, (int)count);
+ for(i = 0L ; !result && (i < count) ; i++) {
server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
- result = CopyCertSubject(data, server_cert, &certp);
- if(!result) {
- infof(data, "Server certificate: %s", certp);
- free(certp);
- }
+ result = collect_server_cert_single(data, server_cert, i);
}
CFRelease(server_certs);
}
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
+ return result;
}
-#endif /* !CURL_DISABLE_VERBOSE_STRINGS */
static CURLcode
sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
@@ -2969,12 +3005,11 @@ sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* There is no step 3!
- * Well, okay, if verbose mode is on, let's print the details of the
- * server certificates. */
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
- if(data->set.verbose)
- show_verbose_server_cert(data, conn, sockindex);
-#endif
+ * Well, okay, let's collect server certificates, and if verbose mode is on,
+ * let's print the details of the server certificates. */
+ const CURLcode result = collect_server_cert(data, conn, sockindex);
+ if(result)
+ return result;
connssl->connecting_state = ssl_connect_done;
return CURLE_OK;
@@ -3188,7 +3223,9 @@ static int sectransp_shutdown(struct Curl_easy *data,
nread = read(conn->sock[sockindex], buf, sizeof(buf));
if(nread < 0) {
- failf(data, "read: %s", strerror(errno));
+ char buffer[STRERROR_LEN];
+ failf(data, "read: %s",
+ Curl_strerror(errno, buffer, sizeof(buffer)));
rc = -1;
}
@@ -3433,6 +3470,7 @@ const struct Curl_ssl Curl_ssl_sectransp = {
{ CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
SSLSUPP_CAINFO_BLOB |
+ SSLSUPP_CERTINFO |
#ifdef SECTRANSP_PINNEDPUBKEY
SSLSUPP_PINNEDPUBKEY,
#else
diff --git a/libs/libcurl/src/vtls/vtls.c b/libs/libcurl/src/vtls/vtls.c
index e5bbe1f5f0..6007bbba0f 100644
--- a/libs/libcurl/src/vtls/vtls.c
+++ b/libs/libcurl/src/vtls/vtls.c
@@ -516,7 +516,8 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
const bool isProxy,
void *ssl_sessionid,
size_t idsize,
- int sockindex)
+ int sockindex,
+ bool *added)
{
size_t i;
struct Curl_ssl_session *store;
@@ -536,6 +537,10 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
const char *hostname = conn->host.name;
#endif
(void)sockindex;
+
+ if(added)
+ *added = FALSE;
+
if(!data->state.session)
return CURLE_OK;
@@ -609,6 +614,9 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
}
+ if(added)
+ *added = TRUE;
+
DEBUGF(infof(data, "Added Session ID to cache for %s://%s:%d [%s]",
store->scheme, store->name, store->remote_port,
isProxy ? "PROXY" : "server"));
diff --git a/libs/libcurl/src/vtls/vtls.h b/libs/libcurl/src/vtls/vtls.h
index beaa83d9e3..c7bbba082d 100644
--- a/libs/libcurl/src/vtls/vtls.h
+++ b/libs/libcurl/src/vtls/vtls.h
@@ -261,7 +261,8 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
const bool isProxy,
void *ssl_sessionid,
size_t idsize,
- int sockindex);
+ int sockindex,
+ bool *added);
/* Kill a single session ID entry in the cache
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
* This will call engine-specific curlssl_session_free function, which must
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c
index 7cab17fb6e..8c5b9157b8 100644
--- a/libs/libcurl/src/vtls/wolfssl.c
+++ b/libs/libcurl/src/vtls/wolfssl.c
@@ -202,6 +202,43 @@ static int do_file_type(const char *type)
return -1;
}
+#ifdef HAVE_LIBOQS
+struct group_name_map {
+ const word16 group;
+ const char *name;
+};
+
+static const struct group_name_map gnm[] = {
+ { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" },
+ { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" },
+ { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" },
+ { WOLFSSL_NTRU_HPS_LEVEL1, "NTRU_HPS_LEVEL1" },
+ { WOLFSSL_NTRU_HPS_LEVEL3, "NTRU_HPS_LEVEL3" },
+ { WOLFSSL_NTRU_HPS_LEVEL5, "NTRU_HPS_LEVEL5" },
+ { WOLFSSL_NTRU_HRSS_LEVEL3, "NTRU_HRSS_LEVEL3" },
+ { WOLFSSL_SABER_LEVEL1, "SABER_LEVEL1" },
+ { WOLFSSL_SABER_LEVEL3, "SABER_LEVEL3" },
+ { WOLFSSL_SABER_LEVEL5, "SABER_LEVEL5" },
+ { WOLFSSL_KYBER_90S_LEVEL1, "KYBER_90S_LEVEL1" },
+ { WOLFSSL_KYBER_90S_LEVEL3, "KYBER_90S_LEVEL3" },
+ { WOLFSSL_KYBER_90S_LEVEL5, "KYBER_90S_LEVEL5" },
+ { WOLFSSL_P256_NTRU_HPS_LEVEL1, "P256_NTRU_HPS_LEVEL1" },
+ { WOLFSSL_P384_NTRU_HPS_LEVEL3, "P384_NTRU_HPS_LEVEL3" },
+ { WOLFSSL_P521_NTRU_HPS_LEVEL5, "P521_NTRU_HPS_LEVEL5" },
+ { WOLFSSL_P384_NTRU_HRSS_LEVEL3, "P384_NTRU_HRSS_LEVEL3" },
+ { WOLFSSL_P256_SABER_LEVEL1, "P256_SABER_LEVEL1" },
+ { WOLFSSL_P384_SABER_LEVEL3, "P384_SABER_LEVEL3" },
+ { WOLFSSL_P521_SABER_LEVEL5, "P521_SABER_LEVEL5" },
+ { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" },
+ { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" },
+ { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" },
+ { WOLFSSL_P256_KYBER_90S_LEVEL1, "P256_KYBER_90S_LEVEL1" },
+ { WOLFSSL_P384_KYBER_90S_LEVEL3, "P384_KYBER_90S_LEVEL3" },
+ { WOLFSSL_P521_KYBER_90S_LEVEL5, "P521_KYBER_90S_LEVEL5" },
+ { 0, NULL }
+};
+#endif
+
/*
* This function loads all the client/CA certificates and CRLs. Setup the TLS
* layer and do all necessary magic.
@@ -210,11 +247,15 @@ static CURLcode
wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
int sockindex)
{
- char *ciphers;
+ char *ciphers, *curves;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
SSL_METHOD* req_method = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
+#ifdef HAVE_LIBOQS
+ word16 oqsAlg = 0;
+ size_t idx = 0;
+#endif
#ifdef HAVE_SNI
bool sni = FALSE;
#define use_sni(x) sni = (x)
@@ -327,6 +368,26 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
infof(data, "Cipher selection: %s", ciphers);
}
+ curves = SSL_CONN_CONFIG(curves);
+ if(curves) {
+
+#ifdef HAVE_LIBOQS
+ for(idx = 0; gnm[idx].name != NULL; idx++) {
+ if(strncmp(curves, gnm[idx].name, strlen(gnm[idx].name)) == 0) {
+ oqsAlg = gnm[idx].group;
+ break;
+ }
+ }
+
+ if(oqsAlg == 0)
+#endif
+ {
+ if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
+ failf(data, "failed setting curves list: '%s'", curves);
+ return CURLE_SSL_CIPHER;
+ }
+ }
+ }
#ifndef NO_FILESYSTEM
/* load trusted cacert */
if(SSL_CONN_CONFIG(CAfile)) {
@@ -439,6 +500,14 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
+#ifdef HAVE_LIBOQS
+ if(oqsAlg) {
+ if(wolfSSL_UseKeyShare(backend->handle, oqsAlg) != WOLFSSL_SUCCESS) {
+ failf(data, "unable to use oqs KEM");
+ }
+ }
+#endif
+
#ifdef HAVE_ALPN
if(conn->bits.tls_enable_alpn) {
char protocols[128];
@@ -495,7 +564,7 @@ wolfssl_connect_step1(struct Curl_easy *data, struct connectdata *conn,
/* we got a session id, use it! */
if(!SSL_set_session(backend->handle, ssl_sessionid)) {
Curl_ssl_delsessionid(data, ssl_sessionid);
- infof(data, "Can't use session ID, going on without\n");
+ infof(data, "Can't use session ID, going on without");
}
else
infof(data, "SSL re-using session ID");
@@ -525,6 +594,8 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
const char * const dispname = SSL_HOST_DISPNAME();
const char * const pinnedpubkey = SSL_PINNED_PUB_KEY();
+ ERR_clear_error();
+
conn->recv[sockindex] = wolfssl_recv;
conn->send[sockindex] = wolfssl_send;
@@ -747,7 +818,7 @@ wolfssl_connect_step3(struct Curl_easy *data, struct connectdata *conn,
if(!incache) {
result = Curl_ssl_addsessionid(data, conn, isproxy, our_ssl_sessionid,
- 0, sockindex);
+ 0, sockindex, NULL);
if(result) {
Curl_ssl_sessionid_unlock(data);
failf(data, "failed to store ssl session");
@@ -775,7 +846,11 @@ static ssize_t wolfssl_send(struct Curl_easy *data,
struct ssl_backend_data *backend = connssl->backend;
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);
+ int rc;
+
+ ERR_clear_error();
+
+ rc = SSL_write(backend->handle, mem, memlen);
if(rc <= 0) {
int err = SSL_get_error(backend->handle, rc);
@@ -831,7 +906,11 @@ static ssize_t wolfssl_recv(struct Curl_easy *data,
struct ssl_backend_data *backend = connssl->backend;
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);
+ int nread;
+
+ ERR_clear_error();
+
+ nread = SSL_read(backend->handle, buf, buffsize);
if(nread < 0) {
int err = SSL_get_error(backend->handle, nread);
@@ -916,6 +995,7 @@ static int wolfssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
(void) data;
if(backend->handle) {
+ ERR_clear_error();
SSL_free(backend->handle);
backend->handle = NULL;
}