in tls/s2n_connection.c [514:661]
int s2n_connection_wipe(struct s2n_connection *conn)
{
/* First make a copy of everything we'd like to save, which isn't very much. */
int mode = conn->mode;
struct s2n_config *config = conn->config;
struct s2n_stuffer alert_in = {0};
struct s2n_stuffer reader_alert_out = {0};
struct s2n_stuffer writer_alert_out = {0};
struct s2n_stuffer client_ticket_to_decrypt = {0};
struct s2n_stuffer handshake_io = {0};
struct s2n_stuffer client_hello_raw_message = {0};
struct s2n_stuffer header_in = {0};
struct s2n_stuffer in = {0};
struct s2n_stuffer out = {0};
/* Session keys will be wiped. Preserve structs to avoid reallocation */
struct s2n_session_key initial_client_key = {0};
struct s2n_session_key initial_server_key = {0};
struct s2n_session_key secure_client_key = {0};
struct s2n_session_key secure_server_key = {0};
/* Parts of the hmac states will be wiped. Preserve structs to avoid reallocation */
struct s2n_connection_hmac_handles hmac_handles = {0};
/* Some required structures might have been freed to conserve memory between handshakes.
* Restore them.
*/
if (!conn->handshake.hashes) {
POSIX_GUARD_RESULT(s2n_handshake_hashes_new(&conn->handshake.hashes));
}
POSIX_GUARD_RESULT(s2n_handshake_hashes_wipe(conn->handshake.hashes));
struct s2n_handshake_hashes *handshake_hashes = conn->handshake.hashes;
if (!conn->prf_space) {
POSIX_GUARD_RESULT(s2n_prf_new(conn));
}
POSIX_GUARD_RESULT(s2n_prf_wipe(conn));
struct s2n_prf_working_space *prf_workspace = conn->prf_space;
/* Wipe all of the sensitive stuff */
POSIX_GUARD(s2n_connection_wipe_keys(conn));
POSIX_GUARD(s2n_connection_reset_hmacs(conn));
POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
POSIX_GUARD(s2n_stuffer_wipe(&conn->reader_alert_out));
POSIX_GUARD(s2n_stuffer_wipe(&conn->writer_alert_out));
POSIX_GUARD(s2n_stuffer_wipe(&conn->client_ticket_to_decrypt));
POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
POSIX_GUARD(s2n_stuffer_wipe(&conn->client_hello.raw_message));
POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
POSIX_GUARD(s2n_stuffer_wipe(&conn->in));
POSIX_GUARD(s2n_stuffer_wipe(&conn->out));
POSIX_GUARD_RESULT(s2n_psk_parameters_wipe(&conn->psk_params));
/* Wipe the I/O-related info and restore the original socket if necessary */
POSIX_GUARD(s2n_connection_wipe_io(conn));
POSIX_GUARD(s2n_free(&conn->client_ticket));
POSIX_GUARD(s2n_free(&conn->status_response));
POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
POSIX_GUARD(s2n_free(&conn->peer_quic_transport_parameters));
POSIX_GUARD(s2n_free(&conn->server_early_data_context));
POSIX_GUARD(s2n_free(&conn->tls13_ticket_fields.session_secret));
/* Allocate memory for handling handshakes */
POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, S2N_LARGE_RECORD_LENGTH));
/* Truncate the message buffers to save memory, we will dynamically resize it as needed */
POSIX_GUARD(s2n_stuffer_resize(&conn->client_hello.raw_message, 0));
POSIX_GUARD(s2n_stuffer_resize(&conn->in, 0));
POSIX_GUARD(s2n_stuffer_resize(&conn->out, 0));
/* Remove context associated with connection */
conn->context = NULL;
conn->verify_host_fn_overridden = 0;
conn->verify_host_fn = NULL;
conn->data_for_verify_host = NULL;
/* Clone the stuffers */
/* ignore gcc 4.7 address warnings because dest is allocated on the stack */
/* pragma gcc diagnostic was added in gcc 4.6 */
#if S2N_GCC_VERSION_AT_LEAST(4,6,0)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#endif
POSIX_CHECKED_MEMCPY(&alert_in, &conn->alert_in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&reader_alert_out, &conn->reader_alert_out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&writer_alert_out, &conn->writer_alert_out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&client_ticket_to_decrypt, &conn->client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&handshake_io, &conn->handshake.io, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&client_hello_raw_message, &conn->client_hello.raw_message, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&header_in, &conn->header_in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&in, &conn->in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&out, &conn->out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&initial_client_key, &conn->initial.client_key, sizeof(struct s2n_session_key));
POSIX_CHECKED_MEMCPY(&initial_server_key, &conn->initial.server_key, sizeof(struct s2n_session_key));
POSIX_CHECKED_MEMCPY(&secure_client_key, &conn->secure.client_key, sizeof(struct s2n_session_key));
POSIX_CHECKED_MEMCPY(&secure_server_key, &conn->secure.server_key, sizeof(struct s2n_session_key));
POSIX_GUARD(s2n_connection_save_hmac_state(&hmac_handles, conn));
#if S2N_GCC_VERSION_AT_LEAST(4,6,0)
#pragma GCC diagnostic pop
#endif
POSIX_GUARD(s2n_connection_zero(conn, mode, config));
POSIX_CHECKED_MEMCPY(&conn->alert_in, &alert_in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->reader_alert_out, &reader_alert_out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->writer_alert_out, &writer_alert_out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->client_ticket_to_decrypt, &client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->handshake.io, &handshake_io, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->client_hello.raw_message, &client_hello_raw_message, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->header_in, &header_in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->in, &in, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->out, &out, sizeof(struct s2n_stuffer));
POSIX_CHECKED_MEMCPY(&conn->initial.client_key, &initial_client_key, sizeof(struct s2n_session_key));
POSIX_CHECKED_MEMCPY(&conn->initial.server_key, &initial_server_key, sizeof(struct s2n_session_key));
POSIX_CHECKED_MEMCPY(&conn->secure.client_key, &secure_client_key, sizeof(struct s2n_session_key));
POSIX_CHECKED_MEMCPY(&conn->secure.server_key, &secure_server_key, sizeof(struct s2n_session_key));
POSIX_GUARD(s2n_connection_restore_hmac_state(conn, &hmac_handles));
conn->handshake.hashes = handshake_hashes;
conn->prf_space = prf_workspace;
/* Re-initialize hash and hmac states */
POSIX_GUARD(s2n_connection_init_hmacs(conn));
POSIX_GUARD_RESULT(s2n_psk_parameters_init(&conn->psk_params));
conn->server_keying_material_lifetime = ONE_WEEK_IN_SEC;
/* Require all handshakes hashes. This set can be reduced as the handshake progresses. */
POSIX_GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
if (conn->mode == S2N_SERVER) {
/* Start with the highest protocol version so that the highest common protocol version can be selected */
/* during handshake. */
conn->server_protocol_version = s2n_highest_protocol_version;
conn->client_protocol_version = s2n_unknown_protocol_version;
conn->actual_protocol_version = s2n_unknown_protocol_version;
}
else {
/* For clients, also set actual_protocol_version. Record generation uses that value for the initial */
/* ClientHello record version. Not all servers ignore the record version in ClientHello. */
conn->server_protocol_version = s2n_unknown_protocol_version;
conn->client_protocol_version = s2n_highest_protocol_version;
conn->actual_protocol_version = s2n_highest_protocol_version;
}
return 0;
}