vtls: move common early data code into vtls.c

With now 2 backends implementing early data, it makes sense to have the
common handling in a single place.

Closes #16450
This commit is contained in:
Stefan Eissing 2025-02-24 13:35:20 +01:00 committed by Daniel Stenberg
parent a1d00da81e
commit 4ed9db9eef
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
4 changed files with 171 additions and 252 deletions

View File

@ -1064,7 +1064,7 @@ static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf,
else { else {
infof(data, "SSL session allows %zu bytes of early data, " infof(data, "SSL session allows %zu bytes of early data, "
"reusing ALPN '%s'", connssl->earlydata_max, scs->alpn); "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
connssl->earlydata_state = ssl_earlydata_use; connssl->earlydata_state = ssl_earlydata_await;
connssl->state = ssl_connection_deferred; connssl->state = ssl_connection_deferred;
result = Curl_alpn_set_negotiated(cf, data, connssl, result = Curl_alpn_set_negotiated(cf, data, connssl,
(const unsigned char *)scs->alpn, (const unsigned char *)scs->alpn,
@ -1756,30 +1756,6 @@ out:
return result; return result;
} }
static CURLcode gtls_set_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen)
{
struct ssl_connect_data *connssl = cf->ctx;
ssize_t nwritten = 0;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_use);
DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
if(blen) {
if(blen > connssl->earlydata_max)
blen = connssl->earlydata_max;
nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
CURL_TRC_CF(data, cf, "gtls_set_earlydata(len=%zu) -> %zd",
blen, nwritten);
if(nwritten < 0)
return result;
}
connssl->earlydata_state = ssl_earlydata_sending;
connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
return CURLE_OK;
}
static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf, static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data) struct Curl_easy *data)
{ {
@ -1855,7 +1831,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
} }
if(connssl->connecting_state == ssl_connect_2) { if(connssl->connecting_state == ssl_connect_2) {
if(connssl->earlydata_state == ssl_earlydata_use) { if(connssl->earlydata_state == ssl_earlydata_await) {
goto out; goto out;
} }
else if(connssl->earlydata_state == ssl_earlydata_sending) { else if(connssl->earlydata_state == ssl_earlydata_sending) {
@ -1863,8 +1839,6 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result) if(result)
goto out; goto out;
connssl->earlydata_state = ssl_earlydata_sent; connssl->earlydata_state = ssl_earlydata_sent;
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip);
} }
DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) || DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
(connssl->earlydata_state == ssl_earlydata_sent)); (connssl->earlydata_state == ssl_earlydata_sent));
@ -1896,31 +1870,19 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf,
if(result) if(result)
goto out; goto out;
if(connssl->earlydata_state == ssl_earlydata_sent) { if(connssl->earlydata_state > ssl_earlydata_none) {
/* report the true time the handshake was done */ /* We should be in this state by now */
connssl->handshake_done = Curl_now(); DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done); connssl->earlydata_state =
if(gnutls_session_get_flags(backend->gtls.session) & (gnutls_session_get_flags(backend->gtls.session) &
GNUTLS_SFLAGS_EARLY_DATA) { GNUTLS_SFLAGS_EARLY_DATA) ?
connssl->earlydata_state = ssl_earlydata_accepted; ssl_earlydata_accepted : ssl_earlydata_rejected;
infof(data, "Server accepted %zu bytes of TLS early data.",
connssl->earlydata_skip);
}
else {
connssl->earlydata_state = ssl_earlydata_rejected;
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
infof(data, "Server rejected TLS early data.");
connssl->earlydata_skip = 0;
}
} }
connssl->connecting_state = ssl_connect_done; connssl->connecting_state = ssl_connect_done;
} }
if(ssl_connect_done == connssl->connecting_state) { if(connssl->connecting_state == ssl_connect_done)
connssl->state = ssl_connection_complete; DEBUGASSERT(connssl->state == ssl_connection_complete);
*done = TRUE;
}
out: out:
if(result == CURLE_AGAIN) { if(result == CURLE_AGAIN) {
@ -1938,7 +1900,8 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
bool *done) bool *done)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
if(connssl->state == ssl_connection_deferred) { if((connssl->state == ssl_connection_deferred) &&
(connssl->earlydata_state == ssl_earlydata_await)) {
/* We refuse to be pushed, we are waiting for someone to send/recv. */ /* We refuse to be pushed, we are waiting for someone to send/recv. */
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
@ -1946,26 +1909,6 @@ static CURLcode gtls_connect(struct Curl_cfilter *cf,
return gtls_connect_common(cf, data, done); return gtls_connect_common(cf, data, done);
} }
static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf,
size_t blen,
bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->state == ssl_connection_deferred);
*done = FALSE;
if(connssl->earlydata_state == ssl_earlydata_use) {
result = gtls_set_earlydata(cf, data, buf, blen);
if(result)
return result;
}
return gtls_connect_common(cf, data, done);
}
static bool gtls_data_pending(struct Curl_cfilter *cf, static bool gtls_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data) const struct Curl_easy *data)
{ {
@ -1993,38 +1936,9 @@ static ssize_t gtls_send(struct Curl_cfilter *cf,
ssize_t rc; ssize_t rc;
size_t nwritten, total_written = 0; size_t nwritten, total_written = 0;
(void)data;
DEBUGASSERT(backend); DEBUGASSERT(backend);
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*curlcode = gtls_connect_deferred(cf, data, buf, blen, &done);
if(*curlcode) {
rc = -1;
goto out;
}
else if(!done) {
*curlcode = CURLE_AGAIN;
rc = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
if(connssl->earlydata_skip) {
if(connssl->earlydata_skip >= blen) {
connssl->earlydata_skip -= blen;
*curlcode = CURLE_OK;
rc = (ssize_t)blen;
goto out;
}
else {
total_written += connssl->earlydata_skip;
buf = ((const char *)buf) + connssl->earlydata_skip;
blen -= connssl->earlydata_skip;
connssl->earlydata_skip = 0;
}
}
while(blen) { while(blen) {
backend->gtls.io_result = CURLE_OK; backend->gtls.io_result = CURLE_OK;
rc = gnutls_record_send(backend->gtls.session, buf, blen); rc = gnutls_record_send(backend->gtls.session, buf, blen);
@ -2171,21 +2085,6 @@ static ssize_t gtls_recv(struct Curl_cfilter *cf,
(void)data; (void)data;
DEBUGASSERT(backend); DEBUGASSERT(backend);
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*curlcode = gtls_connect_deferred(cf, data, NULL, 0, &done);
if(*curlcode) {
ret = -1;
goto out;
}
else if(!done) {
*curlcode = CURLE_AGAIN;
ret = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
ret = gnutls_record_recv(backend->gtls.session, buf, buffersize); ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) { if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = CURLE_AGAIN; *curlcode = CURLE_AGAIN;

View File

@ -485,18 +485,6 @@ static void cf_ctx_free(struct ssl_connect_data *ctx)
} }
} }
static CURLcode
ssl_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
/* mark this is being ssl requested from here on. */
return connssl->ssl_impl->do_connect(cf, data, done);
}
CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex, CURLcode Curl_ssl_get_channel_binding(struct Curl_easy *data, int sockindex,
struct dynbuf *binding) struct dynbuf *binding)
{ {
@ -1318,7 +1306,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
struct cf_call_data save; struct cf_call_data save;
CURLcode result; CURLcode result;
if(cf->connected) { if(cf->connected && (connssl->state != ssl_connection_deferred)) {
*done = TRUE; *done = TRUE;
return CURLE_OK; return CURLE_OK;
} }
@ -1336,8 +1324,6 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data); CF_DATA_SAVE(save, cf, data);
CURL_TRC_CF(data, cf, "cf_connect()"); CURL_TRC_CF(data, cf, "cf_connect()");
DEBUGASSERT(data->conn);
DEBUGASSERT(data->conn == cf->conn);
DEBUGASSERT(connssl); DEBUGASSERT(connssl);
*done = FALSE; *done = FALSE;
@ -1349,7 +1335,13 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
goto out; goto out;
} }
result = ssl_connect(cf, data, done); if(!connssl->prefs_checked) {
if(!ssl_prefs_check(data))
return CURLE_SSL_CONNECT_ERROR;
connssl->prefs_checked = TRUE;
}
result = connssl->ssl_impl->do_connect(cf, data, done);
if(!result && *done) { if(!result && *done) {
cf->connected = TRUE; cf->connected = TRUE;
@ -1358,6 +1350,8 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
/* Connection can be deferred when sending early data */ /* Connection can be deferred when sending early data */
DEBUGASSERT(connssl->state == ssl_connection_complete || DEBUGASSERT(connssl->state == ssl_connection_complete ||
connssl->state == ssl_connection_deferred); connssl->state == ssl_connection_deferred);
DEBUGASSERT(connssl->state != ssl_connection_deferred ||
connssl->earlydata_state > ssl_earlydata_none);
} }
out: out:
CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done); CURL_TRC_CF(data, cf, "cf_connect() -> %d, done=%d", result, *done);
@ -1365,6 +1359,77 @@ out:
return result; return result;
} }
static CURLcode ssl_cf_set_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen)
{
struct ssl_connect_data *connssl = cf->ctx;
ssize_t nwritten = 0;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_await);
DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
if(blen) {
if(blen > connssl->earlydata_max)
blen = connssl->earlydata_max;
nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
CURL_TRC_CF(data, cf, "ssl_cf_set_earlydata(len=%zu) -> %zd",
blen, nwritten);
if(nwritten < 0)
return result;
}
return CURLE_OK;
}
static CURLcode ssl_cf_connect_deferred(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen,
bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->state == ssl_connection_deferred);
*done = FALSE;
if(connssl->earlydata_state == ssl_earlydata_await) {
result = ssl_cf_set_earlydata(cf, data, buf, blen);
if(result)
return result;
/* we buffered any early data we'd like to send. Actually
* do the connect now which sends it and performs the handshake. */
connssl->earlydata_state = ssl_earlydata_sending;
connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
}
result = ssl_cf_connect(cf, data, done);
if(!result && *done) {
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done);
switch(connssl->earlydata_state) {
case ssl_earlydata_none:
break;
case ssl_earlydata_accepted:
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip);
infof(data, "Server accepted %zu bytes of TLS early data.",
connssl->earlydata_skip);
break;
case ssl_earlydata_rejected:
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
infof(data, "Server rejected TLS early data.");
connssl->earlydata_skip = 0;
break;
default:
/* This should not happen. Either we do not use early data or we
* should know if it was accepted or not. */
DEBUGASSERT(NULL);
break;
}
}
return result;
}
static bool ssl_cf_data_pending(struct Curl_cfilter *cf, static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data) const struct Curl_easy *data)
{ {
@ -1383,21 +1448,57 @@ static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
} }
static ssize_t ssl_cf_send(struct Curl_cfilter *cf, static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
struct Curl_easy *data, const void *buf, size_t len, struct Curl_easy *data,
const void *buf, size_t blen,
bool eos, CURLcode *err) bool eos, CURLcode *err)
{ {
struct ssl_connect_data *connssl = cf->ctx; struct ssl_connect_data *connssl = cf->ctx;
struct cf_call_data save; struct cf_call_data save;
ssize_t nwritten = 0; ssize_t nwritten = 0, early_written = 0;
(void)eos; (void)eos;
/* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
*err = CURLE_OK; *err = CURLE_OK;
if(len > 0) { CF_DATA_SAVE(save, cf, data);
CF_DATA_SAVE(save, cf, data);
nwritten = connssl->ssl_impl->send_plain(cf, data, buf, len, err); if(connssl->state == ssl_connection_deferred) {
CF_DATA_RESTORE(cf, save); bool done = FALSE;
*err = ssl_cf_connect_deferred(cf, data, buf, blen, &done);
if(*err) {
nwritten = -1;
goto out;
}
else if(!done) {
*err = CURLE_AGAIN;
nwritten = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
} }
if(connssl->earlydata_skip) {
if(connssl->earlydata_skip >= blen) {
connssl->earlydata_skip -= blen;
*err = CURLE_OK;
nwritten = (ssize_t)blen;
goto out;
}
else {
early_written = connssl->earlydata_skip;
buf = ((const char *)buf) + connssl->earlydata_skip;
blen -= connssl->earlydata_skip;
connssl->earlydata_skip = 0;
}
}
/* OpenSSL and maybe other TLS libs do not like 0-length writes. Skip. */
if(blen > 0)
nwritten = connssl->ssl_impl->send_plain(cf, data, buf, blen, err);
if(nwritten >= 0)
nwritten += early_written;
out:
CF_DATA_RESTORE(cf, save);
return nwritten; return nwritten;
} }
@ -1411,6 +1512,21 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
CF_DATA_SAVE(save, cf, data); CF_DATA_SAVE(save, cf, data);
*err = CURLE_OK; *err = CURLE_OK;
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*err = ssl_cf_connect_deferred(cf, data, NULL, 0, &done);
if(*err) {
nread = -1;
goto out;
}
else if(!done) {
*err = CURLE_AGAIN;
nread = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, err); nread = connssl->ssl_impl->recv_plain(cf, data, buf, len, err);
if(nread > 0) { if(nread > 0) {
DEBUGASSERT((size_t)nread <= len); DEBUGASSERT((size_t)nread <= len);
@ -1419,6 +1535,8 @@ static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
/* eof */ /* eof */
*err = CURLE_OK; *err = CURLE_OK;
} }
out:
CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len, CURL_TRC_CF(data, cf, "cf_recv(len=%zu) -> %zd, %d", len,
nread, *err); nread, *err);
CF_DATA_RESTORE(cf, save); CF_DATA_RESTORE(cf, save);
@ -1433,7 +1551,9 @@ static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf,
CURLcode result = CURLE_OK; CURLcode result = CURLE_OK;
*done = TRUE; *done = TRUE;
if(!cf->shutdown && Curl_ssl->shut_down) { /* If we have done the SSL handshake, shut down the connection cleanly */
if(cf->connected && (connssl->state == ssl_connection_complete) &&
!cf->shutdown && Curl_ssl->shut_down) {
struct cf_call_data save; struct cf_call_data save;
CF_DATA_SAVE(save, cf, data); CF_DATA_SAVE(save, cf, data);

View File

@ -91,7 +91,7 @@ typedef enum {
typedef enum { typedef enum {
ssl_earlydata_none, ssl_earlydata_none,
ssl_earlydata_use, ssl_earlydata_await,
ssl_earlydata_sending, ssl_earlydata_sending,
ssl_earlydata_sent, ssl_earlydata_sent,
ssl_earlydata_accepted, ssl_earlydata_accepted,
@ -126,6 +126,7 @@ struct ssl_connect_data {
int io_need; /* TLS signals special SEND/RECV needs */ int io_need; /* TLS signals special SEND/RECV needs */
BIT(use_alpn); /* if ALPN shall be used in handshake */ BIT(use_alpn); /* if ALPN shall be used in handshake */
BIT(peer_closed); /* peer has closed connection */ BIT(peer_closed); /* peer has closed connection */
BIT(prefs_checked); /* SSL preferences have been checked */
}; };

View File

@ -525,7 +525,7 @@ static CURLcode wssl_on_session_reuse(struct Curl_cfilter *cf,
else { else {
infof(data, "SSL session allows %zu bytes of early data, " infof(data, "SSL session allows %zu bytes of early data, "
"reusing ALPN '%s'", connssl->earlydata_max, scs->alpn); "reusing ALPN '%s'", connssl->earlydata_max, scs->alpn);
connssl->earlydata_state = ssl_earlydata_use; connssl->earlydata_state = ssl_earlydata_await;
connssl->state = ssl_connection_deferred; connssl->state = ssl_connection_deferred;
result = Curl_alpn_set_negotiated(cf, data, connssl, result = Curl_alpn_set_negotiated(cf, data, connssl,
(const unsigned char *)scs->alpn, (const unsigned char *)scs->alpn,
@ -1662,6 +1662,8 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf,
} }
DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) || DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
(connssl->earlydata_state == ssl_earlydata_sent)); (connssl->earlydata_state == ssl_earlydata_sent));
#else
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_none);
#endif /* WOLFSSL_EARLY_DATA */ #endif /* WOLFSSL_EARLY_DATA */
wolfSSL_ERR_clear_error(); wolfSSL_ERR_clear_error();
@ -1788,52 +1790,6 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf,
} }
} }
#ifdef WOLFSSL_EARLY_DATA
static CURLcode wssl_set_earlydata(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf, size_t blen)
{
struct ssl_connect_data *connssl = cf->ctx;
ssize_t nwritten = 0;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_use);
DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
if(blen) {
if(blen > connssl->earlydata_max)
blen = connssl->earlydata_max;
nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
CURL_TRC_CF(data, cf, "wssl_set_earlydata(len=%zu) -> %zd",
blen, nwritten);
if(nwritten < 0)
return result;
}
connssl->earlydata_state = ssl_earlydata_sending;
connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
return CURLE_OK;
}
static CURLcode wssl_connect_deferred(struct Curl_cfilter *cf,
struct Curl_easy *data,
const void *buf,
size_t blen,
bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
DEBUGASSERT(connssl->state == ssl_connection_deferred);
*done = FALSE;
if(connssl->earlydata_state == ssl_earlydata_use) {
result = wssl_set_earlydata(cf, data, buf, blen);
if(result)
return result;
}
return wssl_connect(cf, data, done);
}
#endif /* WOLFSSL_EARLY_DATA */
static ssize_t wssl_send(struct Curl_cfilter *cf, static ssize_t wssl_send(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
const void *buf, size_t blen, const void *buf, size_t blen,
@ -1847,38 +1803,6 @@ static ssize_t wssl_send(struct Curl_cfilter *cf,
wolfSSL_ERR_clear_error(); wolfSSL_ERR_clear_error();
#ifdef WOLFSSL_EARLY_DATA
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*curlcode = wssl_connect_deferred(cf, data, buf, blen, &done);
if(*curlcode) {
nwritten = -1;
goto out;
}
else if(!done) {
*curlcode = CURLE_AGAIN;
nwritten = -1;
goto out;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
if(connssl->earlydata_skip) {
if(connssl->earlydata_skip >= blen) {
connssl->earlydata_skip -= blen;
*curlcode = CURLE_OK;
nwritten = (ssize_t)blen;
goto out;
}
else {
total_written += connssl->earlydata_skip;
buf = ((const char *)buf) + connssl->earlydata_skip;
blen -= connssl->earlydata_skip;
connssl->earlydata_skip = 0;
}
}
#endif /* WOLFSSL_EARLY_DATA */
if(blen) { if(blen) {
int memlen = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen; int memlen = (blen > (size_t)INT_MAX) ? INT_MAX : (int)blen;
int rc; int rc;
@ -2071,21 +1995,6 @@ static ssize_t wssl_recv(struct Curl_cfilter *cf,
DEBUGASSERT(wssl); DEBUGASSERT(wssl);
#ifdef WOLFSSL_EARLY_DATA
if(connssl->state == ssl_connection_deferred) {
bool done = FALSE;
*curlcode = wssl_connect_deferred(cf, data, NULL, 0, &done);
if(*curlcode) {
return -1;
}
else if(!done) {
*curlcode = CURLE_AGAIN;
return-1;
}
DEBUGASSERT(connssl->state == ssl_connection_complete);
}
#endif
wolfSSL_ERR_clear_error(); wolfSSL_ERR_clear_error();
*curlcode = CURLE_OK; *curlcode = CURLE_OK;
@ -2212,7 +2121,7 @@ static CURLcode wssl_connect(struct Curl_cfilter *cf,
} }
if(ssl_connect_2 == connssl->connecting_state) { if(ssl_connect_2 == connssl->connecting_state) {
if(connssl->earlydata_state == ssl_earlydata_use) { if(connssl->earlydata_state == ssl_earlydata_await) {
/* We defer the handshake until request data arrives. */ /* We defer the handshake until request data arrives. */
DEBUGASSERT(connssl->state == ssl_connection_deferred); DEBUGASSERT(connssl->state == ssl_connection_deferred);
goto out; goto out;
@ -2272,23 +2181,13 @@ static CURLcode wssl_connect(struct Curl_cfilter *cf,
connssl->state = ssl_connection_complete; connssl->state = ssl_connection_complete;
#ifdef WOLFSSL_EARLY_DATA #ifdef WOLFSSL_EARLY_DATA
if(connssl->earlydata_state == ssl_earlydata_sent) { if(connssl->earlydata_state > ssl_earlydata_none) {
/* report the true time the handshake was done */ /* We should be in this state by now */
connssl->handshake_done = Curl_now(); DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sent);
Curl_pgrsTimeWas(data, TIMER_APPCONNECT, connssl->handshake_done); connssl->earlydata_state =
if(wolfSSL_get_early_data_status(wssl->ssl) == (wolfSSL_get_early_data_status(wssl->ssl) ==
WOLFSSL_EARLY_DATA_REJECTED) { WOLFSSL_EARLY_DATA_REJECTED) ?
connssl->earlydata_state = ssl_earlydata_rejected; ssl_earlydata_rejected : ssl_earlydata_accepted;
if(!Curl_ssl_cf_is_proxy(cf))
Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
infof(data, "Server rejected TLS early data.");
connssl->earlydata_skip = 0;
}
else if(connssl->earlydata_skip) {
connssl->earlydata_state = ssl_earlydata_accepted;
infof(data, "Server accepted %zu bytes of TLS early data.",
connssl->earlydata_skip);
}
} }
#endif /* WOLFSSL_EARLY_DATA */ #endif /* WOLFSSL_EARLY_DATA */
} }