Skip to content

Commit b9792f8

Browse files
author
Boquan Fang
committed
address PR feedbacks
1 parent e38bd76 commit b9792f8

File tree

5 files changed

+40
-59
lines changed

5 files changed

+40
-59
lines changed

crypto/s2n_ecc_evp.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ int s2n_ecc_evp_write_params_point(struct s2n_ecc_evp_params *ecc_evp_params, st
424424
}
425425
#else
426426
uint8_t point_len = 0;
427+
struct s2n_blob point_blob = { 0 };
427428

428429
DEFER_CLEANUP(EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(ecc_evp_params->evp_pkey), EC_KEY_free_pointer);
429430
S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
@@ -433,20 +434,17 @@ int s2n_ecc_evp_write_params_point(struct s2n_ecc_evp_params *ecc_evp_params, st
433434

434435
POSIX_GUARD(s2n_ecc_evp_calculate_point_length(point, group, &point_len));
435436
S2N_ERROR_IF(point_len != ecc_evp_params->negotiated_curve->share_size, S2N_ERR_ECDHE_SERIALIZING);
436-
437-
/* Use a temporary stuffer copy to perform s2n_stuffer_raw_write, so the original stuffer won't be tainted */
438-
POSIX_GUARD(s2n_stuffer_reserve_space(out, point_len));
439-
struct s2n_stuffer copy = *out;
440-
441-
struct s2n_blob point_blob = { 0 };
442-
point_blob.data = s2n_stuffer_raw_write(&copy, point_len);
437+
point_blob.data = s2n_stuffer_raw_write(out, point_len);
443438
POSIX_ENSURE_REF(point_blob.data);
444439
point_blob.size = point_len;
445440

446441
POSIX_GUARD(s2n_ecc_evp_write_point_data_snug(point, group, &point_blob));
447442

448-
out->write_cursor = copy.write_cursor;
449-
out->high_water_mark = copy.high_water_mark;
443+
/**
444+
* point_blob.data is not accessable outside of this function.
445+
* The stuffer is not tainted after it goes out of this function's scope.
446+
*/
447+
out->tainted = false;
450448
#endif
451449
return 0;
452450
}
@@ -462,13 +460,6 @@ int s2n_ecc_evp_write_params(struct s2n_ecc_evp_params *ecc_evp_params, struct s
462460

463461
uint8_t key_share_size = ecc_evp_params->negotiated_curve->share_size;
464462

465-
/* Use a temporary stuffer copy to perform s2n_stuffer_raw_write, so the original stuffer won't be tainted */
466-
struct s2n_stuffer copy = *out;
467-
468-
/* Remember where the written data starts */
469-
written->data = s2n_stuffer_raw_write(&copy, 0);
470-
POSIX_ENSURE_REF(written->data);
471-
472463
POSIX_GUARD(s2n_stuffer_write_uint8(out, TLS_EC_CURVE_TYPE_NAMED));
473464
POSIX_GUARD(s2n_stuffer_write_uint16(out, ecc_evp_params->negotiated_curve->iana_id));
474465
POSIX_GUARD(s2n_stuffer_write_uint8(out, key_share_size));
@@ -478,6 +469,18 @@ int s2n_ecc_evp_write_params(struct s2n_ecc_evp_params *ecc_evp_params, struct s
478469
/* key share + key share size (1) + iana (2) + curve type (1) */
479470
written->size = key_share_size + 4;
480471

472+
/* Write data after writing ecc evp params to avoid stuffer resize failure */
473+
uint32_t read_cursor = out->read_cursor;
474+
uint32_t written_data_location = s2n_stuffer_data_available(out) - written->size;
475+
476+
POSIX_GUARD(s2n_stuffer_rewrite(out));
477+
POSIX_GUARD(s2n_stuffer_skip_write(out, written_data_location));
478+
POSIX_GUARD(s2n_stuffer_skip_read(out, read_cursor));
479+
480+
/* Remember where the written data starts */
481+
written->data = s2n_stuffer_raw_write(out, written->size);
482+
POSIX_ENSURE_REF(written->data);
483+
481484
return written->size;
482485
}
483486

error/s2n_errno.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ static const char *no_such_error = "Internal s2n error";
139139
ERR_ENTRY(S2N_ERR_RESIZE_TAINTED_STUFFER, "cannot resize a tainted stuffer") \
140140
ERR_ENTRY(S2N_ERR_STUFFER_OUT_OF_DATA, "stuffer is out of data") \
141141
ERR_ENTRY(S2N_ERR_STUFFER_IS_FULL, "stuffer is full") \
142+
ERR_ENTRY(S2N_ERR_STUFFER_IS_TAINTED, "stuffer is tainted") \
142143
ERR_ENTRY(S2N_ERR_STUFFER_NOT_FOUND, "stuffer expected bytes were not found") \
143144
ERR_ENTRY(S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA, "stuffer has unprocessed data") \
144145
ERR_ENTRY(S2N_ERR_HASH_INVALID_ALGORITHM, "invalid hash algorithm") \

error/s2n_errno.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ typedef enum {
170170
S2N_ERR_RESIZE_TAINTED_STUFFER,
171171
S2N_ERR_STUFFER_OUT_OF_DATA,
172172
S2N_ERR_STUFFER_IS_FULL,
173+
S2N_ERR_STUFFER_IS_TAINTED,
173174
S2N_ERR_STUFFER_NOT_FOUND,
174175
S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA,
175176
S2N_ERR_HASH_INVALID_ALGORITHM,

tests/unit/s2n_client_hello_test.c

Lines changed: 13 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@
4949
#define MAX_CIPHER_SUITE_COUNT (CIPHER_SUITES_MAX_LENGTH / S2N_TLS_CIPHER_SUITE_LEN)
5050
/* Drop 150 cipher suites from max, so that the total handshake message length won't exceed 64KB */
5151
#define REDUCED_CIPHER_SUITE_COUNT (MAX_CIPHER_SUITE_COUNT - NUM_OF_CIPHER_SUITES_TO_DROP)
52-
/* Reducing cipher suites by 150 creates approximately 300 bytes margin below maximum handshake length */
53-
#define ESTIMATED_MAX_HANDSHAKE_LENGTH_MARGIN (NUM_OF_CIPHER_SUITES_TO_DROP * S2N_TLS_CIPHER_SUITE_LEN)
5452

5553
int s2n_parse_client_hello(struct s2n_connection *conn);
5654
S2N_RESULT s2n_client_hello_get_raw_extension(uint16_t extension_iana,
@@ -1963,9 +1961,6 @@ int main(int argc, char **argv)
19631961

19641962
/* Test: Client Hello is slightly less than 64KB */
19651963
{
1966-
DEFER_CLEANUP(struct s2n_config *client_config = s2n_config_new(), s2n_config_ptr_free);
1967-
EXPECT_NOT_NULL(client_config);
1968-
19691964
DEFER_CLEANUP(struct s2n_config *server_config = s2n_config_new(), s2n_config_ptr_free);
19701965
EXPECT_NOT_NULL(server_config);
19711966

@@ -1982,23 +1977,16 @@ int main(int argc, char **argv)
19821977
.suites = test_cipher_suites,
19831978
};
19841979

1985-
struct s2n_security_policy test_security_policy = {
1986-
.minimum_protocol_version = S2N_TLS12,
1987-
.cipher_preferences = &test_cipher_suites_preferences,
1988-
.kem_preferences = &kem_preferences_null,
1989-
.signature_preferences = &s2n_signature_preferences_20240501,
1990-
.ecc_preferences = &s2n_ecc_preferences_20240501,
1991-
.rules = {
1992-
[S2N_PERFECT_FORWARD_SECRECY] = true,
1993-
},
1994-
};
1980+
const struct s2n_security_policy *default_policy = NULL;
1981+
EXPECT_SUCCESS(s2n_find_security_policy_from_version("default", &default_policy));
19951982

1996-
EXPECT_SUCCESS(s2n_config_disable_x509_verification(client_config));
1983+
/* Use default security policy but with custom cipher suites preferences */
1984+
struct s2n_security_policy test_security_policy = *default_policy;
1985+
test_security_policy.cipher_preferences = &test_cipher_suites_preferences;
19971986

19981987
DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT),
19991988
s2n_connection_ptr_free);
20001989
EXPECT_NOT_NULL(client);
2001-
EXPECT_SUCCESS(s2n_connection_set_config(client, client_config));
20021990
EXPECT_SUCCESS(s2n_connection_set_blinding(client, S2N_SELF_SERVICE_BLINDING));
20031991
client->security_policy_override = &test_security_policy;
20041992

@@ -2015,22 +2003,15 @@ int main(int argc, char **argv)
20152003

20162004
EXPECT_OK(s2n_negotiate_test_server_and_client_until_message(server, client, SERVER_HELLO));
20172005

2018-
/* handshake.io shouldn't be tainted after sending and receiving large client hello */
2019-
EXPECT_TRUE(client->handshake.io.tainted == 0);
2020-
EXPECT_TRUE(server->handshake.io.tainted == 0);
2021-
20222006
struct s2n_client_hello *client_hello = s2n_connection_get_client_hello(server);
20232007
EXPECT_NOT_NULL(client_hello);
2024-
uint32_t handshake_max_len_margin = S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH - s2n_client_hello_get_raw_message_length(client_hello);
2025-
/* Size of Client Hello is less than 300 bytes from the maximum handshake length */
2026-
EXPECT_TRUE(handshake_max_len_margin < ESTIMATED_MAX_HANDSHAKE_LENGTH_MARGIN);
2008+
2009+
/* Size of Client Hello should be less than S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH*/
2010+
EXPECT_TRUE(s2n_client_hello_get_raw_message_length(client_hello) < S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH);
20272011
}
20282012

20292013
/* Test: Client Hello is larger than 64KB */
20302014
{
2031-
DEFER_CLEANUP(struct s2n_config *client_config = s2n_config_new(), s2n_config_ptr_free);
2032-
EXPECT_NOT_NULL(client_config);
2033-
20342015
DEFER_CLEANUP(struct s2n_config *server_config = s2n_config_new(), s2n_config_ptr_free);
20352016
EXPECT_NOT_NULL(server_config);
20362017

@@ -2048,23 +2029,16 @@ int main(int argc, char **argv)
20482029
.suites = test_cipher_suites,
20492030
};
20502031

2051-
struct s2n_security_policy test_security_policy = {
2052-
.minimum_protocol_version = S2N_TLS12,
2053-
.cipher_preferences = &test_cipher_suites_preferences,
2054-
.kem_preferences = &kem_preferences_null,
2055-
.signature_preferences = &s2n_signature_preferences_20240501,
2056-
.ecc_preferences = &s2n_ecc_preferences_20240501,
2057-
.rules = {
2058-
[S2N_PERFECT_FORWARD_SECRECY] = true,
2059-
},
2060-
};
2032+
const struct s2n_security_policy *default_policy = NULL;
2033+
EXPECT_SUCCESS(s2n_find_security_policy_from_version("default", &default_policy));
20612034

2062-
EXPECT_SUCCESS(s2n_config_disable_x509_verification(client_config));
2035+
/* Use default security policy but with custom cipher suites preferences */
2036+
struct s2n_security_policy test_security_policy = *default_policy;
2037+
test_security_policy.cipher_preferences = &test_cipher_suites_preferences;
20632038

20642039
DEFER_CLEANUP(struct s2n_connection *client = s2n_connection_new(S2N_CLIENT),
20652040
s2n_connection_ptr_free);
20662041
EXPECT_NOT_NULL(client);
2067-
EXPECT_SUCCESS(s2n_connection_set_config(client, client_config));
20682042
EXPECT_SUCCESS(s2n_connection_set_blinding(client, S2N_SELF_SERVICE_BLINDING));
20692043
client->security_policy_override = &test_security_policy;
20702044

@@ -2087,10 +2061,6 @@ int main(int argc, char **argv)
20872061
/* The size of Client Hello exceeds S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH */
20882062
EXPECT_TRUE(s2n_stuffer_data_available(&io_pair.server_in) > S2N_MAXIMUM_HANDSHAKE_MESSAGE_LENGTH);
20892063
EXPECT_ERROR_WITH_ERRNO(s2n_negotiate_test_server_and_client_until_message(server, client, SERVER_HELLO), S2N_ERR_BAD_MESSAGE);
2090-
2091-
/* handshake.io shouldn't be tainted after sending and receiving large client hello */
2092-
EXPECT_TRUE(client->handshake.io.tainted == 0);
2093-
EXPECT_TRUE(server->handshake.io.tainted == 0);
20942064
}
20952065

20962066
EXPECT_SUCCESS(s2n_cert_chain_and_key_free(chain_and_key));

tls/extensions/s2n_extension_type.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ int s2n_extension_send(const s2n_extension_type *extension_type, struct s2n_conn
114114
/* Write extension data */
115115
POSIX_GUARD(extension_type->send(conn, out));
116116

117+
/**
118+
* Stuffer might get tainted when sending extensions, while we can't find all of them at the moment.
119+
* Catch tainted stuffer during testing only, so we won't break our customers in production.
120+
*/
121+
POSIX_DEBUG_ENSURE(out->tainted, S2N_ERR_STUFFER_IS_TAINTED);
122+
117123
/* Record extension size */
118124
POSIX_GUARD(s2n_stuffer_write_vector_size(&extension_size_bytes));
119125

0 commit comments

Comments
 (0)