diff --git a/api/s2n.h b/api/s2n.h index 6bce51c0342..43ad5e085ce 100644 --- a/api/s2n.h +++ b/api/s2n.h @@ -1882,6 +1882,30 @@ S2N_API extern uint64_t s2n_connection_get_delay(struct s2n_connection *conn); */ S2N_API extern int s2n_connection_set_cipher_preferences(struct s2n_connection *conn, const char *version); +/** + * Used to indicate the type of key update that is being requested. For further + * information refer to `s2n_connection_request_key_update`. +*/ +typedef enum { + S2N_KEY_UPDATE_NOT_REQUESTED = 0, + S2N_KEY_UPDATE_REQUESTED +} s2n_peer_key_update; + +/** + * Signals the connection to do a key_update at the next possible opportunity. Note that the resulting key update message + * will not be sent until `s2n_send` is called. + * + * @param conn The connection object to trigger the key update on. + * @param peer_request Indicates if a key update should also be requested + * of the peer. When set to `S2N_KEY_UPDATE_NOT_REQUESTED`, then only the sending + * key of `conn` will be updated. If set to `S2N_KEY_UPDATE_REQUESTED`, then + * the sending key of conn will be updated AND the peer will be requested to + * update their sending key. Note that s2n-tls currently only supports + * `peer_request` being set to `S2N_KEY_UPDATE_NOT_REQUESTED` and will return + * S2N_FAILURE if any other value is used. + * @returns S2N_SUCCESS on success. S2N_FAILURE on failure +*/ +S2N_API extern int s2n_connection_request_key_update(struct s2n_connection *conn, s2n_peer_key_update peer_request); /** * Appends the provided application protocol to the preference list * diff --git a/bindings/rust/s2n-tls/src/config.rs b/bindings/rust/s2n-tls/src/config.rs index 3137a9d248d..9c42ad2b532 100644 --- a/bindings/rust/s2n-tls/src/config.rs +++ b/bindings/rust/s2n-tls/src/config.rs @@ -151,7 +151,6 @@ impl Drop for Config { } } -#[derive(Default)] pub struct Builder { config: Config, load_system_certs: bool, @@ -743,6 +742,12 @@ impl Builder { } } +impl Default for Builder { + fn default() -> Self { + Self::new() + } +} + pub(crate) struct Context { refcount: AtomicUsize, pub(crate) client_hello_callback: Option>, diff --git a/bindings/rust/s2n-tls/src/testing/s2n_tls.rs b/bindings/rust/s2n-tls/src/testing/s2n_tls.rs index 1b6f12eae03..8fcf7c86db6 100644 --- a/bindings/rust/s2n-tls/src/testing/s2n_tls.rs +++ b/bindings/rust/s2n-tls/src/testing/s2n_tls.rs @@ -756,32 +756,36 @@ mod tests { // Load the server certificate into the trust store by overriding the OpenSSL default // certificate location. temp_env::with_var("SSL_CERT_FILE", Some(keypair.cert_path()), || { - let mut builder = Builder::new(); - builder - .load_pem(keypair.cert(), keypair.key()) - .unwrap() - .set_security_policy(&security::DEFAULT_TLS13) - .unwrap() - .set_verify_host_callback(InsecureAcceptAllCertificatesHandler {}) - .unwrap(); + // Test the Builder itself, and also the Builder produced by the Config builder() API. + for mut builder in [Builder::new(), Config::builder()] { + builder + .load_pem(keypair.cert(), keypair.key()) + .unwrap() + .set_security_policy(&security::DEFAULT_TLS13) + .unwrap() + .set_verify_host_callback(InsecureAcceptAllCertificatesHandler {}) + .unwrap(); - // Disable loading system certificates - builder.with_system_certs(false).unwrap(); + // Disable loading system certificates + builder.with_system_certs(false).unwrap(); - let config = builder.build().unwrap(); - let mut config_with_system_certs = config.clone(); + let config = builder.build().unwrap(); + let mut config_with_system_certs = config.clone(); - let mut pair = tls_pair(config); + let mut pair = tls_pair(config); - // System certificates should not be loaded into the trust store. The handshake - // should fail since the certificate should not be trusted. - assert!(poll_tls_pair_result(&mut pair).is_err()); + // System certificates should not be loaded into the trust store. The handshake + // should fail since the certificate should not be trusted. + assert!(poll_tls_pair_result(&mut pair).is_err()); - // The handshake should succeed after trusting the certificate. - unsafe { - s2n_tls_sys::s2n_config_load_system_certs(config_with_system_certs.as_mut_ptr()); + // The handshake should succeed after trusting the certificate. + unsafe { + s2n_tls_sys::s2n_config_load_system_certs( + config_with_system_certs.as_mut_ptr(), + ); + } + establish_connection(config_with_system_certs); } - establish_connection(config_with_system_certs); }); } diff --git a/tests/sidetrail/working/patches/cbc.patch b/tests/sidetrail/working/patches/cbc.patch index 2af00d6b356..b47f10eb776 100644 --- a/tests/sidetrail/working/patches/cbc.patch +++ b/tests/sidetrail/working/patches/cbc.patch @@ -35,7 +35,7 @@ index 401ab760..f39cc7e2 100644 */ int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, struct s2n_blob *decrypted) { -- uint8_t mac_digest_size; +- uint8_t mac_digest_size = 0; - POSIX_GUARD(s2n_hmac_digest_size(hmac->alg, &mac_digest_size)); + uint8_t mac_digest_size = DIGEST_SIZE; + //POSIX_GUARD(s2n_hmac_digest_size(hmac->alg, &mac_digest_size)); diff --git a/tests/unit/s2n_key_update_test.c b/tests/unit/s2n_key_update_test.c index 23955cdd2a8..be8bf8b1874 100644 --- a/tests/unit/s2n_key_update_test.c +++ b/tests/unit/s2n_key_update_test.c @@ -333,7 +333,7 @@ int main(int argc, char **argv) EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0)); EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, client_conn)); - s2n_atomic_flag_set(&client_conn->key_update_pending); + EXPECT_SUCCESS(s2n_connection_request_key_update(client_conn, S2N_KEY_UPDATE_NOT_REQUESTED)); s2n_blocked_status blocked = 0; EXPECT_SUCCESS(s2n_key_update_send(client_conn, &blocked)); @@ -677,5 +677,27 @@ int main(int argc, char **argv) } } + /* s2n_connection_key_update_requested */ + { + /* null safety */ + { + EXPECT_FAILURE_WITH_ERRNO(s2n_connection_request_key_update(NULL, S2N_KEY_UPDATE_NOT_REQUESTED), S2N_ERR_NULL); + }; + + /* usage */ + { + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); + EXPECT_FAILURE_WITH_ERRNO(s2n_connection_request_key_update(conn, S2N_KEY_UPDATE_REQUESTED), S2N_ERR_INVALID_ARGUMENT); + }; + + /* happy path */ + { + DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free); + EXPECT_FALSE(s2n_atomic_flag_test(&conn->key_update_pending)); + EXPECT_SUCCESS(s2n_connection_request_key_update(conn, S2N_KEY_UPDATE_NOT_REQUESTED)); + EXPECT_TRUE(s2n_atomic_flag_test(&conn->key_update_pending)); + }; + }; + END_TEST(); } diff --git a/tests/unit/s2n_key_update_threads_test.c b/tests/unit/s2n_key_update_threads_test.c index 0a7ef4dd4c0..d54807c6587 100644 --- a/tests/unit/s2n_key_update_threads_test.c +++ b/tests/unit/s2n_key_update_threads_test.c @@ -35,7 +35,7 @@ _##name##_record_alg.encryption_limit = limit; \ name.record_alg = &_##name##_record_alg; -S2N_RESULT s2n_set_key_update_request_for_testing(keyupdate_request request); +S2N_RESULT s2n_set_key_update_request_for_testing(s2n_peer_key_update request); static void *s2n_send_random_data(void *arg) { diff --git a/tls/s2n_cbc.c b/tls/s2n_cbc.c index cc9d0546dcb..20367a10a0f 100644 --- a/tls/s2n_cbc.c +++ b/tls/s2n_cbc.c @@ -45,7 +45,7 @@ */ int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, struct s2n_blob *decrypted) { - uint8_t mac_digest_size; + uint8_t mac_digest_size = 0; POSIX_GUARD(s2n_hmac_digest_size(hmac->alg, &mac_digest_size)); /* The record has to be at least big enough to contain the MAC, diff --git a/tls/s2n_key_update.c b/tls/s2n_key_update.c index d10d7c5b244..90c49c9756e 100644 --- a/tls/s2n_key_update.c +++ b/tls/s2n_key_update.c @@ -24,12 +24,12 @@ #include "utils/s2n_atomic.h" #include "utils/s2n_safety.h" -static keyupdate_request key_update_request_val = S2N_KEY_UPDATE_NOT_REQUESTED; +static s2n_peer_key_update key_update_request_val = S2N_KEY_UPDATE_NOT_REQUESTED; int s2n_key_update_write(struct s2n_blob *out); int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequence_number); -S2N_RESULT s2n_set_key_update_request_for_testing(keyupdate_request request) +S2N_RESULT s2n_set_key_update_request_for_testing(s2n_peer_key_update request) { RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST); key_update_request_val = request; @@ -146,3 +146,12 @@ int s2n_check_record_limit(struct s2n_connection *conn, struct s2n_blob *sequenc return S2N_SUCCESS; } + +int s2n_connection_request_key_update(struct s2n_connection *conn, s2n_peer_key_update peer_request) +{ + POSIX_ENSURE_REF(conn); + /* s2n-tls does not currently support requesting key updates from peers */ + POSIX_ENSURE(peer_request == S2N_KEY_UPDATE_NOT_REQUESTED, S2N_ERR_INVALID_ARGUMENT); + s2n_atomic_flag_set(&conn->key_update_pending); + return S2N_SUCCESS; +} diff --git a/tls/s2n_key_update.h b/tls/s2n_key_update.h index 2b787f08487..79a103d8261 100644 --- a/tls/s2n_key_update.h +++ b/tls/s2n_key_update.h @@ -25,10 +25,5 @@ typedef enum { RECEIVING } keyupdate_status; -typedef enum { - S2N_KEY_UPDATE_NOT_REQUESTED = 0, - S2N_KEY_UPDATE_REQUESTED -} keyupdate_request; - int s2n_key_update_recv(struct s2n_connection *conn, struct s2n_stuffer *request); int s2n_key_update_send(struct s2n_connection *conn, s2n_blocked_status *blocked);