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
67 changes: 67 additions & 0 deletions doc/dox_comments/header_files/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
18 changes: 16 additions & 2 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -18073,6 +18077,16 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
}
#endif

#if !defined(HAVE_SECURE_RENEGOTIATION)
if (ssl->options.handShakeState == HANDSHAKE_DONE && type == client_hello &&
ssl->options.side == WOLFSSL_SERVER_END){
WOLFSSL_MSG("Renegotiation request rejected");
SendAlert(ssl, alert_fatal, no_renegotiation);
WOLFSSL_ERROR_VERBOSE(SECURE_RENEGOTIATION_E);
return SECURE_RENEGOTIATION_E;
}
#endif

if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){
WOLFSSL_MSG("HandShake message after handshake complete");
SendAlert(ssl, alert_fatal, unexpected_message);
Expand Down Expand Up @@ -31656,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.
Expand Down
24 changes: 24 additions & 0 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
110 changes: 110 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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) && \
Expand Down
4 changes: 4 additions & 0 deletions wolfssl/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions wolfssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) && \
Expand Down