diff options
Diffstat (limited to 'libs/libcurl/src/vtls/wolfssl.c')
-rw-r--r-- | libs/libcurl/src/vtls/wolfssl.c | 469 |
1 files changed, 279 insertions, 190 deletions
diff --git a/libs/libcurl/src/vtls/wolfssl.c b/libs/libcurl/src/vtls/wolfssl.c index 458219ef61..9a05f82946 100644 --- a/libs/libcurl/src/vtls/wolfssl.c +++ b/libs/libcurl/src/vtls/wolfssl.c @@ -97,9 +97,25 @@ #endif
#endif
-#if defined(HAVE_WOLFSSL_FULL_BIO) && HAVE_WOLFSSL_FULL_BIO
+#ifdef HAVE_WOLFSSL_BIO
#define USE_BIO_CHAIN
-#else
+#ifdef HAVE_WOLFSSL_FULL_BIO
+#define USE_FULL_BIO
+#else /* HAVE_WOLFSSL_FULL_BIO */
+#undef USE_FULL_BIO
+#endif
+/* wolfSSL 5.7.4 and older do not have these symbols, but only the
+ * OpenSSL ones. */
+#ifndef WOLFSSL_BIO_CTRL_GET_CLOSE
+#define WOLFSSL_BIO_CTRL_GET_CLOSE BIO_CTRL_GET_CLOSE
+#define WOLFSSL_BIO_CTRL_SET_CLOSE BIO_CTRL_SET_CLOSE
+#define WOLFSSL_BIO_CTRL_FLUSH BIO_CTRL_FLUSH
+#define WOLFSSL_BIO_CTRL_DUP BIO_CTRL_DUP
+#define wolfSSL_BIO_set_retry_write BIO_set_retry_write
+#define wolfSSL_BIO_set_retry_read BIO_set_retry_read
+#endif /* !WOLFSSL_BIO_CTRL_GET_CLOSE */
+
+#else /* HAVE_WOLFSSL_BIO */
#undef USE_BIO_CHAIN
#endif
@@ -163,7 +179,7 @@ wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret, #endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */
static void
-wolfssl_log_tls12_secret(SSL *ssl)
+wolfssl_log_tls12_secret(WOLFSSL *ssl)
{
unsigned char *ms, *sr, *cr;
unsigned int msLen, srLen, crLen, i, x = 0;
@@ -187,7 +203,7 @@ wolfssl_log_tls12_secret(SSL *ssl) #endif
if(wolfSSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) !=
- SSL_SUCCESS) {
+ WOLFSSL_SUCCESS) {
return;
}
@@ -208,11 +224,11 @@ wolfssl_log_tls12_secret(SSL *ssl) static int wolfssl_do_file_type(const char *type)
{
if(!type || !type[0])
- return SSL_FILETYPE_PEM;
+ return WOLFSSL_FILETYPE_PEM;
if(strcasecompare(type, "PEM"))
- return SSL_FILETYPE_PEM;
+ return WOLFSSL_FILETYPE_PEM;
if(strcasecompare(type, "DER"))
- return SSL_FILETYPE_ASN1;
+ return WOLFSSL_FILETYPE_ASN1;
return -1;
}
@@ -237,7 +253,9 @@ static const struct group_name_map gnm[] = { static int wolfssl_bio_cf_create(WOLFSSL_BIO *bio)
{
+#ifdef USE_FULL_BIO
wolfSSL_BIO_set_shutdown(bio, 1);
+#endif
wolfSSL_BIO_set_data(bio, NULL);
return 1;
}
@@ -251,28 +269,35 @@ static int wolfssl_bio_cf_destroy(WOLFSSL_BIO *bio) static long wolfssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr)
{
- struct Curl_cfilter *cf = BIO_get_data(bio);
+ struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio);
long ret = 1;
(void)cf;
(void)ptr;
+ (void)num;
switch(cmd) {
- case BIO_CTRL_GET_CLOSE:
+ case WOLFSSL_BIO_CTRL_GET_CLOSE:
+#ifdef USE_FULL_BIO
ret = (long)wolfSSL_BIO_get_shutdown(bio);
+#else
+ ret = 0;
+#endif
break;
- case BIO_CTRL_SET_CLOSE:
+ case WOLFSSL_BIO_CTRL_SET_CLOSE:
+#ifdef USE_FULL_BIO
wolfSSL_BIO_set_shutdown(bio, (int)num);
+#endif
break;
- case BIO_CTRL_FLUSH:
+ case WOLFSSL_BIO_CTRL_FLUSH:
/* we do no delayed writes, but if we ever would, this
* needs to trigger it. */
ret = 1;
break;
- case BIO_CTRL_DUP:
+ case WOLFSSL_BIO_CTRL_DUP:
ret = 1;
break;
-#ifdef BIO_CTRL_EOF
- case BIO_CTRL_EOF:
+#ifdef WOLFSSL_BIO_CTRL_EOF
+ case WOLFSSL_BIO_CTRL_EOF:
/* EOF has been reached on input? */
return (!cf->next || !cf->next->connected);
#endif
@@ -309,9 +334,11 @@ static int wolfssl_bio_cf_out_write(WOLFSSL_BIO *bio, backend->io_result = result;
CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %zd, %d",
blen, nwritten, result);
+#ifdef USE_FULL_BIO
wolfSSL_BIO_clear_retry_flags(bio);
+#endif
if(nwritten < 0 && CURLE_AGAIN == result) {
- BIO_set_retry_write(bio);
+ wolfSSL_BIO_set_retry_write(bio);
if(backend->shutting_down && !backend->io_send_blocked_len)
backend->io_send_blocked_len = blen;
}
@@ -338,9 +365,11 @@ static int wolfssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
backend->io_result = result;
CURL_TRC_CF(data, cf, "bio_read(len=%d) -> %zd, %d", blen, nread, result);
+#ifdef USE_FULL_BIO
wolfSSL_BIO_clear_retry_flags(bio);
+#endif
if(nread < 0 && CURLE_AGAIN == result)
- BIO_set_retry_read(bio);
+ wolfSSL_BIO_set_retry_read(bio);
else if(nread == 0)
connssl->peer_closed = TRUE;
return (int)nread;
@@ -350,7 +379,8 @@ static WOLFSSL_BIO_METHOD *wolfssl_bio_cf_method = NULL; static void wolfssl_bio_cf_init_methods(void)
{
- wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(BIO_TYPE_MEM, "wolfSSL CF BIO");
+ wolfssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY,
+ "wolfSSL CF BIO");
wolfSSL_BIO_meth_set_write(wolfssl_bio_cf_method, &wolfssl_bio_cf_out_write);
wolfSSL_BIO_meth_set_read(wolfssl_bio_cf_method, &wolfssl_bio_cf_in_read);
wolfSSL_BIO_meth_set_ctrl(wolfssl_bio_cf_method, &wolfssl_bio_cf_ctrl);
@@ -370,9 +400,114 @@ static void wolfssl_bio_cf_free_methods(void) #endif /* !USE_BIO_CHAIN */
+static void wolfssl_session_free(void *sdata, size_t slen)
+{
+ (void)slen;
+ free(sdata);
+}
+
+CURLcode wssl_cache_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct ssl_peer *peer,
+ WOLFSSL_SESSION *session)
+{
+ CURLcode result = CURLE_OK;
+ unsigned char *sdata = NULL;
+ unsigned int slen;
+
+ if(!session)
+ goto out;
+
+ slen = wolfSSL_i2d_SSL_SESSION(session, NULL);
+ if(slen <= 0) {
+ CURL_TRC_CF(data, cf, "fail to assess session length: %u", slen);
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+ sdata = calloc(1, slen);
+ if(!sdata) {
+ failf(data, "unable to allocate session buffer of %u bytes", slen);
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+ slen = wolfSSL_i2d_SSL_SESSION(session, &sdata);
+ if(slen <= 0) {
+ CURL_TRC_CF(data, cf, "fail to serialize session: %u", slen);
+ result = CURLE_FAILED_INIT;
+ goto out;
+ }
+
+ Curl_ssl_sessionid_lock(data);
+ result = Curl_ssl_set_sessionid(cf, data, peer, NULL,
+ sdata, slen, wolfssl_session_free);
+ Curl_ssl_sessionid_unlock(data);
+ if(result)
+ failf(data, "failed to add new ssl session to cache (%d)", result);
+ else {
+ CURL_TRC_CF(data, cf, "added new session to cache");
+ sdata = NULL;
+ }
+
+out:
+ free(sdata);
+ return 0;
+}
+
+static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session)
+{
+ struct Curl_cfilter *cf;
+
+ cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl);
+ DEBUGASSERT(cf != NULL);
+ if(cf && session) {
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct Curl_easy *data = CF_DATA_CURRENT(cf);
+ DEBUGASSERT(connssl);
+ DEBUGASSERT(data);
+ if(connssl && data) {
+ (void)wssl_cache_session(cf, data, &connssl->peer, session);
+ }
+ }
+ return 0;
+}
+
+CURLcode wssl_setup_session(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ struct wolfssl_ctx *wss,
+ struct ssl_peer *peer)
+{
+ void *psdata;
+ const unsigned char *sdata = NULL;
+ size_t slen = 0;
+ CURLcode result = CURLE_OK;
+
+ Curl_ssl_sessionid_lock(data);
+ if(!Curl_ssl_getsessionid(cf, data, peer, &psdata, &slen, NULL)) {
+ WOLFSSL_SESSION *session;
+ sdata = psdata;
+ session = wolfSSL_d2i_SSL_SESSION(NULL, &sdata, (long)slen);
+ if(session) {
+ int ret = wolfSSL_set_session(wss->handle, session);
+ if(ret != WOLFSSL_SUCCESS) {
+ Curl_ssl_delsessionid(data, psdata);
+ infof(data, "previous session not accepted (%d), "
+ "removing from cache", ret);
+ }
+ else
+ infof(data, "SSL reusing session ID");
+ wolfSSL_SESSION_free(session);
+ }
+ else {
+ failf(data, "could not decode previous session");
+ }
+ }
+ Curl_ssl_sessionid_unlock(data);
+ return result;
+}
+
static CURLcode populate_x509_store(struct Curl_cfilter *cf,
struct Curl_easy *data,
- X509_STORE *store,
+ WOLFSSL_X509_STORE *store,
struct wolfssl_ctx *wssl)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
@@ -382,7 +517,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, (ca_info_blob ? NULL : conn_config->CAfile);
const char * const ssl_capath = conn_config->CApath;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
- bool imported_native_ca = false;
+ bool imported_native_ca = FALSE;
#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SYS_CA_CERTS)
/* load native CA certificates */
@@ -391,7 +526,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, infof(data, "error importing native CA store, continuing anyway");
}
else {
- imported_native_ca = true;
+ imported_native_ca = TRUE;
infof(data, "successfully imported native CA store");
wssl->x509_store_setup = TRUE;
}
@@ -402,7 +537,8 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, if(ca_info_blob) {
if(wolfSSL_CTX_load_verify_buffer(wssl->ctx, ca_info_blob->data,
(long)ca_info_blob->len,
- SSL_FILETYPE_PEM) != SSL_SUCCESS) {
+ WOLFSSL_FILETYPE_PEM) !=
+ WOLFSSL_SUCCESS) {
if(imported_native_ca) {
infof(data, "error importing CA certificate blob, continuing anyway");
}
@@ -421,7 +557,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, /* load trusted cacert from file if not blob */
CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d",
- ssl_cafile? ssl_cafile : "none", !!ca_info_blob);
+ ssl_cafile ? ssl_cafile : "none", !!ca_info_blob);
if(!store)
return CURLE_OUT_OF_MEMORY;
@@ -431,7 +567,7 @@ static CURLcode populate_x509_store(struct Curl_cfilter *cf, ssl_cafile,
ssl_capath,
WOLFSSL_LOAD_FLAG_IGNORE_ERR);
- if(SSL_SUCCESS != rc) {
+ if(WOLFSSL_SUCCESS != rc) {
if(conn_config->verifypeer) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:"
@@ -493,7 +629,7 @@ cached_x509_store_expired(const struct Curl_easy *data, timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
if(timeout_ms < 0)
- return false;
+ return FALSE;
return elapsed_ms >= timeout_ms;
}
@@ -509,17 +645,17 @@ cached_x509_store_different(struct Curl_cfilter *cf, return strcmp(mb->CAfile, conn_config->CAfile);
}
-static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
- const struct Curl_easy *data)
+static WOLFSSL_X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
+ const struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct wssl_x509_share *share;
WOLFSSL_X509_STORE *store = NULL;
DEBUGASSERT(multi);
- share = multi? Curl_hash_pick(&multi->proto_hash,
- (void *)MPROTO_WSSL_X509_KEY,
- sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
+ share = multi ? Curl_hash_pick(&multi->proto_hash,
+ (void *)MPROTO_WSSL_X509_KEY,
+ sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL;
if(share && share->store &&
!cached_x509_store_expired(data, share) &&
!cached_x509_store_different(cf, share)) {
@@ -531,7 +667,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, static void set_cached_x509_store(struct Curl_cfilter *cf,
const struct Curl_easy *data,
- X509_STORE *store)
+ WOLFSSL_X509_STORE *store)
{
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct Curl_multi *multi = data->multi;
@@ -563,13 +699,13 @@ static void set_cached_x509_store(struct Curl_cfilter *cf, if(conn_config->CAfile) {
CAfile = strdup(conn_config->CAfile);
if(!CAfile) {
- X509_STORE_free(store);
+ wolfSSL_X509_STORE_free(store);
return;
}
}
if(share->store) {
- X509_STORE_free(share->store);
+ wolfSSL_X509_STORE_free(share->store);
free(share->CAfile);
}
@@ -609,7 +745,7 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, else if(cache_criteria_met) {
/* wolfSSL's initial store in CTX is not shareable by default.
* Make a new one, suitable for adding to the cache. See #14278 */
- X509_STORE *store = wolfSSL_X509_STORE_new();
+ WOLFSSL_X509_STORE *store = wolfSSL_X509_STORE_new();
if(!store) {
failf(data, "SSL: could not create a X509 store");
return CURLE_OUT_OF_MEMORY;
@@ -623,7 +759,7 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, }
else {
/* We never share the CTX's store, use it. */
- X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
+ WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ctx);
result = populate_x509_store(cf, data, store, wssl);
}
@@ -631,36 +767,35 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, }
#ifdef WOLFSSL_TLS13
-static size_t
-wssl_get_default_ciphers(bool tls13, char *buf, size_t size)
+static CURLcode
+wssl_add_default_ciphers(bool tls13, struct dynbuf *buf)
{
- size_t len = 0;
- char *term = buf;
int i;
char *str;
- size_t n;
for(i = 0; (str = wolfSSL_get_cipher_list(i)); i++) {
+ size_t n;
if((strncmp(str, "TLS13", 5) == 0) != tls13)
continue;
- n = strlen(str);
- if(buf && len + n + 1 <= size) {
- memcpy(buf + len, str, n);
- term = buf + len + n;
- *term = ':';
+ /* if there already is data in the string, add colon separator */
+ if(Curl_dyn_len(buf)) {
+ CURLcode result = Curl_dyn_addn(buf, ":", 1);
+ if(result)
+ return result;
}
- len += n + 1;
- }
- if(buf)
- *term = '\0';
+ n = strlen(str);
+ if(Curl_dyn_addn(buf, str, n))
+ return CURLE_OUT_OF_MEMORY;
+ }
- return len > 0 ? len - 1 : 0;
+ return CURLE_OK;
}
#endif
-#if LIBWOLFSSL_VERSION_HEX < 0x04002000 /* 4.2.0 (2019) */
+/* 4.2.0 (2019) */
+#if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA)
static int
wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version)
{
@@ -707,7 +842,7 @@ static CURLcode wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
{
int res;
- char *ciphers, *curves;
+ char *curves;
struct ssl_connect_data *connssl = cf->ctx;
struct wolfssl_ctx *backend =
(struct wolfssl_ctx *)connssl->backend;
@@ -798,50 +933,50 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) }
#ifndef WOLFSSL_TLS13
- ciphers = conn_config->cipher_list;
- if(ciphers) {
- if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
- failf(data, "failed setting cipher list: %s", ciphers);
- return CURLE_SSL_CIPHER;
+ {
+ char *ciphers = conn_config->cipher_list;
+ if(ciphers) {
+ if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
+ failf(data, "failed setting cipher list: %s", ciphers);
+ return CURLE_SSL_CIPHER;
+ }
+ infof(data, "Cipher selection: %s", ciphers);
}
- infof(data, "Cipher selection: %s", ciphers);
}
#else
+#define MAX_CIPHER_LEN 4096
if(conn_config->cipher_list || conn_config->cipher_list13) {
const char *ciphers12 = conn_config->cipher_list;
const char *ciphers13 = conn_config->cipher_list13;
-
- /* Set ciphers to a combination of ciphers_list and ciphers_list13.
- * If cipher_list is not set use the default TLSv1.2 (1.1, 1.0) ciphers.
- * If cipher_list13 is not set use the default TLSv1.3 ciphers. */
- size_t len13 = ciphers13 ? strlen(ciphers13)
- : wssl_get_default_ciphers(true, NULL, 0);
- size_t len12 = ciphers12 ? strlen(ciphers12)
- : wssl_get_default_ciphers(false, NULL, 0);
-
- ciphers = malloc(len13 + 1 + len12 + 1);
- if(!ciphers)
- return CURLE_OUT_OF_MEMORY;
+ struct dynbuf c;
+ CURLcode result;
+ Curl_dyn_init(&c, MAX_CIPHER_LEN);
if(ciphers13)
- memcpy(ciphers, ciphers13, len13);
+ result = Curl_dyn_add(&c, ciphers13);
else
- wssl_get_default_ciphers(true, ciphers, len13 + 1);
- ciphers[len13] = ':';
+ result = wssl_add_default_ciphers(TRUE, &c);
- if(ciphers12)
- memcpy(ciphers + len13 + 1, ciphers12, len12);
- else
- wssl_get_default_ciphers(false, ciphers + len13 + 1, len12 + 1);
- ciphers[len13 + 1 + len12] = '\0';
+ if(!result) {
+ if(ciphers12) {
+ if(Curl_dyn_len(&c))
+ result = Curl_dyn_addn(&c, ":", 1);
+ if(!result)
+ result = Curl_dyn_add(&c, ciphers12);
+ }
+ else
+ result = wssl_add_default_ciphers(FALSE, &c);
+ }
+ if(result)
+ return result;
- if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
- failf(data, "failed setting cipher list: %s", ciphers);
- free(ciphers);
+ if(!wolfSSL_CTX_set_cipher_list(backend->ctx, Curl_dyn_ptr(&c))) {
+ failf(data, "failed setting cipher list: %s", Curl_dyn_ptr(&c));
+ Curl_dyn_free(&c);
return CURLE_SSL_CIPHER;
}
- infof(data, "Cipher selection: %s", ciphers);
- free(ciphers);
+ infof(data, "Cipher selection: %s", Curl_dyn_ptr(&c));
+ Curl_dyn_free(&c);
}
#endif
@@ -859,7 +994,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(pqkem == 0)
#endif
{
- if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) {
+ if(!wolfSSL_CTX_set1_curves_list(backend->ctx, curves)) {
failf(data, "failed setting curves list: '%s'", curves);
return CURLE_SSL_CIPHER;
}
@@ -960,8 +1095,8 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) * anyway. In the latter case the result of the verification is checked with
* SSL_get_verify_result() below. */
wolfSSL_CTX_set_verify(backend->ctx,
- conn_config->verifypeer?SSL_VERIFY_PEER:
- SSL_VERIFY_NONE, NULL);
+ conn_config->verifypeer ? WOLFSSL_VERIFY_PEER :
+ WOLFSSL_VERIFY_NONE, NULL);
#ifdef HAVE_SNI
if(connssl->peer.sni) {
@@ -1028,7 +1163,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(result ||
wolfSSL_UseALPN(backend->handle,
(char *)proto.data, (unsigned int)proto.len,
- WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
+ WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != WOLFSSL_SUCCESS) {
failf(data, "SSL: failed setting ALPN protocols");
return CURLE_SSL_CONNECT_ERROR;
}
@@ -1056,20 +1191,11 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* Check if there is a cached ID we can/should use here! */
if(ssl_config->primary.cache_session) {
- void *ssl_sessionid = NULL;
-
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &ssl_sessionid, NULL)) {
- /* we got a session id, use it! */
- if(!SSL_set_session(backend->handle, ssl_sessionid)) {
- Curl_ssl_delsessionid(data, ssl_sessionid);
- infof(data, "cannot use session ID, going on without");
- }
- else
- infof(data, "SSL reusing session ID");
- }
- Curl_ssl_sessionid_unlock(data);
+ /* Set session from cache if there is one */
+ (void)wssl_setup_session(cf, data, backend, &connssl->peer);
+ /* Register to get notified when a new session is received */
+ wolfSSL_set_app_data(backend->handle, cf);
+ wolfSSL_CTX_sess_set_new_cb(backend->ctx, wssl_vtls_new_session_cb);
}
#ifdef USE_ECH
@@ -1152,7 +1278,7 @@ wolfssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) {
WOLFSSL_BIO *bio;
- bio = BIO_new(wolfssl_bio_cf_method);
+ bio = wolfSSL_BIO_new(wolfssl_bio_cf_method);
if(!bio)
return CURLE_OUT_OF_MEMORY;
@@ -1200,8 +1326,8 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) (struct wolfssl_ctx *)connssl->backend;
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
#ifndef CURL_DISABLE_PROXY
- const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
+ const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ?
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY];
#else
const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
@@ -1213,9 +1339,9 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* Enable RFC2818 checks */
if(conn_config->verifyhost) {
- char *snihost = connssl->peer.sni?
- connssl->peer.sni : connssl->peer.hostname;
- if(wolfSSL_check_domain_name(backend->handle, snihost) == SSL_FAILURE)
+ char *snihost = connssl->peer.sni ?
+ connssl->peer.sni : connssl->peer.hostname;
+ if(wolfSSL_check_domain_name(backend->handle, snihost) == WOLFSSL_FAILURE)
return CURLE_SSL_CONNECT_ERROR;
}
@@ -1244,7 +1370,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
* changes, the worst case is that no key is logged on error.
*/
- if(ret == SSL_SUCCESS ||
+ if(ret == WOLFSSL_SUCCESS ||
(!wolfSSL_want_read(backend->handle) &&
!wolfSSL_want_write(backend->handle))) {
wolfssl_log_tls12_secret(backend->handle);
@@ -1258,11 +1384,11 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret != 1) {
int detail = wolfSSL_get_error(backend->handle, ret);
- if(SSL_ERROR_WANT_READ == detail) {
+ if(WOLFSSL_ERROR_WANT_READ == detail) {
connssl->io_need = CURL_SSL_IO_NEED_RECV;
return CURLE_OK;
}
- else if(SSL_ERROR_WANT_WRITE == detail) {
+ else if(WOLFSSL_ERROR_WANT_WRITE == detail) {
connssl->io_need = CURL_SSL_IO_NEED_SEND;
return CURLE_OK;
}
@@ -1354,7 +1480,7 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) if(pinnedpubkey) {
#ifdef KEEP_PEER_CERT
- X509 *x509;
+ WOLFSSL_X509 *x509;
const char *x509_der;
int x509_der_len;
struct Curl_X509certificate x509_parsed;
@@ -1406,12 +1532,12 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
- if(rc == SSL_SUCCESS) {
- Curl_alpn_set_negotiated(cf, data, (const unsigned char *)protocol,
- protocol_len);
+ if(rc == WOLFSSL_SUCCESS) {
+ Curl_alpn_set_negotiated(cf, data, connssl,
+ (const unsigned char *)protocol, protocol_len);
}
- else if(rc == SSL_ALPN_NOT_FOUND)
- Curl_alpn_set_negotiated(cf, data, NULL, 0);
+ else if(rc == WOLFSSL_ALPN_NOT_FOUND)
+ Curl_alpn_set_negotiated(cf, data, connssl, NULL, 0);
else {
failf(data, "ALPN, failure getting protocol, error %d", rc);
return CURLE_SSL_CONNECT_ERROR;
@@ -1431,50 +1557,6 @@ wolfssl_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK;
}
-
-static void wolfssl_session_free(void *sessionid, size_t idsize)
-{
- (void)idsize;
- wolfSSL_SESSION_free(sessionid);
-}
-
-
-static CURLcode
-wolfssl_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data)
-{
- CURLcode result = CURLE_OK;
- struct ssl_connect_data *connssl = cf->ctx;
- struct wolfssl_ctx *backend =
- (struct wolfssl_ctx *)connssl->backend;
- const struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
-
- DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
- DEBUGASSERT(backend);
-
- if(ssl_config->primary.cache_session) {
- /* wolfSSL_get1_session allocates memory that has to be freed. */
- WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle);
-
- if(our_ssl_sessionid) {
- Curl_ssl_sessionid_lock(data);
- /* call takes ownership of `our_ssl_sessionid` */
- result = Curl_ssl_set_sessionid(cf, data, &connssl->peer,
- our_ssl_sessionid, 0,
- wolfssl_session_free);
- Curl_ssl_sessionid_unlock(data);
- if(result) {
- failf(data, "failed to store ssl session");
- return result;
- }
- }
- }
-
- connssl->connecting_state = ssl_connect_done;
-
- return result;
-}
-
-
static ssize_t wolfssl_send(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *mem,
@@ -1496,8 +1578,8 @@ static ssize_t wolfssl_send(struct Curl_cfilter *cf, int err = wolfSSL_get_error(backend->handle, rc);
switch(err) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
+ case WOLFSSL_ERROR_WANT_READ:
+ case WOLFSSL_ERROR_WANT_WRITE:
/* there is data pending, re-invoke SSL_write() */
CURL_TRC_CF(data, cf, "wolfssl_send(len=%zu) -> AGAIN", len);
*curlcode = CURLE_AGAIN;
@@ -1546,14 +1628,14 @@ static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf, wctx->shutting_down = TRUE;
connssl->io_need = CURL_SSL_IO_NEED_NONE;
*done = FALSE;
- if(!(wolfSSL_get_shutdown(wctx->handle) & SSL_SENT_SHUTDOWN)) {
+ if(!(wolfSSL_get_shutdown(wctx->handle) & WOLFSSL_SENT_SHUTDOWN)) {
/* We have not started the shutdown from our side yet. Check
* if the server already sent us one. */
- ERR_clear_error();
+ wolfSSL_ERR_clear_error();
nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
err = wolfSSL_get_error(wctx->handle, nread);
CURL_TRC_CF(data, cf, "wolfSSL_read, nread=%d, err=%d", nread, err);
- if(!nread && err == SSL_ERROR_ZERO_RETURN) {
+ if(!nread && err == WOLFSSL_ERROR_ZERO_RETURN) {
bool input_pending;
/* Yes, it did. */
if(!send_shutdown) {
@@ -1576,13 +1658,13 @@ static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf, /* SSL should now have started the shutdown from our side. Since it
* was not complete, we are lacking the close notify from the server. */
if(send_shutdown) {
- ERR_clear_error();
+ wolfSSL_ERR_clear_error();
if(wolfSSL_shutdown(wctx->handle) == 1) {
CURL_TRC_CF(data, cf, "SSL shutdown finished");
*done = TRUE;
goto out;
}
- if(SSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) {
+ if(WOLFSSL_ERROR_WANT_WRITE == wolfSSL_get_error(wctx->handle, nread)) {
CURL_TRC_CF(data, cf, "SSL shutdown still wants to send");
connssl->io_need = CURL_SSL_IO_NEED_SEND;
goto out;
@@ -1592,25 +1674,25 @@ static CURLcode wolfssl_shutdown(struct Curl_cfilter *cf, }
for(i = 0; i < 10; ++i) {
- ERR_clear_error();
+ wolfSSL_ERR_clear_error();
nread = wolfSSL_read(wctx->handle, buf, (int)sizeof(buf));
if(nread <= 0)
break;
}
err = wolfSSL_get_error(wctx->handle, nread);
switch(err) {
- case SSL_ERROR_ZERO_RETURN: /* no more data */
+ case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
CURL_TRC_CF(data, cf, "SSL shutdown received");
*done = TRUE;
break;
- case SSL_ERROR_NONE: /* just did not get anything */
- case SSL_ERROR_WANT_READ:
+ case WOLFSSL_ERROR_NONE: /* just did not get anything */
+ case WOLFSSL_ERROR_WANT_READ:
/* SSL has send its notify and now wants to read the reply
* from the server. We are not really interested in that. */
CURL_TRC_CF(data, cf, "SSL shutdown sent, want receive");
connssl->io_need = CURL_SSL_IO_NEED_RECV;
break;
- case SSL_ERROR_WANT_WRITE:
+ case WOLFSSL_ERROR_WANT_WRITE:
CURL_TRC_CF(data, cf, "SSL shutdown send blocked");
connssl->io_need = CURL_SSL_IO_NEED_SEND;
break;
@@ -1671,13 +1753,18 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, int err = wolfSSL_get_error(backend->handle, nread);
switch(err) {
- case SSL_ERROR_ZERO_RETURN: /* no more data */
+ case WOLFSSL_ERROR_ZERO_RETURN: /* no more data */
CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
*curlcode = CURLE_OK;
return 0;
- case SSL_ERROR_NONE:
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
+ case WOLFSSL_ERROR_NONE:
+ case WOLFSSL_ERROR_WANT_READ:
+ case WOLFSSL_ERROR_WANT_WRITE:
+ if(!backend->io_result && connssl->peer_closed) {
+ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
+ *curlcode = CURLE_OK;
+ return 0;
+ }
/* there is data pending, re-invoke wolfSSL_read() */
CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> AGAIN", blen);
*curlcode = CURLE_AGAIN;
@@ -1688,7 +1775,12 @@ static ssize_t wolfssl_recv(struct Curl_cfilter *cf, *curlcode = CURLE_AGAIN;
return -1;
}
- {
+ else if(!backend->io_result && connssl->peer_closed) {
+ CURL_TRC_CF(data, cf, "wolfssl_recv(len=%zu) -> CLOSED", blen);
+ *curlcode = CURLE_OK;
+ return 0;
+ }
+ else {
char error_buffer[256];
failf(data, "SSL read: %s, errno %d",
wolfssl_strerror((unsigned long)err, error_buffer,
@@ -1721,7 +1813,7 @@ static int wolfssl_init(void) #ifdef OPENSSL_EXTRA
Curl_tls_keylog_open();
#endif
- ret = (wolfSSL_Init() == SSL_SUCCESS);
+ ret = (wolfSSL_Init() == WOLFSSL_SUCCESS);
wolfssl_bio_cf_init_methods();
return ret;
}
@@ -1748,7 +1840,7 @@ static bool wolfssl_data_pending(struct Curl_cfilter *cf, backend = (struct wolfssl_ctx *)ctx->backend;
if(backend->handle) /* SSL is in use */
- return (0 != wolfSSL_pending(backend->handle)) ? TRUE : FALSE;
+ return wolfSSL_pending(backend->handle);
else
return FALSE;
}
@@ -1762,7 +1854,6 @@ wolfssl_connect_common(struct Curl_cfilter *cf, CURLcode result;
struct ssl_connect_data *connssl = cf->ctx;
curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
- int what;
/* check if the connection has already been established */
if(ssl_connection_complete == connssl->state) {
@@ -1798,14 +1889,12 @@ wolfssl_connect_common(struct Curl_cfilter *cf, /* if ssl is expecting something, check if it is available. */
if(connssl->io_need) {
-
- curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND)?
- sockfd:CURL_SOCKET_BAD;
- curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV)?
- sockfd:CURL_SOCKET_BAD;
-
- what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:timeout_ms);
+ curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
+ sockfd : CURL_SOCKET_BAD;
+ curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
+ sockfd : CURL_SOCKET_BAD;
+ int 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);
@@ -1838,9 +1927,9 @@ wolfssl_connect_common(struct Curl_cfilter *cf, } /* repeat step2 until all transactions are done. */
if(ssl_connect_3 == connssl->connecting_state) {
- result = wolfssl_connect_step3(cf, data);
- if(result)
- return result;
+ /* In other backends, this is where we verify the certificate, but
+ * wolfSSL already does that as part of the handshake. */
+ connssl->connecting_state = ssl_connect_done;
}
if(ssl_connect_done == connssl->connecting_state) {
|