Skip to content

Commit

Permalink
fix: Wipe conn->in on all record parse failures (#4499)
Browse files Browse the repository at this point in the history
  • Loading branch information
goatgoose authored Apr 12, 2024
1 parent 171c96a commit 4220a4d
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
diff --git a/tls/s2n_record_read_cbc.c b/tls/s2n_record_read_cbc.c
index bb06523..60a2eed 100644
index 346e6571..0f2527e9 100644
--- a/tls/s2n_record_read_cbc.c
+++ b/tls/s2n_record_read_cbc.c
@@ -30,6 +30,8 @@
#include "utils/s2n_safety.h"
@@ -26,6 +26,8 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"

+extern int g_padding_length;
+
int s2n_record_parse_cbc(
const struct s2n_cipher_suite *cipher_suite,
struct s2n_connection *conn,
@@ -86,6 +88,8 @@ int s2n_record_parse_cbc(
const struct s2n_cipher_suite *cipher_suite,
struct s2n_connection *conn,
@@ -82,6 +84,8 @@ int s2n_record_parse_cbc(

/* Subtract the padding length */
POSIX_ENSURE_GT(en.size, 0);
Expand All @@ -20,11 +20,11 @@ index bb06523..60a2eed 100644
uint32_t out = 0;
POSIX_GUARD(s2n_sub_overflow(payload_length, en.data[en.size - 1] + 1, &out));
payload_length = out;
@@ -107,6 +111,7 @@ int s2n_record_parse_cbc(
@@ -103,6 +107,7 @@ int s2n_record_parse_cbc(

/* Padding */
/* Padding. This finalizes the provided HMAC. */
if (s2n_verify_cbc(conn, mac, &en) < 0) {
+ __VERIFIER_assume(0);
POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}

Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
diff --git a/tls/s2n_record_read_cbc.c b/tls/s2n_record_read_cbc.c
index bb06523..60a2eed 100644
index 346e6571..0f2527e9 100644
--- a/tls/s2n_record_read_cbc.c
+++ b/tls/s2n_record_read_cbc.c
@@ -30,6 +30,8 @@
#include "utils/s2n_safety.h"
@@ -26,6 +26,8 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"

+extern int g_padding_length;
+
int s2n_record_parse_cbc(
const struct s2n_cipher_suite *cipher_suite,
struct s2n_connection *conn,
@@ -86,6 +88,8 @@ int s2n_record_parse_cbc(
const struct s2n_cipher_suite *cipher_suite,
struct s2n_connection *conn,
@@ -82,6 +84,8 @@ int s2n_record_parse_cbc(

/* Subtract the padding length */
POSIX_ENSURE_GT(en.size, 0);
Expand All @@ -20,11 +20,11 @@ index bb06523..60a2eed 100644
uint32_t out = 0;
POSIX_GUARD(s2n_sub_overflow(payload_length, en.data[en.size - 1] + 1, &out));
payload_length = out;
@@ -107,6 +111,7 @@ int s2n_record_parse_cbc(
@@ -103,6 +107,7 @@ int s2n_record_parse_cbc(

/* Padding */
/* Padding. This finalizes the provided HMAC. */
if (s2n_verify_cbc(conn, mac, &en) < 0) {
+ __VERIFIER_assume(0);
POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}

52 changes: 52 additions & 0 deletions tests/unit/s2n_record_read_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ int main(int argc, char *argv[])
{
BEGIN_TEST();

DEFER_CLEANUP(struct s2n_cert_chain_and_key *chain_and_key = NULL,
s2n_cert_chain_and_key_ptr_free);
EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&chain_and_key,
S2N_DEFAULT_TEST_CERT_CHAIN, S2N_DEFAULT_TEST_PRIVATE_KEY));

/* Test s2n_sslv2_record_header_parse */
{
const struct {
Expand Down Expand Up @@ -159,5 +164,52 @@ int main(int argc, char *argv[])
};
};

/* Ensure that the input buffer is wiped after failing to read a record */
{
DEFER_CLEANUP(struct s2n_config *config = s2n_config_new_minimal(), s2n_config_ptr_free);
EXPECT_NOT_NULL(config);
EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
EXPECT_SUCCESS(s2n_config_disable_x509_verification(config));

DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT),
s2n_connection_ptr_free);
EXPECT_NOT_NULL(client);
DEFER_CLEANUP(struct s2n_connection *server = s2n_connection_new(S2N_SERVER),
s2n_connection_ptr_free);
EXPECT_NOT_NULL(server);

EXPECT_SUCCESS(s2n_connection_set_config(client, config));
EXPECT_SUCCESS(s2n_connection_set_config(server, config));

EXPECT_SUCCESS(s2n_connection_set_blinding(server, S2N_SELF_SERVICE_BLINDING));

DEFER_CLEANUP(struct s2n_test_io_stuffer_pair stuffer_pair = { 0 },
s2n_io_stuffer_pair_free);
EXPECT_OK(s2n_io_stuffer_pair_init(&stuffer_pair));
EXPECT_OK(s2n_connections_set_io_stuffer_pair(client, server, &stuffer_pair));

EXPECT_SUCCESS(s2n_negotiate_test_server_and_client(server, client));

/* Send some test data to the server. */
uint8_t test_data[] = "hello world";
s2n_blocked_status blocked = S2N_NOT_BLOCKED;
ssize_t send_size = s2n_send(client, test_data, sizeof(test_data), &blocked);
EXPECT_EQUAL(send_size, sizeof(test_data));

/* Invalidate an encrypted byte to cause decryption to fail. */
struct s2n_stuffer invalidation_stuffer = stuffer_pair.server_in;
uint8_t *first_byte = s2n_stuffer_raw_read(&invalidation_stuffer, 1);
EXPECT_NOT_NULL(first_byte);
*first_byte += 1;

/* Receive the invalid data. */
uint8_t buffer[sizeof(test_data)] = { 0 };
ssize_t ret = s2n_recv(server, buffer, sizeof(buffer), &blocked);
EXPECT_FAILURE_WITH_ERRNO(ret, S2N_ERR_DECRYPT);

/* Ensure that the invalid data has been wiped from the input buffer. */
EXPECT_TRUE(s2n_stuffer_is_wiped(&server->in));
}

END_TEST();
}
3 changes: 3 additions & 0 deletions tls/s2n_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,9 @@ S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **c
return S2N_RESULT_OK;
}

/* Ensure that conn->in doesn't contain any leftover invalid or unauthenticated data. */
RESULT_GUARD_POSIX(s2n_stuffer_wipe(&(*conn)->in));

int error_code = s2n_errno;
int error_type = s2n_error_get_type(error_code);

Expand Down
1 change: 0 additions & 1 deletion tls/s2n_record_read_cbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ int s2n_record_parse_cbc(

/* Padding. This finalizes the provided HMAC. */
if (s2n_verify_cbc(conn, mac, &en) < 0) {
POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}

Expand Down
1 change: 0 additions & 1 deletion tls/s2n_record_read_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ int s2n_record_parse_stream(
POSIX_GUARD(s2n_hmac_digest(mac, check_digest, mac_digest_size));

if (s2n_hmac_digest_verify(en.data + payload_length, check_digest, mac_digest_size) < 0) {
POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
POSIX_BAIL(S2N_ERR_BAD_MESSAGE);
}

Expand Down

0 comments on commit 4220a4d

Please sign in to comment.