Add a runtime option to enable or disable the secure renegotation check.

This commit is contained in:
Kareem
2025-12-30 13:19:04 -07:00
parent 1773a4ab41
commit ddb2fb628e
6 changed files with 217 additions and 2 deletions

View File

@@ -15984,3 +15984,70 @@ void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,
*/
void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
void* userdata);
/*!
\ingroup Setup
\brief Gets the state of the secure renegotiation (SCR) check requirement.
This function returns whether the client requires the server to acknowledge
the secure renegotiation extension and enable secure renegotiation when
sending it from the client. When enabled, the client will generate a fatal
handshake_failure alert if the server does not acknowledge the extension
in the ServerHello message, as required by RFC 9325.
\return 1 if the SCR check is enabled.
\return 0 if the SCR check is disabled.
\return BAD_FUNC_ARG if ssl is NULL.
\param ssl Pointer to the WOLFSSL structure, created with wolfSSL_new().
_Example_
\code
WOLFSSL* ssl;
int enabled;
ssl = wolfSSL_new(ctx);
enabled = wolfSSL_get_scr_check_enabled(ssl);
if (enabled) {
// SCR check is enabled
}
\endcode
\sa wolfSSL_set_scr_check_enabled
*/
byte wolfSSL_get_scr_check_enabled(WOLFSSL* ssl);
/*!
\ingroup Setup
\brief Sets the state of the secure renegotiation (SCR) check requirement.
This function enables or disables the requirement for the server to
acknowledge the secure renegotiation extension and enable secure
renegotiation when sending it from the client. When enabled, the client
will generate a fatal handshake_failure alert if the server does not
acknowledge the extension in the ServerHello message, as required by
RFC 9325.
\return WOLFSSL_SUCCESS on success.
\return BAD_FUNC_ARG if ssl is NULL.
\param ssl Pointer to the WOLFSSL structure, created with wolfSSL_new().
\param enabled Non-zero to enable the SCR check, zero to disable it.
_Example_
\code
WOLFSSL* ssl;
int ret;
ssl = wolfSSL_new(ctx);
ret = wolfSSL_set_scr_check_enabled(ssl, 1);
if (ret != WOLFSSL_SUCCESS) {
// Error setting SCR check
}
\endcode
\sa wolfSSL_get_scr_check_enabled
*/
int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled);

View File

@@ -7850,6 +7850,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;
#endif
InitCiphers(ssl);
InitCipherSpecs(&ssl->specs);
@@ -31666,8 +31670,8 @@ static int DhSetKey(WOLFSSL* ssl)
#endif /* HAVE_TLS_EXTENSIONS */
#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
if (ssl->secure_renegotiation == NULL ||
!ssl->secure_renegotiation->enabled) {
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.

View File

@@ -4215,6 +4215,30 @@ 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)
WOLFSSL_API int wolfSSL_get_scr_check_enabled(WOLFSSL* ssl)
{
WOLFSSL_ENTER("wolfSSL_get_scr_check_enabled");
if (ssl == NULL)
return BAD_FUNC_ARG;
return ssl->scr_check_enabled;
}
WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled)
{
WOLFSSL_ENTER("wolfSSL_set_scr_check_enabled");
if (ssl == NULL)
return BAD_FUNC_ARG;
ssl->scr_check_enabled = !!enabled;
return WOLFSSL_SUCCESS;
}
#endif
#if defined(HAVE_SESSION_TICKET)
/* Session Ticket */

View File

@@ -12844,6 +12844,115 @@ static int test_wolfSSL_SCR_Reconnect(void)
return EXPECT_RESULT();
}
/* Test SCR check when server doesn't reply to secure_renegotiation. */
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
defined(HAVE_SECURE_RENEGOTIATION) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
/* IO callback to remove secure renegotiation extension from ServerHello */
static int test_SCR_check_remove_ext_io_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
static int sentServerHello = FALSE;
if (!sentServerHello) {
/* Look for secure renegotiation extension: 0xFF 0x01 (extension type) */
byte renegExt[] = { 0xFF, 0x01 };
size_t i;
if (sz < (int)sizeof(renegExt))
return test_memio_write_cb(ssl, buf, sz, ctx);
/* Search for the extension in the buffer */
for (i = 0; i < (size_t)sz - sizeof(renegExt); i++) {
if (XMEMCMP(buf + i, renegExt, sizeof(renegExt)) == 0) {
/* Found the extension. Remove it by changing the type to something
* unrecognized so it won't be parsed as secure renegotiation. */
buf[i+1] = 0x11;
break;
}
}
sentServerHello = TRUE;
}
/* Call the original test_memio_write_cb */
return test_memio_write_cb(ssl, buf, sz, ctx);
}
#endif
static int test_wolfSSL_SCR_check_enabled(void)
{
EXPECT_DECLS;
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
defined(HAVE_SECURE_RENEGOTIATION) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
struct test_memio_ctx test_ctx;
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
int ret;
int enabled;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
/* Set up client and server */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
/* Enable secure renegotiation on client (so it sends the extension) */
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c));
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c));
/* Set up IO callback on server to remove the extension from ServerHello */
wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb);
/* Try to connect - should fail with SECURE_RENEGOTIATION_E */
ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
ExpectIntNE(0, ret); /* Handshake should fail */
ret = wolfSSL_get_error(ssl_c, 0);
ExpectIntEQ(WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E), ret);
/* Clean up for next attempt */
wolfSSL_free(ssl_c);
ssl_c = NULL;
wolfSSL_free(ssl_s);
ssl_s = NULL;
test_memio_clear_buffer(&test_ctx, 1);
test_memio_clear_buffer(&test_ctx, 0);
/* Set up new client and server */
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
/* Enable secure renegotiation on client */
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c));
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c));
/* Set up IO callback on server to remove the extension from ServerHello */
wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb);
/* Disable the SCR check */
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_scr_check_enabled(ssl_c, 0));
/* Verify the state is 0 */
enabled = wolfSSL_get_scr_check_enabled(ssl_c);
ExpectIntEQ(0, enabled);
/* Now connection should succeed */
ExpectIntEQ(0, test_memio_do_handshake(ssl_c, ssl_s, 10, NULL));
/* Cleanup */
wolfSSL_free(ssl_c);
ssl_c = NULL;
wolfSSL_free(ssl_s);
ssl_s = NULL;
wolfSSL_CTX_free(ctx_c);
ctx_c = NULL;
wolfSSL_CTX_free(ctx_s);
ctx_s = NULL;
#endif
return EXPECT_RESULT();
}
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \
!defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC))
/* Called when writing. */
@@ -42164,6 +42273,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_certificate_authorities_client_hello),
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
TEST_DECL(test_wolfSSL_SCR_Reconnect),
TEST_DECL(test_wolfSSL_SCR_check_enabled),
TEST_DECL(test_tls_ext_duplicate),
TEST_DECL(test_tls_bad_legacy_version),
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \

View File

@@ -6333,6 +6333,10 @@ struct WOLFSSL {
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
int secLevel; /* The security level of system-wide crypto policy. */
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
WC_BITFIELD scr_check_enabled:1; /* enable/disable SCR check */
#endif
};
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)

View File

@@ -4726,6 +4726,12 @@ WOLFSSL_API int wolfSSL_SecureResume(WOLFSSL* ssl);
#endif
WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl);
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
WOLFSSL_API int wolfSSL_get_scr_check_enabled(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled);
#endif
#endif
#if defined(HAVE_SELFTEST) && \