Send secure renegotiation extension by default

- Add test for terminating the connection
- Add ProcessReplyEx(ssl, 1) to wolfSSL_accept
This commit is contained in:
Juliusz Sosinowicz
2023-03-27 17:53:59 +02:00
parent 28fd14621a
commit f0ad01f552
5 changed files with 123 additions and 2 deletions

View File

@ -195,6 +195,7 @@ then
else
AC_MSG_ERROR([Invalid value for --enable-harden-tls])
fi
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_EXTRA_ALERTS -DWOLFSSL_CHECK_ALERT_ON_ERR"
fi
# Support for forcing 32-bit mode

View File

@ -7127,11 +7127,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
}
#endif
#ifdef HAVE_SECURE_RENEGOTIATION
#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) */
#ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT
#if defined(WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT) || \
(defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_NO_TLS12))
useSecureReneg = 1;
#endif
if (useSecureReneg) {
@ -26988,6 +26990,18 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType,
}
#endif
#ifdef WOLFSSL_HARDEN_TLS
if (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");
return SECURE_RENEGOTIATION_E;
}
#endif
ssl->options.serverState = SERVER_HELLO_COMPLETE;
if (IsEncryptionOn(ssl, 0)) {

View File

@ -13959,6 +13959,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
case ACCEPT_FIRST_REPLY_DONE :
if ( (ssl->error = SendServerHello(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -13975,6 +13978,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#ifndef NO_CERTS
if (!ssl->options.resuming)
if ( (ssl->error = SendCertificate(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -13987,6 +13993,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#ifndef NO_CERTS
if (!ssl->options.resuming)
if ( (ssl->error = SendCertificateStatus(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -14003,6 +14012,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#endif
if (!ssl->options.resuming)
if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -14015,6 +14027,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
if (!ssl->options.resuming) {
if (ssl->options.verifyPeer) {
if ( (ssl->error = SendCertificateRequest(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -14032,6 +14047,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
case CERT_REQ_SENT :
if (!ssl->options.resuming)
if ( (ssl->error = SendServerHelloDone(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -14070,6 +14088,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#ifdef HAVE_SESSION_TICKET
if (ssl->options.createTicket && !ssl->options.noTicketTls12) {
if ( (ssl->error = SendTicket(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_MSG("Thought we need ticket but failed");
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
@ -14088,6 +14109,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
}
if ( (ssl->error = SendChangeCipher(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}
@ -14097,6 +14121,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
case CHANGE_CIPHER_SENT :
if ( (ssl->error = SendFinished(ssl)) != 0) {
#ifdef WOLFSSL_CHECK_ALERT_ON_ERR
ProcessReplyEx(ssl, 1); /* See if an alert was sent. */
#endif
WOLFSSL_ERROR(ssl->error);
return WOLFSSL_FATAL_ERROR;
}

View File

@ -63519,6 +63519,77 @@ static int test_extra_alerts_bad_psk(void)
return TEST_SKIPPED;
}
#endif
#if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_NO_TLS12) && \
defined(HAVE_IO_TESTS_DEPENDENCIES)
static int test_harden_no_secure_renegotiation_io_cb(WOLFSSL *ssl, char *buf,
int sz, void *ctx)
{
static int sentServerHello = FALSE;
if (!sentServerHello) {
byte renegExt[] = { 0xFF, 0x01, 0x00, 0x01, 0x00 };
size_t i;
if (sz < (int)sizeof(renegExt))
return WOLFSSL_CBIO_ERR_GENERAL;
/* Remove SCR from ServerHello */
for (i = 0; i < sz - sizeof(renegExt); i++) {
if (XMEMCMP(buf + i, renegExt, sizeof(renegExt)) == 0) {
/* Found the extension. Change it to something unrecognized. */
buf[i+1] = 0x11;
break;
}
}
sentServerHello = TRUE;
}
return EmbedSend(ssl, buf, sz, ctx);
}
static void test_harden_no_secure_renegotiation_ssl_ready(WOLFSSL* ssl)
{
wolfSSL_SSLSetIOSend(ssl, test_harden_no_secure_renegotiation_io_cb);
}
static void test_harden_no_secure_renegotiation_on_cleanup(WOLFSSL* ssl)
{
WOLFSSL_ALERT_HISTORY h;
AssertIntEQ(wolfSSL_get_alert_history(ssl, &h), WOLFSSL_SUCCESS);
AssertIntEQ(h.last_rx.code, handshake_failure);
AssertIntEQ(h.last_rx.level, alert_fatal);
}
static int test_harden_no_secure_renegotiation(void)
{
callback_functions client_cbs, server_cbs;
XMEMSET(&client_cbs, 0, sizeof(client_cbs));
XMEMSET(&server_cbs, 0, sizeof(server_cbs));
client_cbs.method = wolfTLSv1_2_client_method;
server_cbs.method = wolfTLSv1_2_server_method;
server_cbs.ssl_ready = test_harden_no_secure_renegotiation_ssl_ready;
server_cbs.on_cleanup = test_harden_no_secure_renegotiation_on_cleanup;
test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs);
AssertIntEQ(client_cbs.return_code, TEST_FAIL);
AssertIntEQ(client_cbs.last_err, SECURE_RENEGOTIATION_E);
AssertIntEQ(server_cbs.return_code, TEST_FAIL);
AssertIntEQ(server_cbs.last_err, SOCKET_ERROR_E);
return TEST_RES_CHECK(1);
}
#else
static int test_harden_no_secure_renegotiation(void)
{
return TEST_SKIPPED;
}
#endif
/*----------------------------------------------------------------------------*
| Main
*----------------------------------------------------------------------------*/
@ -64539,6 +64610,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_extra_alerts_wrong_cs),
TEST_DECL(test_extra_alerts_skip_hs),
TEST_DECL(test_extra_alerts_bad_psk),
TEST_DECL(test_harden_no_secure_renegotiation),
/* If at some point a stub get implemented this test should fail indicating
* a need to implement a new test case
*/

View File

@ -2995,6 +2995,13 @@ extern void uITRON4_free(void *p) ;
#ifndef NO_OLD_TLS
#error "TLS < 1.2 protocol versions not allowed https://www.rfc-editor.org/rfc/rfc9325#section-3.1.1"
#endif
#if !defined(WOLFSSL_NO_TLS12) && !defined(HAVE_SECURE_RENEGOTIATION) && \
!defined(HAVE_SERVER_RENEGOTIATION_INFO)
#error "TLS 1.2 requires at least HAVE_SERVER_RENEGOTIATION_INFO to send the secure renegotiation extension https://www.rfc-editor.org/rfc/rfc9325#section-3.5"
#endif
#if !defined(WOLFSSL_EXTRA_ALERTS) || !defined(WOLFSSL_CHECK_ALERT_ON_ERR)
#error "RFC9325 requires some additional alerts to be sent"
#endif
/* Ciphersuite check done in internal.h */
#endif