Skip to content

Commit eeaa3a7

Browse files
authored
Merge pull request #9596 from kareem-wolfssl/zd19378
Add a runtime option to enable or disable the secure renegotiation check.
2 parents 4574a0c + 1103552 commit eeaa3a7

File tree

6 files changed

+227
-2
lines changed

6 files changed

+227
-2
lines changed

doc/dox_comments/header_files/ssl.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15986,3 +15986,70 @@ void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,
1598615986
*/
1598715987
void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx,
1598815988
void* userdata);
15989+
15990+
/*!
15991+
\ingroup Setup
15992+
15993+
\brief Gets the state of the secure renegotiation (SCR) check requirement.
15994+
15995+
This function returns whether the client requires the server to acknowledge
15996+
the secure renegotiation extension and enable secure renegotiation when
15997+
sending it from the client. When enabled, the client will generate a fatal
15998+
handshake_failure alert if the server does not acknowledge the extension
15999+
in the ServerHello message, as required by RFC 9325.
16000+
16001+
\return 1 if the SCR check is enabled.
16002+
\return 0 if the SCR check is disabled.
16003+
\return BAD_FUNC_ARG if ssl is NULL.
16004+
16005+
\param ssl Pointer to the WOLFSSL structure, created with wolfSSL_new().
16006+
16007+
_Example_
16008+
\code
16009+
WOLFSSL* ssl;
16010+
int enabled;
16011+
16012+
ssl = wolfSSL_new(ctx);
16013+
enabled = wolfSSL_get_scr_check_enabled(ssl);
16014+
if (enabled) {
16015+
// SCR check is enabled
16016+
}
16017+
\endcode
16018+
16019+
\sa wolfSSL_set_scr_check_enabled
16020+
*/
16021+
int wolfSSL_get_scr_check_enabled(const WOLFSSL* ssl);
16022+
16023+
/*!
16024+
\ingroup Setup
16025+
16026+
\brief Sets the state of the secure renegotiation (SCR) check requirement.
16027+
16028+
This function enables or disables the requirement for the server to
16029+
acknowledge the secure renegotiation extension and enable secure
16030+
renegotiation when sending it from the client. When enabled, the client
16031+
will generate a fatal handshake_failure alert if the server does not
16032+
acknowledge the extension in the ServerHello message, as required by
16033+
RFC 9325.
16034+
16035+
\return WOLFSSL_SUCCESS on success.
16036+
\return BAD_FUNC_ARG if ssl is NULL.
16037+
16038+
\param ssl Pointer to the WOLFSSL structure, created with wolfSSL_new().
16039+
\param enabled Non-zero to enable the SCR check, zero to disable it.
16040+
16041+
_Example_
16042+
\code
16043+
WOLFSSL* ssl;
16044+
int ret;
16045+
16046+
ssl = wolfSSL_new(ctx);
16047+
ret = wolfSSL_set_scr_check_enabled(ssl, 1);
16048+
if (ret != WOLFSSL_SUCCESS) {
16049+
// Error setting SCR check
16050+
}
16051+
\endcode
16052+
16053+
\sa wolfSSL_get_scr_check_enabled
16054+
*/
16055+
int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled);

src/internal.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7912,6 +7912,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
79127912

79137913
ssl->disabledCurves = ctx->disabledCurves;
79147914
#endif
7915+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
7916+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
7917+
ssl->scr_check_enabled = 1;
7918+
#endif
79157919

79167920
InitCiphers(ssl);
79177921
InitCipherSpecs(&ssl->specs);
@@ -18166,6 +18170,16 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1816618170
}
1816718171
#endif
1816818172

18173+
#if !defined(HAVE_SECURE_RENEGOTIATION)
18174+
if (ssl->options.handShakeState == HANDSHAKE_DONE && type == client_hello &&
18175+
ssl->options.side == WOLFSSL_SERVER_END) {
18176+
WOLFSSL_MSG("Renegotiation request rejected");
18177+
SendAlert(ssl, alert_fatal, no_renegotiation);
18178+
WOLFSSL_ERROR_VERBOSE(SECURE_RENEGOTIATION_E);
18179+
return SECURE_RENEGOTIATION_E;
18180+
}
18181+
#endif
18182+
1816918183
if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){
1817018184
WOLFSSL_MSG("HandShake message after handshake complete");
1817118185
SendAlert(ssl, alert_fatal, unexpected_message);
@@ -31355,8 +31369,8 @@ static int DhSetKey(WOLFSSL* ssl)
3135531369
#endif /* HAVE_TLS_EXTENSIONS */
3135631370

3135731371
#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
31358-
if (ssl->secure_renegotiation == NULL ||
31359-
!ssl->secure_renegotiation->enabled) {
31372+
if (ssl->scr_check_enabled && (ssl->secure_renegotiation == NULL ||
31373+
!ssl->secure_renegotiation->enabled)) {
3136031374
/* If the server does not acknowledge the extension, the client
3136131375
* MUST generate a fatal handshake_failure alert prior to
3136231376
* terminating the connection.

src/ssl.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4223,6 +4223,30 @@ long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl)
42234223

42244224
#endif /* HAVE_SECURE_RENEGOTIATION_INFO */
42254225

4226+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
4227+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
4228+
WOLFSSL_API int wolfSSL_get_scr_check_enabled(const WOLFSSL* ssl)
4229+
{
4230+
WOLFSSL_ENTER("wolfSSL_get_scr_check_enabled");
4231+
4232+
if (ssl == NULL)
4233+
return BAD_FUNC_ARG;
4234+
4235+
return ssl->scr_check_enabled;
4236+
}
4237+
4238+
WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled)
4239+
{
4240+
WOLFSSL_ENTER("wolfSSL_set_scr_check_enabled");
4241+
4242+
if (ssl == NULL)
4243+
return BAD_FUNC_ARG;
4244+
4245+
ssl->scr_check_enabled = !!enabled;
4246+
return WOLFSSL_SUCCESS;
4247+
}
4248+
#endif
4249+
42264250
#if defined(HAVE_SESSION_TICKET)
42274251
/* Session Ticket */
42284252

tests/api.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9769,6 +9769,115 @@ static int test_wolfSSL_SCR_Reconnect(void)
97699769
return EXPECT_RESULT();
97709770
}
97719771

9772+
/* Test SCR check when server doesn't reply to secure_renegotiation. */
9773+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
9774+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
9775+
defined(HAVE_SECURE_RENEGOTIATION) && \
9776+
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
9777+
/* IO callback to remove secure renegotiation extension from ServerHello */
9778+
static int test_SCR_check_remove_ext_io_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
9779+
{
9780+
static int sentServerHello = FALSE;
9781+
9782+
if (!sentServerHello) {
9783+
/* Look for secure renegotiation extension: 0xFF 0x01 (extension type) */
9784+
byte renegExt[] = { 0xFF, 0x01 };
9785+
size_t i;
9786+
9787+
if (sz < (int)sizeof(renegExt))
9788+
return test_memio_write_cb(ssl, buf, sz, ctx);
9789+
9790+
/* Search for the extension in the buffer */
9791+
for (i = 0; i < (size_t)sz - sizeof(renegExt); i++) {
9792+
if (XMEMCMP(buf + i, renegExt, sizeof(renegExt)) == 0) {
9793+
/* Found the extension. Remove it by changing the type to something
9794+
* unrecognized so it won't be parsed as secure renegotiation. */
9795+
buf[i+1] = 0x11;
9796+
break;
9797+
}
9798+
}
9799+
sentServerHello = TRUE;
9800+
}
9801+
9802+
/* Call the original test_memio_write_cb */
9803+
return test_memio_write_cb(ssl, buf, sz, ctx);
9804+
}
9805+
#endif
9806+
9807+
static int test_wolfSSL_SCR_check_enabled(void)
9808+
{
9809+
EXPECT_DECLS;
9810+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
9811+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
9812+
defined(HAVE_SECURE_RENEGOTIATION) && \
9813+
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
9814+
struct test_memio_ctx test_ctx;
9815+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
9816+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
9817+
int ret;
9818+
int enabled;
9819+
9820+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
9821+
9822+
/* Set up client and server */
9823+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
9824+
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
9825+
9826+
/* Enable secure renegotiation on client (so it sends the extension) */
9827+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c));
9828+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c));
9829+
9830+
/* Set up IO callback on server to remove the extension from ServerHello */
9831+
wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb);
9832+
9833+
/* Try to connect - should fail with SECURE_RENEGOTIATION_E */
9834+
ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
9835+
ExpectIntNE(0, ret); /* Handshake should fail */
9836+
ret = wolfSSL_get_error(ssl_c, 0);
9837+
ExpectIntEQ(WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E), ret);
9838+
9839+
/* Clean up for next attempt */
9840+
wolfSSL_free(ssl_c);
9841+
ssl_c = NULL;
9842+
wolfSSL_free(ssl_s);
9843+
ssl_s = NULL;
9844+
test_memio_clear_buffer(&test_ctx, 1);
9845+
test_memio_clear_buffer(&test_ctx, 0);
9846+
9847+
/* Set up new client and server */
9848+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
9849+
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
9850+
9851+
/* Enable secure renegotiation on client */
9852+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c));
9853+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c));
9854+
9855+
/* Set up IO callback on server to remove the extension from ServerHello */
9856+
wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb);
9857+
9858+
/* Disable the SCR check */
9859+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_scr_check_enabled(ssl_c, 0));
9860+
9861+
/* Verify the state is 0 */
9862+
enabled = wolfSSL_get_scr_check_enabled(ssl_c);
9863+
ExpectIntEQ(0, enabled);
9864+
9865+
/* Now connection should succeed */
9866+
ExpectIntEQ(0, test_memio_do_handshake(ssl_c, ssl_s, 10, NULL));
9867+
9868+
/* Cleanup */
9869+
wolfSSL_free(ssl_c);
9870+
ssl_c = NULL;
9871+
wolfSSL_free(ssl_s);
9872+
ssl_s = NULL;
9873+
wolfSSL_CTX_free(ctx_c);
9874+
ctx_c = NULL;
9875+
wolfSSL_CTX_free(ctx_s);
9876+
ctx_s = NULL;
9877+
#endif
9878+
return EXPECT_RESULT();
9879+
}
9880+
97729881
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \
97739882
!defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC))
97749883
/* Called when writing. */
@@ -31645,6 +31754,7 @@ TEST_CASE testCases[] = {
3164531754
TEST_DECL(test_certificate_authorities_client_hello),
3164631755
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
3164731756
TEST_DECL(test_wolfSSL_SCR_Reconnect),
31757+
TEST_DECL(test_wolfSSL_SCR_check_enabled),
3164831758
TEST_DECL(test_tls_ext_duplicate),
3164931759
TEST_DECL(test_tls_bad_legacy_version),
3165031760
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \

wolfssl/internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6344,6 +6344,10 @@ struct WOLFSSL {
63446344
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
63456345
int secLevel; /* The security level of system-wide crypto policy. */
63466346
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
6347+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
6348+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
6349+
WC_BITFIELD scr_check_enabled:1; /* enable/disable SCR check */
6350+
#endif
63476351
};
63486352

63496353
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)

wolfssl/ssl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4734,6 +4734,12 @@ WOLFSSL_API int wolfSSL_SecureResume(WOLFSSL* ssl);
47344734
#endif
47354735
WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl);
47364736

4737+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
4738+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
4739+
WOLFSSL_API int wolfSSL_get_scr_check_enabled(const WOLFSSL* ssl);
4740+
WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled);
4741+
#endif
4742+
47374743
#endif
47384744

47394745
#if defined(HAVE_SELFTEST) && \

0 commit comments

Comments
 (0)