summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/vtls/mbedtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/vtls/mbedtls.c')
-rw-r--r--libs/libcurl/src/vtls/mbedtls.c226
1 files changed, 126 insertions, 100 deletions
diff --git a/libs/libcurl/src/vtls/mbedtls.c b/libs/libcurl/src/vtls/mbedtls.c
index ae2acdb0a0..c0e98e12c5 100644
--- a/libs/libcurl/src/vtls/mbedtls.c
+++ b/libs/libcurl/src/vtls/mbedtls.c
@@ -64,6 +64,7 @@
#include "mbedtls.h"
#include "vtls.h"
#include "vtls_int.h"
+#include "vtls_scache.h"
#include "x509asn1.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
@@ -78,11 +79,8 @@
#include "memdebug.h"
/* ALPN for http2 */
-#ifdef USE_HTTP2
-# undef HAS_ALPN
-# ifdef MBEDTLS_SSL_ALPN
-# define HAS_ALPN
-# endif
+#if defined(USE_HTTP2) && defined(MBEDTLS_SSL_ALPN)
+# define HAS_ALPN_MBEDTLS
#endif
struct mbed_ssl_backend_data {
@@ -96,33 +94,40 @@ struct mbed_ssl_backend_data {
#endif
mbedtls_pk_context pk;
mbedtls_ssl_config config;
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
const char *protocols[3];
#endif
int *ciphersuites;
+ size_t send_blocked_len;
BIT(initialized); /* mbedtls_ssl_context is initialized */
BIT(sent_shutdown);
+ BIT(send_blocked);
};
/* apply threading? */
-#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
- defined(_WIN32)
-#define THREADING_SUPPORT
+#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
+ defined(_WIN32)
+#define HAS_THREADING_SUPPORT
#endif
#ifndef MBEDTLS_ERROR_C
#define mbedtls_strerror(a,b,c) b[0] = 0
#endif
+/* PSA can be used independently of TLS 1.3 */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && MBEDTLS_VERSION_NUMBER >= 0x03060000
+#define HAS_PSA_SUPPORT
+#endif
+
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && MBEDTLS_VERSION_NUMBER >= 0x03060000
-#define TLS13_SUPPORT
+#define HAS_TLS13_SUPPORT
#endif
-#if defined(TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(HAS_TLS13_SUPPORT) && defined(MBEDTLS_SSL_SESSION_TICKETS)
#define HAS_SESSION_TICKETS
#endif
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
static mbedtls_entropy_context ts_entropy;
static int entropy_init_initialized = 0;
@@ -160,7 +165,7 @@ static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
return ret;
}
-#endif /* THREADING_SUPPORT */
+#endif /* HAS_THREADING_SUPPORT */
#ifdef MBEDTLS_DEBUG
static void mbed_debug(void *context, int level, const char *f_name,
@@ -290,7 +295,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
/* ver_min = MBEDTLS_SSL_VERSION_TLS1_2; */
break;
case CURL_SSLVERSION_TLSv1_3:
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
ver_min = MBEDTLS_SSL_VERSION_TLS1_3;
break;
#endif
@@ -304,7 +309,7 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data,
case CURL_SSLVERSION_MAX_DEFAULT:
case CURL_SSLVERSION_MAX_NONE:
case CURL_SSLVERSION_MAX_TLSv1_3:
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
ver_max = MBEDTLS_SSL_VERSION_TLS1_3;
break;
#endif
@@ -395,7 +400,7 @@ mbed_set_selected_ciphers(struct Curl_easy *data,
if(!selected)
return CURLE_OUT_OF_MEMORY;
-#ifndef TLS13_SUPPORT
+#ifndef HAS_TLS13_SUPPORT
(void) ciphers13, (void) j;
#else
if(!ciphers13) {
@@ -443,7 +448,7 @@ add_ciphers:
selected[count++] = id;
}
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
if(ciphers == ciphers13 && ciphers12) {
ciphers = ciphers12;
goto add_ciphers;
@@ -585,7 +590,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_NOT_BUILT_IN;
}
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
mbedtls_ctr_drbg_init(&backend->ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
@@ -608,7 +613,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
-ret, errorbuf);
return CURLE_FAILED_INIT;
}
-#endif /* THREADING_SUPPORT */
+#endif /* HAS_THREADING_SUPPORT */
/* Load the trusted CA */
mbedtls_x509_crt_init(&backend->cacert);
@@ -802,7 +807,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED
+#if defined(HAS_SESSION_TICKETS) && MBEDTLS_VERSION_NUMBER >= 0x03060100
/* New in mbedTLS 3.6.1, need to enable, default is now disabled */
mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config,
MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED);
@@ -841,7 +846,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_bio_cf_read,
NULL /* rev_timeout() */);
-#ifndef TLS13_SUPPORT
+#ifndef HAS_TLS13_SUPPORT
if(conn_config->cipher_list) {
CURLcode result = mbed_set_selected_ciphers(data, backend,
conn_config->cipher_list,
@@ -875,29 +880,30 @@ mbed_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 *sdata = NULL;
- size_t slen = 0;
+ struct Curl_ssl_session *sc_session = NULL;
+ CURLcode result;
- Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &sdata, &slen, NULL) && slen) {
+ result = Curl_ssl_scache_take(cf, data, connssl->peer.scache_key,
+ &sc_session);
+ if(!result && sc_session && sc_session->sdata && sc_session->sdata_len) {
mbedtls_ssl_session session;
mbedtls_ssl_session_init(&session);
- ret = mbedtls_ssl_session_load(&session, sdata, slen);
+ ret = mbedtls_ssl_session_load(&session, sc_session->sdata,
+ sc_session->sdata_len);
if(ret) {
- failf(data, "error loading cached session: -0x%x", -ret);
+ failf(data, "SSL session error loading: -0x%x", -ret);
}
else {
ret = mbedtls_ssl_set_session(&backend->ssl, &session);
if(ret)
- failf(data, "error setting session: -0x%x", -ret);
+ failf(data, "SSL session error setting: -0x%x", -ret);
else
infof(data, "SSL reusing session ID");
}
mbedtls_ssl_session_free(&session);
}
- Curl_ssl_sessionid_unlock(data);
+ Curl_ssl_scache_return(cf, data, connssl->peer.scache_key, sc_session);
}
mbedtls_ssl_conf_ca_chain(&backend->config,
@@ -922,7 +928,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
return CURLE_SSL_CONNECT_ERROR;
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
if(connssl->alpn) {
struct alpn_proto_buf proto;
size_t i;
@@ -1100,7 +1106,7 @@ pinnedpubkey_error:
}
}
-#ifdef HAS_ALPN
+#ifdef HAS_ALPN_MBEDTLS
if(connssl->alpn) {
const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
@@ -1115,12 +1121,6 @@ pinnedpubkey_error:
return CURLE_OK;
}
-static void mbedtls_session_free(void *session, size_t slen)
-{
- (void)slen;
- free(session);
-}
-
static CURLcode
mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data)
{
@@ -1128,48 +1128,64 @@ mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data)
struct mbed_ssl_backend_data *backend =
(struct mbed_ssl_backend_data *)connssl->backend;
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
+ mbedtls_ssl_session session;
+ bool msession_alloced = FALSE;
+ struct Curl_ssl_session *sc_session = NULL;
+ unsigned char *sdata = NULL;
+ size_t slen = 0;
+ int ietf_tls_id;
CURLcode result = CURLE_OK;
+ int ret;
DEBUGASSERT(backend);
- if(ssl_config->primary.cache_session) {
- int ret;
- mbedtls_ssl_session session;
- unsigned char *sdata = NULL;
- size_t slen = 0;
+ if(!ssl_config->primary.cache_session)
+ return CURLE_OK;
- mbedtls_ssl_session_init(&session);
- ret = mbedtls_ssl_get_session(&backend->ssl, &session);
- if(ret) {
- if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
- mbedtls_ssl_session_free(&session);
- failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
- return CURLE_SSL_CONNECT_ERROR;
- }
+ mbedtls_ssl_session_init(&session);
+ ret = mbedtls_ssl_get_session(&backend->ssl, &session);
+ msession_alloced = (ret != MBEDTLS_ERR_SSL_ALLOC_FAILED);
+ if(ret) {
+ failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
+ result = CURLE_SSL_CONNECT_ERROR;
+ goto out;
+ }
- mbedtls_ssl_session_save(&session, NULL, 0, &slen);
- if(!slen) {
- failf(data, "failed to serialize session: length is 0");
- }
- else {
- sdata = malloc(slen);
- if(sdata) {
- ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
- if(ret) {
- failf(data, "failed to serialize session: -0x%x", -ret);
- }
- else {
- Curl_ssl_sessionid_lock(data);
- result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, NULL,
- sdata, slen, mbedtls_session_free);
- Curl_ssl_sessionid_unlock(data);
- if(!result)
- sdata = NULL;
- }
- }
- }
- mbedtls_ssl_session_free(&session);
- free(sdata);
+ mbedtls_ssl_session_save(&session, NULL, 0, &slen);
+ if(!slen) {
+ failf(data, "failed to serialize session: length is 0");
+ goto out;
+ }
+
+ sdata = malloc(slen);
+ if(!sdata) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = mbedtls_ssl_session_save(&session, sdata, slen, &slen);
+ if(ret) {
+ failf(data, "failed to serialize session: -0x%x", -ret);
+ goto out;
}
+
+#if MBEDTLS_VERSION_NUMBER >= 0x03020000
+ ietf_tls_id = mbedtls_ssl_get_version_number(&backend->ssl);
+#else
+ ietf_tls_id = CURL_IETF_PROTO_UNKNOWN;
+#endif
+ result = Curl_ssl_session_create(sdata, slen,
+ ietf_tls_id,
+ connssl->negotiated.alpn, 0, 0,
+ &sc_session);
+ sdata = NULL; /* call took ownership */
+ if(!result)
+ result = Curl_ssl_scache_put(cf, data, connssl->peer.scache_key,
+ sc_session);
+
+out:
+ if(msession_alloced)
+ mbedtls_ssl_session_free(&session);
+ free(sdata);
return result;
}
@@ -1184,27 +1200,41 @@ static ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data,
(void)data;
DEBUGASSERT(backend);
+ /* mbedtls is picky when a mbedtls_ssl_write) was previously blocked.
+ * It requires to be called with the same amount of bytes again, or it
+ * will lose bytes, e.g. reporting all was sent but they were not.
+ * Remember the blocked length and use that when set. */
+ if(backend->send_blocked) {
+ DEBUGASSERT(backend->send_blocked_len <= len);
+ CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> previously blocked "
+ "on %zu bytes", len, backend->send_blocked_len);
+ len = backend->send_blocked_len;
+ }
+
ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len);
if(ret < 0) {
CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> -0x%04X",
len, -ret);
*curlcode = ((ret == MBEDTLS_ERR_SSL_WANT_WRITE)
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
|| (ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
#endif
) ? CURLE_AGAIN : CURLE_SEND_ERROR;
ret = -1;
+ if((*curlcode == CURLE_AGAIN) && !backend->send_blocked) {
+ backend->send_blocked = TRUE;
+ backend->send_blocked_len = len;
+ }
+ }
+ else {
+ CURL_TRC_CF(data, cf, "mbedtls_ssl_write(len=%zu) -> %d", len, ret);
+ backend->send_blocked = FALSE;
}
return ret;
}
-static void mbedtls_close_all(struct Curl_easy *data)
-{
- (void)data;
-}
-
static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool send_shutdown, bool *done)
@@ -1260,7 +1290,7 @@ static CURLcode mbedtls_shutdown(struct Curl_cfilter *cf,
* WANT_READ, but has not encountered an EAGAIN. */
if(ret == MBEDTLS_ERR_SSL_WANT_READ)
ret = mbedtls_ssl_read(&backend->ssl, buf, sizeof(buf));
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
if(ret == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
continue;
#endif
@@ -1314,9 +1344,9 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data)
mbedtls_ssl_config_free(&backend->config);
mbedtls_ssl_free(&backend->ssl);
mbedtls_ctr_drbg_free(&backend->ctr_drbg);
-#ifndef THREADING_SUPPORT
+#ifndef HAS_THREADING_SUPPORT
mbedtls_entropy_free(&backend->entropy);
-#endif /* THREADING_SUPPORT */
+#endif /* HAS_THREADING_SUPPORT */
backend->initialized = FALSE;
}
}
@@ -1558,29 +1588,29 @@ static int mbedtls_init(void)
{
if(!Curl_mbedtlsthreadlock_thread_setup())
return 0;
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
entropy_init_mutex(&ts_entropy);
#endif
-#ifdef TLS13_SUPPORT
+#ifdef HAS_PSA_SUPPORT
{
int ret;
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
Curl_mbedtlsthreadlock_lock_function(0);
#endif
ret = psa_crypto_init();
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
Curl_mbedtlsthreadlock_unlock_function(0);
#endif
if(ret != PSA_SUCCESS)
return 0;
}
-#endif /* TLS13_SUPPORT */
+#endif /* HAS_PSA_SUPPORT */
return 1;
}
static void mbedtls_cleanup(void)
{
-#ifdef THREADING_SUPPORT
+#ifdef HAS_THREADING_SUPPORT
entropy_cleanup_mutex(&ts_entropy);
#endif
(void)Curl_mbedtlsthreadlock_thread_cleanup();
@@ -1603,7 +1633,6 @@ 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);
@@ -1637,7 +1666,7 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
SSLSUPP_CERTINFO |
SSLSUPP_PINNEDPUBKEY |
SSLSUPP_SSL_CTX |
-#ifdef TLS13_SUPPORT
+#ifdef HAS_TLS13_SUPPORT
SSLSUPP_TLS13_CIPHERSUITES |
#endif
SSLSUPP_HTTPS_PROXY |
@@ -1648,24 +1677,21 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
mbedtls_init, /* init */
mbedtls_cleanup, /* cleanup */
mbedtls_version, /* version */
- Curl_none_check_cxn, /* check_cxn */
mbedtls_shutdown, /* shutdown */
mbedtls_data_pending, /* data_pending */
mbedtls_random, /* random */
- Curl_none_cert_status_request, /* cert_status_request */
+ NULL, /* cert_status_request */
mbedtls_connect, /* connect */
mbedtls_connect_nonblocking, /* connect_nonblocking */
Curl_ssl_adjust_pollset, /* adjust_pollset */
mbedtls_get_internals, /* get_internals */
mbedtls_close, /* close_one */
- mbedtls_close_all, /* close_all */
- 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 */
+ NULL, /* close_all */
+ NULL, /* set_engine */
+ NULL, /* set_engine_default */
+ NULL, /* engines_list */
+ NULL, /* false_start */
mbedtls_sha256sum, /* sha256sum */
- NULL, /* associate_connection */
- NULL, /* disassociate_connection */
mbed_recv, /* recv decrypted data */
mbed_send, /* send data to encrypt */
NULL, /* get_channel_binding */