Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS
WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT
WOLFSSL_DUMP_MEMIO_STREAM
WOLFSSL_DUP_CERTPOL
WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY
WOLFSSL_ECC_BLIND_K
WOLFSSL_ECC_GEN_REJECT_SAMPLING
WOLFSSL_ECC_NO_SMALL_STACK
Expand Down
4 changes: 4 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -14407,6 +14407,10 @@ wolfSSL_accept_TLSv13(WOLFSSL* ssl);
A server value of zero indicates no early data is to be sent by client using
session tickets. A client value of zero indicates that the client will
not send any early data.
The default value is zero: per RFC 8446 Appendix E.5, TLS implementations
"MUST NOT enable 0-RTT (either sending or accepting) unless specifically
requested by the application." Servers must call this function (or the
per-SSL equivalent) with a non-zero value to opt in.
It is recommended that the number of early data bytes be kept as low as
practically possible in the application.

Expand Down
14 changes: 8 additions & 6 deletions examples/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,21 +602,23 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */

#ifdef WOLFSSL_EARLY_DATA
static void EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg,
int msgSz, char* buffer)
static int EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg,
int msgSz, char* buffer)
{
int err;
int ret;

(void)ctx;
(void)buffer;
WOLFSSL_ASYNC_WHILE_PENDING(ret = wolfSSL_write_early_data(ssl, msg, msgSz, &msgSz),
ret <= 0);
if (ret != msgSz) {
err = wolfSSL_get_error(ssl, ret);
LOG_ERROR("SSL_write_early_data msg error %d, %s\n", err,
wolfSSL_ERR_error_string((unsigned long)err, buffer));
wolfSSL_free(ssl); ssl = NULL;
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("SSL_write_early_data failed");
wolfSSL_ERR_error_string((unsigned long)err, buffer));
return -1;
}
return 0;
}
#endif

Expand Down
4 changes: 4 additions & 0 deletions examples/server/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2848,6 +2848,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
err_sys_ex(catastrophic, "can't set minimum downgrade version");
}

#ifdef WOLFSSL_EARLY_DATA
if (earlyData)
wolfSSL_CTX_set_max_early_data(ctx, 4096);
#endif
#ifdef OPENSSL_COMPATIBLE_DEFAULTS
/* Restore wolfSSL verify defaults */
wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_DEFAULT, NULL);
Expand Down
4 changes: 3 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2840,7 +2840,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
#endif

#ifdef WOLFSSL_EARLY_DATA
ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ;
/* RFC 8446 section E.5: 0-RTT off by default; opt in via
* wolfSSL_CTX_set_max_early_data(). */
ctx->maxEarlyDataSz = 0;
#endif

#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
Expand Down
14 changes: 9 additions & 5 deletions src/ssl_sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,8 +3255,12 @@ static void SESSION_ex_data_cache_update(WOLFSSL_SESSION* session, int idx,
#endif

#ifndef NO_SESSION_CACHE
/* OpenSSL-compatible return: 1 if the session was found and removed from the
* internal cache, or if the external remove callback (rem_sess_cb) was
* invoked. 0 if neither applied (not present, or null arguments). */
int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
{
int found = 0;
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
int rem_called = FALSE;
#endif
Expand All @@ -3265,7 +3269,7 @@ int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)

s = ClientSessionToSession(s);
if (ctx == NULL || s == NULL)
return BAD_FUNC_ARG;
return 0;

#ifdef HAVE_EXT_CACHE
if (!ctx->internalCacheOff)
Expand All @@ -3282,6 +3286,7 @@ int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)

ret = TlsSessionCacheGetAndWrLock(id, &sess, &row, ctx->method->side);
if (ret == 0 && sess != NULL) {
found = 1;
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
if (sess->rem_sess_cb != NULL) {
rem_called = TRUE;
Expand Down Expand Up @@ -3320,13 +3325,12 @@ int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s)
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
if (ctx->rem_sess_cb != NULL && !rem_called) {
ctx->rem_sess_cb(ctx, s);
/* Assume the external cache had the session. */
found = 1;
}
#endif

/* s cannot be resumed at this point */
s->timeout = 0;

return 0;
return found;
}

#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
Expand Down
44 changes: 30 additions & 14 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
*
* TLS 1.3 Session Tickets:
* WOLFSSL_TICKET_HAVE_ID: Session tickets include ID default: off
* Forced on when WOLFSSL_EARLY_DATA is set.
* WOLFSSL_TICKET_NONCE_MALLOC: Dynamically allocate ticket nonce default: off
*
* TLS 1.3 Key Exchange:
Expand All @@ -81,6 +82,14 @@

#if !defined(NO_TLS) && defined(WOLFSSL_TLS13)

/* 0-RTT anti-replay eviction needs the session cache. */
#if defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET) && \
defined(NO_SESSION_CACHE) && !defined(NO_WOLFSSL_SERVER) && \
!defined(WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY)
#error "WOLFSSL_EARLY_DATA with tickets requires !NO_SESSION_CACHE, or " \
"define WOLFSSL_EARLY_DATA_NO_ANTI_REPLAY to opt out."
#endif

#ifndef WOLFCRYPT_ONLY

#ifdef HAVE_ERRNO_H
Expand Down Expand Up @@ -5901,8 +5910,11 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input,
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData != no_early_data) {
TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
if (ext == NULL || !ext->val)
if (ext == NULL || !ext->val) {
WOLFSSL_MSG("Early data rejected by server (no early_data "
"EncryptedExtensions response)");
ssl->earlyData = no_early_data;
}
}

if (ssl->earlyData == no_early_data) {
Expand Down Expand Up @@ -6377,18 +6389,6 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,
/* This PSK works, no need to try any more. */
current->chosen = 1;
ext->resp = 1;
#if defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET) && \
!defined(NO_SESSION_CACHE)
/* RFC 8446 section 8: accept 0-RTT for a given handshake at most
* once. Evict the session from both the internal cache (under a
* write lock) and any external cache (via ctx->rem_sess_cb) so
* the same ClientHello cannot replay early data. Only when the
* client offered 0-RTT on a session that permits it. */
if (ssl->earlyData != no_early_data &&
ssl->session->maxEarlyDataSz != 0) {
(void)wolfSSL_SSL_CTX_remove_session(ssl->ctx, ssl->session);
}
#endif
break;
}

Expand Down Expand Up @@ -6549,8 +6549,16 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
* RFC 8773bis: early_data is not compatible with
* cert_with_extern_psk, so skip key derivation in that case. */
if (ssl->earlyData != no_early_data && first
&& ssl->options.maxEarlyDataSz > 0
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
&& !hasCertWithExternPsk
#endif
#if defined(HAVE_SESSION_TICKET) && !defined(NO_SESSION_CACHE)
/* RFC 8446 section 8: evict the session from the cache.
* Accept 0-RTT only when the eviction found the entry
* (single-use). */
&& wolfSSL_SSL_CTX_remove_session(ssl->ctx, ssl->session)
== 1
Comment thread
julek-wolfssl marked this conversation as resolved.
#endif
) {
extEarlyData->resp = 1;
Expand Down Expand Up @@ -6613,6 +6621,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
* combination in the ClientHello, but clear the response flag
* here as a defense-in-depth measure. */
if (extEarlyData != NULL) {
WOLFSSL_MSG("Rejecting early data: "
"cert_with_extern_psk is not 0-RTT compatible");
extEarlyData->resp = 0;
ssl->earlyData = no_early_data;
}
Expand Down Expand Up @@ -15388,7 +15398,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
#ifdef HAVE_SESSION_TICKET
#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
if (!ssl->options.verifyPeer && !ssl->options.noTicketTls13 &&
ssl->ctx->ticketEncCb != NULL) {
ssl->ctx->ticketEncCb != NULL &&
ssl->options.maxTicketTls13 > 0) {
if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) {
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
Expand Down Expand Up @@ -15529,6 +15540,11 @@ int wolfSSL_send_SessionTicket(WOLFSSL* ssl)
* A value of zero indicates no early data is to be sent by client using session
* tickets.
*
* The default value is zero: per RFC 8446 Appendix E.5, TLS implementations
* "MUST NOT enable 0-RTT (either sending or accepting) unless specifically
* requested by the application." Servers must explicitly opt in by calling
* this function (or the per-SSL equivalent) with a non-zero value.
*
* ctx The SSL/TLS CTX object.
* sz Maximum size of the early data.
* returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and
Expand Down
10 changes: 6 additions & 4 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -18689,8 +18689,9 @@ static int test_wolfSSL_CTX_sess_set_remove_cb(void)
/* Force a cache update */
ExpectNotNull(SSL_SESSION_set_ex_data(clientSess, serverSessRemIdx - 1, 0));
/* This should set the timeout to 0 and call the remove callback from within
* the session cache. */
ExpectIntEQ(SSL_CTX_remove_session(clientSessCtx, clientSess), 0);
* the session cache. Returns 1 per OpenSSL semantics (session was
* present in the cache and removed). */
ExpectIntEQ(SSL_CTX_remove_session(clientSessCtx, clientSess), 1);
ExpectNull(SSL_SESSION_get_ex_data(clientSess, serverSessRemIdx));
ExpectIntEQ(clientSessRemCountFree, 1);
#endif
Expand All @@ -18702,8 +18703,9 @@ static int test_wolfSSL_CTX_sess_set_remove_cb(void)
/* Force a cache update */
ExpectNotNull(SSL_SESSION_set_ex_data(serverSess, serverSessRemIdx - 1, 0));
/* This should set the timeout to 0 and call the remove callback from within
* the session cache. */
ExpectIntEQ(SSL_CTX_remove_session(serverSessCtx, serverSess), 0);
* the session cache. Returns 1 per OpenSSL semantics (session was
* present in the cache and removed). */
ExpectIntEQ(SSL_CTX_remove_session(serverSessCtx, serverSess), 1);
ExpectNull(SSL_SESSION_get_ex_data(serverSess, serverSessRemIdx));
ExpectIntEQ(serverSessRemCountFree, 1);
/* Need to free the references that we kept */
Expand Down
Loading
Loading