Skip to content

Commit ddb2fb6

Browse files
Add a runtime option to enable or disable the secure renegotation check.
1 parent 1773a4a commit ddb2fb6

File tree

6 files changed

+217
-2
lines changed

6 files changed

+217
-2
lines changed

doc/dox_comments/header_files/ssl.h

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

src/internal.c

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

78517851
ssl->disabledCurves = ctx->disabledCurves;
78527852
#endif
7853+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
7854+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
7855+
ssl->scr_check_enabled = 1;
7856+
#endif
78537857

78547858
InitCiphers(ssl);
78557859
InitCipherSpecs(&ssl->specs);
@@ -31666,8 +31670,8 @@ static int DhSetKey(WOLFSSL* ssl)
3166631670
#endif /* HAVE_TLS_EXTENSIONS */
3166731671

3166831672
#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
31669-
if (ssl->secure_renegotiation == NULL ||
31670-
!ssl->secure_renegotiation->enabled) {
31673+
if (ssl->scr_check_enabled && (ssl->secure_renegotiation == NULL ||
31674+
!ssl->secure_renegotiation->enabled)) {
3167131675
/* If the server does not acknowledge the extension, the client
3167231676
* MUST generate a fatal handshake_failure alert prior to
3167331677
* terminating the connection.

src/ssl.c

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

42164216
#endif /* HAVE_SECURE_RENEGOTIATION_INFO */
42174217

4218+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
4219+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
4220+
WOLFSSL_API int wolfSSL_get_scr_check_enabled(WOLFSSL* ssl)
4221+
{
4222+
WOLFSSL_ENTER("wolfSSL_get_scr_check_enabled");
4223+
4224+
if (ssl == NULL)
4225+
return BAD_FUNC_ARG;
4226+
4227+
return ssl->scr_check_enabled;
4228+
}
4229+
4230+
WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled)
4231+
{
4232+
WOLFSSL_ENTER("wolfSSL_set_scr_check_enabled");
4233+
4234+
if (ssl == NULL)
4235+
return BAD_FUNC_ARG;
4236+
4237+
ssl->scr_check_enabled = !!enabled;
4238+
return WOLFSSL_SUCCESS;
4239+
}
4240+
#endif
4241+
42184242
#if defined(HAVE_SESSION_TICKET)
42194243
/* Session Ticket */
42204244

tests/api.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12844,6 +12844,115 @@ static int test_wolfSSL_SCR_Reconnect(void)
1284412844
return EXPECT_RESULT();
1284512845
}
1284612846

12847+
/* Test SCR check when server doesn't reply to secure_renegotiation. */
12848+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
12849+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
12850+
defined(HAVE_SECURE_RENEGOTIATION) && \
12851+
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
12852+
/* IO callback to remove secure renegotiation extension from ServerHello */
12853+
static int test_SCR_check_remove_ext_io_cb(WOLFSSL *ssl, char *buf, int sz, void *ctx)
12854+
{
12855+
static int sentServerHello = FALSE;
12856+
12857+
if (!sentServerHello) {
12858+
/* Look for secure renegotiation extension: 0xFF 0x01 (extension type) */
12859+
byte renegExt[] = { 0xFF, 0x01 };
12860+
size_t i;
12861+
12862+
if (sz < (int)sizeof(renegExt))
12863+
return test_memio_write_cb(ssl, buf, sz, ctx);
12864+
12865+
/* Search for the extension in the buffer */
12866+
for (i = 0; i < (size_t)sz - sizeof(renegExt); i++) {
12867+
if (XMEMCMP(buf + i, renegExt, sizeof(renegExt)) == 0) {
12868+
/* Found the extension. Remove it by changing the type to something
12869+
* unrecognized so it won't be parsed as secure renegotiation. */
12870+
buf[i+1] = 0x11;
12871+
break;
12872+
}
12873+
}
12874+
sentServerHello = TRUE;
12875+
}
12876+
12877+
/* Call the original test_memio_write_cb */
12878+
return test_memio_write_cb(ssl, buf, sz, ctx);
12879+
}
12880+
#endif
12881+
12882+
static int test_wolfSSL_SCR_check_enabled(void)
12883+
{
12884+
EXPECT_DECLS;
12885+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
12886+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
12887+
defined(HAVE_SECURE_RENEGOTIATION) && \
12888+
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
12889+
struct test_memio_ctx test_ctx;
12890+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
12891+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
12892+
int ret;
12893+
int enabled;
12894+
12895+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
12896+
12897+
/* Set up client and server */
12898+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
12899+
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
12900+
12901+
/* Enable secure renegotiation on client (so it sends the extension) */
12902+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c));
12903+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c));
12904+
12905+
/* Set up IO callback on server to remove the extension from ServerHello */
12906+
wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb);
12907+
12908+
/* Try to connect - should fail with SECURE_RENEGOTIATION_E */
12909+
ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL);
12910+
ExpectIntNE(0, ret); /* Handshake should fail */
12911+
ret = wolfSSL_get_error(ssl_c, 0);
12912+
ExpectIntEQ(WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E), ret);
12913+
12914+
/* Clean up for next attempt */
12915+
wolfSSL_free(ssl_c);
12916+
ssl_c = NULL;
12917+
wolfSSL_free(ssl_s);
12918+
ssl_s = NULL;
12919+
test_memio_clear_buffer(&test_ctx, 1);
12920+
test_memio_clear_buffer(&test_ctx, 0);
12921+
12922+
/* Set up new client and server */
12923+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
12924+
wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0);
12925+
12926+
/* Enable secure renegotiation on client */
12927+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_UseSecureRenegotiation(ctx_c));
12928+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSecureRenegotiation(ssl_c));
12929+
12930+
/* Set up IO callback on server to remove the extension from ServerHello */
12931+
wolfSSL_SSLSetIOSend(ssl_s, test_SCR_check_remove_ext_io_cb);
12932+
12933+
/* Disable the SCR check */
12934+
ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_scr_check_enabled(ssl_c, 0));
12935+
12936+
/* Verify the state is 0 */
12937+
enabled = wolfSSL_get_scr_check_enabled(ssl_c);
12938+
ExpectIntEQ(0, enabled);
12939+
12940+
/* Now connection should succeed */
12941+
ExpectIntEQ(0, test_memio_do_handshake(ssl_c, ssl_s, 10, NULL));
12942+
12943+
/* Cleanup */
12944+
wolfSSL_free(ssl_c);
12945+
ssl_c = NULL;
12946+
wolfSSL_free(ssl_s);
12947+
ssl_s = NULL;
12948+
wolfSSL_CTX_free(ctx_c);
12949+
ctx_c = NULL;
12950+
wolfSSL_CTX_free(ctx_s);
12951+
ctx_s = NULL;
12952+
#endif
12953+
return EXPECT_RESULT();
12954+
}
12955+
1284712956
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) && \
1284812957
!defined(NO_FILESYSTEM) && (!defined(NO_RSA) || defined(HAVE_ECC))
1284912958
/* Called when writing. */
@@ -42164,6 +42273,7 @@ TEST_CASE testCases[] = {
4216442273
TEST_DECL(test_certificate_authorities_client_hello),
4216542274
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
4216642275
TEST_DECL(test_wolfSSL_SCR_Reconnect),
42276+
TEST_DECL(test_wolfSSL_SCR_check_enabled),
4216742277
TEST_DECL(test_tls_ext_duplicate),
4216842278
TEST_DECL(test_tls_bad_legacy_version),
4216942279
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \

wolfssl/internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6333,6 +6333,10 @@ struct WOLFSSL {
63336333
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
63346334
int secLevel; /* The security level of system-wide crypto policy. */
63356335
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
6336+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
6337+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
6338+
WC_BITFIELD scr_check_enabled:1; /* enable/disable SCR check */
6339+
#endif
63366340
};
63376341

63386342
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)

wolfssl/ssl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4726,6 +4726,12 @@ WOLFSSL_API int wolfSSL_SecureResume(WOLFSSL* ssl);
47264726
#endif
47274727
WOLFSSL_API long wolfSSL_SSL_get_secure_renegotiation_support(WOLFSSL* ssl);
47284728

4729+
#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
4730+
defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
4731+
WOLFSSL_API int wolfSSL_get_scr_check_enabled(WOLFSSL* ssl);
4732+
WOLFSSL_API int wolfSSL_set_scr_check_enabled(WOLFSSL* ssl, byte enabled);
4733+
#endif
4734+
47294735
#endif
47304736

47314737
#if defined(HAVE_SELFTEST) && \

0 commit comments

Comments
 (0)