Skip to content
Draft
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
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,21 @@ if("${WOLFSSL_HRR_COOKIE}" STREQUAL "yes")
endif()
endif()

# TLS v1.3 middlebox compatibility (RFC 8446 Appendix D.4)
add_option("WOLFSSL_TLS13_MIDDLEBOX_COMPAT"
"Enable TLS v1.3 middlebox compatibility mode (default: disabled)"
"no" "yes;no")

if(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
if(NOT WOLFSSL_TLS13)
message(WARNING "TLS 1.3 is disabled - disabling middlebox compatibility")
override_cache(WOLFSSL_TLS13_MIDDLEBOX_COMPAT "no")
else()
list(APPEND WOLFSSL_DEFINITIONS
"-DWOLFSSL_TLS13_MIDDLEBOX_COMPAT")
endif()
endif()
Comment on lines +714 to +722

# DTLS v1.3
add_option("WOLFSSL_DTLS13"
"Enable wolfSSL DTLS v1.3 (default: disabled)"
Expand Down Expand Up @@ -2982,6 +2997,13 @@ if(WOLFSSL_ECH)
message(FATAL_ERROR "ECH supported only with SNI (WOLFSSL_SNI)")
endif()
list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ECH")
if(WOLFSSL_TLS13_MIDDLEBOX_COMPAT)
message(WARNING
"ECH is incompatible with middlebox compatibility - disabling middlebox compatibility")
override_cache(WOLFSSL_TLS13_MIDDLEBOX_COMPAT "no")
list(REMOVE_ITEM WOLFSSL_DEFINITIONS
"-DWOLFSSL_TLS13_MIDDLEBOX_COMPAT")
endif()
endif()

if(WOLFSSL_KEYING_MATERIAL)
Expand Down
22 changes: 22 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2558,6 +2558,28 @@ then
fi


# TLS v1.3 middlebox compatibility (RFC 8446 Appendix D.4)
AC_ARG_ENABLE([tls13-middlebox-compat],
[AS_HELP_STRING([--enable-tls13-middlebox-compat],[Enable TLS v1.3 middlebox compatibility mode (default: disabled)])],
[ ENABLED_TLS13_MIDDLEBOX_COMPAT=$enableval ],
[ ENABLED_TLS13_MIDDLEBOX_COMPAT=no ]
)
if test "$ENABLED_TLS13_MIDDLEBOX_COMPAT" = "yes"
then
if test "x$ENABLED_TLS13" = "xno"
then
AC_MSG_NOTICE([TLS 1.3 is disabled - disabling middlebox compatibility])
ENABLED_TLS13_MIDDLEBOX_COMPAT="no"
elif test "x$ENABLED_ECH" = "xyes"
then
AC_MSG_NOTICE([ECH is incompatible with middlebox compatibility - disabling middlebox compatibility])
ENABLED_TLS13_MIDDLEBOX_COMPAT="no"
else
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TLS13_MIDDLEBOX_COMPAT"
fi
fi


# RNG
AC_ARG_ENABLE([rng],
[AS_HELP_STRING([--enable-rng],[Enable compiling and using RNG (default: enabled)])],
Expand Down
34 changes: 34 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15318,6 +15318,40 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data,
int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz,
int* outSz);

/*!
\ingroup Setup

\brief This function is called on the server to disable the
RFC 8446 Section 8.2 fresh start protection. By default a freshly
created context rejects early data, but not resumption, for session
tickets minted before the context was created, since the anti-replay
state for those tickets may not have survived a server restart. Only
call this function when the anti-replay state (session cache or
external cache) reliably survives server restarts.

\param [in,out] ctx a pointer to a WOLFSSL_CTX structure, created
with wolfSSL_CTX_new().

\return BAD_FUNC_ARG if ctx is NULL or not using TLS v1.3.
\return SIDE_ERROR if called with a client.
\return 0 if successful.

_Example_
\code
int ret;
WOLFSSL_CTX* ctx;
...
ret = wolfSSL_CTX_no_early_data_fresh_start_check(ctx);
if (ret != 0) {
// failed to disable the fresh start check
}
\endcode

\sa wolfSSL_CTX_set_max_early_data
\sa wolfSSL_read_early_data
*/
int wolfSSL_CTX_no_early_data_fresh_start_check(WOLFSSL_CTX* ctx);

/*!
\ingroup IO

Expand Down
16 changes: 15 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,16 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
}
ctx->timeout = WOLFSSL_SESSION_TIMEOUT;

#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_EARLY_DATA) && \
defined(HAVE_SESSION_TICKET) && !defined(NO_TLS)
/* RFC 8446 Section 8.2: a freshly started server should reject 0-RTT.
* Tickets minted before this time cannot carry early data. Rounded
* down to a whole second because stateful tickets only store second
* resolution. */
ctx->ticketStartTime = TimeNowInMilliseconds();
ctx->ticketStartTime -= ctx->ticketStartTime % 1000;
#endif

#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_TLS_READ_AHEAD)
/* Default the read-ahead window to one full record. Contexts (and the
* WOLFSSL objects that inherit it) then always carry a concrete window, so
Expand Down Expand Up @@ -24592,8 +24602,12 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_EARLY_DATA
if (ssl->options.tls1_3) {
/* RFC 8446 Section 4.2.10: only skip records when
* early data was rejected. After accepting early data
* a decrypt failure is a fatal bad_record_mac. */
if (ssl->options.side == WOLFSSL_SERVER_END &&
ssl->earlyData != no_early_data &&
(ssl->earlyData == early_data_ext ||
ssl->earlyData == expecting_early_data) &&
ssl->options.clientState <
CLIENT_FINISHED_COMPLETE) {
ssl->earlyDataSz += ssl->curSize;
Expand Down
47 changes: 47 additions & 0 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -6522,6 +6522,10 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,

(void)suite;

#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_EARLY_DATA)
ssl->options.ticketPredatesCtx = 0;
#endif

ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
if (ext == NULL) {
WOLFSSL_MSG("No pre shared extension keys found");
Expand Down Expand Up @@ -6650,6 +6654,21 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,

#ifdef WOLFSSL_EARLY_DATA
ssl->options.maxEarlyDataSz = ssl->session->maxEarlyDataSz;
/* RFC 8446 Section 8.2: fresh servers should reject 0-RTT.
* Flag tickets minted before this ctx was created. */
if (!ssl->ctx->noFreshStartCheck) {
#ifdef WOLFSSL_32BIT_MILLI_TIME
/* Wrap-safe: the max ticket age is far below half of the
* 2^32 ms range. */
word32 delta = ssl->ctx->ticketStartTime -
ssl->session->ticketSeen;
ssl->options.ticketPredatesCtx =
(delta != 0 && delta < 0x80000000U);
#else
ssl->options.ticketPredatesCtx =
(ssl->session->ticketSeen < ssl->ctx->ticketStartTime);
#endif
}
#endif
/* Use the same cipher suite as before and set up for use. */
ssl->options.cipherSuite0 = ssl->session->cipherSuite0;
Expand Down Expand Up @@ -6910,6 +6929,12 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
* cert_with_extern_psk, so skip key derivation in that case. */
if (ssl->earlyData != no_early_data && first
&& ssl->options.maxEarlyDataSz > 0
#ifdef HAVE_SESSION_TICKET
/* RFC 8446 section 8.2: freshly started servers should
* reject 0-RTT. Tickets minted before this ctx was created
* belong to a previous instance. */
&& !ssl->options.ticketPredatesCtx
#endif
#ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
&& !hasCertWithExternPsk
#endif
Expand Down Expand Up @@ -16200,6 +16225,28 @@ int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz)
#endif
}

/* Disable the RFC 8446 Section 8.2 fresh start protection. Early data is
* then accepted for tickets minted before this ctx was created. Only use
* this when the anti-replay state reliably survives server restarts.
*
* ctx The SSL/TLS CTX object.
* returns BAD_FUNC_ARG when ctx is NULL or not TLS v1.3, SIDE_ERROR when
* called with a client and 0 on success.
*/
int wolfSSL_CTX_no_early_data_fresh_start_check(WOLFSSL_CTX* ctx)
{
if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version))
return BAD_FUNC_ARG;
if (ctx->method->side == WOLFSSL_CLIENT_END)
return SIDE_ERROR;

#ifdef HAVE_SESSION_TICKET
ctx->noFreshStartCheck = 1;
#endif

return 0;
}

/* Sets the maximum amount of early data that a client or server would like
* to exchange. Servers will advertise this value in session tickets sent
* to a client.
Expand Down
Loading