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
21 changes: 21 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -8886,6 +8886,26 @@ AC_ARG_ENABLE([secure-renegotiation-info],
[ ENABLED_SECURE_RENEGOTIATION_INFO=yes ]
)

# Legacy Server Connect
# By default a TLS 1.2 client requires the server to acknowledge the
# renegotiation_info extension on the initial handshake (RFC 5746 / RFC 9325).
# Enable this option to also connect to legacy servers that do not support
# secure renegotiation (not recommended).
AC_ARG_ENABLE([legacy-server-connect],
[AS_HELP_STRING([--enable-legacy-server-connect],[Allow connecting to servers that do not support secure renegotiation (default: disabled)])],
[ ENABLED_LEGACY_SERVER_CONNECT=$enableval ],
[ ENABLED_LEGACY_SERVER_CONNECT=no ]
)

if test "x$ENABLED_LEGACY_SERVER_CONNECT" = "xyes"
then
if test "x$ENABLED_HARDEN_TLS" != "xno"
then
AC_MSG_ERROR([--enable-legacy-server-connect conflicts with --enable-harden-tls (RFC 9325 3.5). Define WOLFSSL_HARDEN_TLS_NO_SCR_CHECK directly if this is intended.])
fi
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALLOW_LEGACY_SERVER_CONNECT"
fi


# Exporting Keying Material
AC_ARG_ENABLE([keying-material],
Expand Down Expand Up @@ -13613,6 +13633,7 @@ echo " * Session Ticket: $ENABLED_SESSION_TICKET"
echo " * Extended Master Secret: $ENABLED_EXTENDED_MASTER"
echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION"
echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION"
echo " * Legacy Server Connect: $ENABLED_LEGACY_SERVER_CONNECT"
echo " * Keying Material Exporter: $ENABLED_KEYING_MATERIAL"
echo " * All TLS Extensions: $ENABLED_TLSX"
echo " * S/MIME: $ENABLED_SMIME"
Expand Down
117 changes: 97 additions & 20 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -2699,6 +2699,17 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
ctx->minMlDsaKeySz = MIN_MLDSAKEY_SZ;
#endif /* WOLFSSL_HAVE_MLDSA */
ctx->verifyDepth = MAX_CHAIN_DEPTH;
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
!defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
!defined(WOLFSSL_ALLOW_LEGACY_SERVER_CONNECT)
/* RFC 5746 / RFC 9325: a TLS 1.2 client requires the server to acknowledge
* the renegotiation_info extension on the initial handshake. Enabled by
* default; define WOLFSSL_ALLOW_LEGACY_SERVER_CONNECT (or call
* wolfSSL_CTX_set_scr_check_enabled(ctx, 0)) to connect to servers that do
* not support secure renegotiation. */
ctx->scr_check_enabled = 1;
#endif
#ifdef OPENSSL_EXTRA
ctx->cbioFlag = WOLFSSL_CBIO_NONE;
#endif
Expand Down Expand Up @@ -8023,6 +8034,58 @@ static void InitSSL_Multicast(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
}
#endif /* WOLFSSL_MULTICAST */

#if defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)
/* Set up the client's renegotiation_info advertising. Shared by InitSSL and the
* ClientHello send paths so the "advertise implies enforce" invariant survives
* WOLFSSL object reuse: without re-advertising after wolfSSL_clear the client
* would send no renegotiation_info yet still enforce its presence, failing
* every reused-object handshake.
*
* Willingness to perform a peer-initiated renegotiation is derived from
* ssl->ctx->useSecureReneg. A per-object wolfSSL_UseSecureRenegotiation() opt-in
* is not tracked here, so after wolfSSL_clear a reused object reverts to
* advertise-only; applications that renegotiate on reused objects should opt in
* at the context level with wolfSSL_CTX_UseSecureRenegotiation(). */
int SetupClientSecureRenegotiation(WOLFSSL* ssl)
{
int ret = WOLFSSL_SUCCESS;

if (ssl->options.side == WOLFSSL_CLIENT_END) {
int useSecureReneg = ssl->ctx->useSecureReneg;
#ifdef HAVE_SECURE_RENEGOTIATION
int advertiseOnly = 0;
#endif
/* Advertise the empty renegotiation_info extension by default so the
* client can enforce RFC 5746 / RFC 9325 on the initial handshake.
* Advertising is always safe: legacy servers ignore it and secure
* servers echo it. */
#if defined(WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT)
/* Integrator asked for secure renegotiation by default: keep the full
* renegotiation behavior (advertiseOnly stays 0). */
useSecureReneg = 1;
#elif !defined(WOLFSSL_NO_TLS12) && defined(HAVE_SERVER_RENEGOTIATION_INFO)
#ifdef HAVE_SECURE_RENEGOTIATION
/* Advertising was forced on for the RFC 5746 check, not requested by
* the application, so do not also grant willingness to perform a
* peer-initiated renegotiation. */
if (!useSecureReneg)
advertiseOnly = 1;
#endif
useSecureReneg = 1;
#endif
if (useSecureReneg) {
ret = wolfSSL_UseSecureRenegotiation(ssl);
#ifdef HAVE_SECURE_RENEGOTIATION
if (ret == WOLFSSL_SUCCESS && ssl->secure_renegotiation != NULL)
ssl->secure_renegotiation->advertiseOnly = (byte)advertiseOnly;
#endif
}
}

return ret;
}
#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */

int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
{
int ret;
Expand Down Expand Up @@ -8239,8 +8302,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->disabledCurves = ctx->disabledCurves;
#endif
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
ssl->scr_check_enabled = 1;
defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
!defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
/* Inherit the renegotiation_info enforcement setting from the context. */
ssl->scr_check_enabled = ctx->scr_check_enabled;
#endif

InitCiphers(ssl);
Expand Down Expand Up @@ -8366,20 +8431,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)

#if defined(HAVE_SECURE_RENEGOTIATION) || \
defined(HAVE_SERVER_RENEGOTIATION_INFO)
if (ssl->options.side == WOLFSSL_CLIENT_END) {
int useSecureReneg = ssl->ctx->useSecureReneg;
/* use secure renegotiation by default (not recommend) */
#if defined(WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT) || \
(defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_NO_TLS12) && \
!defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK))
useSecureReneg = 1;
#endif
if (useSecureReneg) {
ret = wolfSSL_UseSecureRenegotiation(ssl);
if (ret != WOLFSSL_SUCCESS)
return ret;
}
}
ret = SetupClientSecureRenegotiation(ssl);
if (ret != WOLFSSL_SUCCESS)
return ret;
#endif /* HAVE_SECURE_RENEGOTIATION */

#ifdef WOLFSSL_QUIC
Expand Down Expand Up @@ -9428,7 +9482,10 @@ void FreeHandshakeResources(WOLFSSL* ssl)
#endif

#ifdef HAVE_SECURE_RENEGOTIATION
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
/* advertiseOnly clients never renegotiate, so do not retain (and leave
* unzeroed) the master secret and other handshake resources for them. */
if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
!ssl->secure_renegotiation->advertiseOnly) {
WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
return;
}
Expand Down Expand Up @@ -18573,8 +18630,13 @@ static int DoHelloRequest(WOLFSSL* ssl, word32 size)
return FATAL_ERROR;
}
#ifdef HAVE_SECURE_RENEGOTIATION
else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
/* WOLFSSL_OP_NO_RENEGOTIATION: caller opted into rejecting
else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
!ssl->secure_renegotiation->advertiseOnly) {
/* advertiseOnly: renegotiation_info was advertised only for the RFC
* 5746 initial-handshake check, so the application did not opt into
* secure renegotiation; the else branch below refuses the request.
*
* WOLFSSL_OP_NO_RENEGOTIATION: caller opted into rejecting
* peer-initiated renegotiation. Respond with a no_renegotiation
* warning alert instead of starting a secure renegotiation. */
if (ssl->options.mask & WOLFSSL_OP_NO_RENEGOTIATION) {
Expand Down Expand Up @@ -32654,6 +32716,17 @@ static void MakePSKPreMasterSecret(Arrays* arrays, byte use_psk_key)
return BAD_FUNC_ARG;
}

#if defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)
/* Re-establish renegotiation_info advertising for a reused object
* (wolfSSL_clear frees it). Only when absent, so an in-progress
* renegotiation keeps its verify_data state. */
if (ssl->secure_renegotiation == NULL) {
ret = SetupClientSecureRenegotiation(ssl);
if (ret != WOLFSSL_SUCCESS)
return ret;
}
#endif

#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(ssl->version))
return SendTls13ClientHello(ssl);
Expand Down Expand Up @@ -33346,14 +33419,18 @@ static void MakePSKPreMasterSecret(Arrays* arrays, byte use_psk_key)
}
#endif /* HAVE_TLS_EXTENSIONS */

#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
!defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
if (ssl->scr_check_enabled && (ssl->secure_renegotiation == NULL ||
!ssl->secure_renegotiation->enabled)) {
/* If the server does not acknowledge the extension, the client
* MUST generate a fatal handshake_failure alert prior to
* terminating the connection.
* https://www.rfc-editor.org/rfc/rfc9325#name-renegotiation-in-tls-12 */
WOLFSSL_MSG("ServerHello did not contain SCR extension");
WOLFSSL_ERROR_VERBOSE(SECURE_RENEGOTIATION_E);
(void)SendAlert(ssl, alert_fatal, handshake_failure);
return SECURE_RENEGOTIATION_E;
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5667,6 +5667,9 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
#if defined(HAVE_SECURE_RENEGOTIATION) \
|| defined(HAVE_SERVER_RENEGOTIATION_INFO)
ssl->secure_renegotiation = NULL;
/* The renegotiation_info advertising is re-established when the next
* ClientHello is built (SendClientHello), so a reused client object
* keeps the "advertise implies enforce" invariant (RFC 5746). */
#endif
#endif

Expand Down
49 changes: 48 additions & 1 deletion src/ssl_api_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,13 @@ static int _Rehandshake(WOLFSSL* ssl)
return SECURE_RENEGOTIATION_E;
}

if (ssl->secure_renegotiation->advertiseOnly) {
/* Extension was advertised only for the RFC 5746 check; the
* application did not call wolfSSL_UseSecureRenegotiation(). */
WOLFSSL_MSG("Secure Renegotiation not forced on by user");
return SECURE_RENEGOTIATION_E;
}

#ifdef WOLFSSL_DTLS
if (ssl->options.dtls && ssl->keys.dtls_epoch == 0xFFFF) {
WOLFSSL_MSG("Secure Renegotiation not allowed. Epoch would wrap");
Expand Down Expand Up @@ -962,7 +969,8 @@ long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl)
#endif /* HAVE_SECURE_RENEGOTIATION_INFO */

#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
!defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
/* Get whether the secure renegotiation check is enabled for the object.
*
* @param [in] ssl SSL/TLS object.
Expand Down Expand Up @@ -996,6 +1004,45 @@ WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled)
ssl->scr_check_enabled = !!enabled;
return WOLFSSL_SUCCESS;
}

/* Get whether the secure renegotiation check is enabled for the context.
*
* @param [in] ctx SSL/TLS context object.
* @return Non-zero when the check is enabled, 0 otherwise.
* @return BAD_FUNC_ARG when ctx is NULL.
*/
WOLFSSL_API int wolfSSL_CTX_get_scr_check_enabled(const WOLFSSL_CTX* ctx)
{
WOLFSSL_ENTER("wolfSSL_CTX_get_scr_check_enabled");

if (ctx == NULL)
return BAD_FUNC_ARG;

return ctx->scr_check_enabled;
}

/* Set whether the secure renegotiation check is enabled for the context.
*
* WOLFSSL objects created from the context inherit this setting. Disabling the
* check allows connecting to servers that do not support secure renegotiation
* (RFC 5746), which is not recommended.
*
* @param [in] ctx SSL/TLS context object.
* @param [in] enabled Non-zero to enable the check, 0 to disable it.
* @return WOLFSSL_SUCCESS on success.
* @return BAD_FUNC_ARG when ctx is NULL.
*/
WOLFSSL_API int wolfSSL_CTX_set_scr_check_enabled(WOLFSSL_CTX* ctx,
byte enabled)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_scr_check_enabled");

if (ctx == NULL)
return BAD_FUNC_ARG;

ctx->scr_check_enabled = !!enabled;
return WOLFSSL_SUCCESS;
}
#endif

#if defined(HAVE_SESSION_TICKET)
Expand Down
11 changes: 11 additions & 0 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -4647,6 +4647,17 @@ int SendTls13ClientHello(WOLFSSL* ssl)
return BAD_FUNC_ARG;
}

#if defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)
/* Re-establish renegotiation_info advertising for a reused object
* (wolfSSL_clear frees it) so a TLS 1.2 downgrade still enforces what the
* ClientHello advertised. Only when absent, to keep any existing state. */
if (ssl->secure_renegotiation == NULL) {
ret = SetupClientSecureRenegotiation(ssl);
if (ret != WOLFSSL_SUCCESS)
return ret;
}
#endif

ssl->options.buildingMsg = 1;
major = SSLv3_MAJOR;
tls12minor = TLSv1_2_MINOR;
Expand Down
Loading
Loading