in tls/s2n_handshake_io.c [1012:1102]
int s2n_conn_set_handshake_type(struct s2n_connection *conn)
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->secure);
POSIX_GUARD_RESULT(s2n_conn_choose_state_machine(conn, conn->actual_protocol_version));
if (IS_TLS13_HANDSHAKE(conn)) {
POSIX_GUARD_RESULT(s2n_conn_set_tls13_handshake_type(conn));
return S2N_SUCCESS;
}
POSIX_GUARD_RESULT(s2n_handshake_type_reset(conn));
/* A handshake type has been negotiated */
POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, NEGOTIATED));
s2n_cert_auth_type client_cert_auth_type;
POSIX_GUARD(s2n_connection_get_client_auth_type(conn, &client_cert_auth_type));
if (conn->mode == S2N_CLIENT && client_cert_auth_type == S2N_CERT_AUTH_REQUIRED) {
/* If we're a client, and Client Auth is REQUIRED, then the Client must expect the CLIENT_CERT_REQ Message */
POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
} else if (conn->mode == S2N_SERVER && client_cert_auth_type != S2N_CERT_AUTH_NONE) {
/* If we're a server, and Client Auth is REQUIRED or OPTIONAL, then the server must send the CLIENT_CERT_REQ Message*/
POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, CLIENT_AUTH));
}
if (conn->npn_negotiated) {
POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_NPN));
}
if (conn->config->use_tickets) {
if (conn->session_ticket_status == S2N_DECRYPT_TICKET) {
/* We reuse the session if a valid TLS12 ticket is provided.
* Otherwise, we will perform a full handshake and then generate
* a new session ticket. */
if (s2n_result_is_ok(s2n_resume_decrypt_session(conn, &conn->client_ticket_to_decrypt))) {
return S2N_SUCCESS;
}
POSIX_GUARD_RESULT(s2n_validate_ems_status(conn));
/* Set up the handshake to send a session ticket since a valid ticket was not provided */
if (s2n_result_is_ok(s2n_config_is_encrypt_key_available(conn->config))) {
conn->session_ticket_status = S2N_NEW_TICKET;
POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
}
/* If a session ticket is presented by the client, then skip lookup in Session ID server cache */
goto skip_cache_lookup;
}
if (conn->session_ticket_status == S2N_NEW_TICKET) {
POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, WITH_SESSION_TICKET));
}
}
/* If a TLS session is resumed, the Server should respond in its ServerHello with the same SessionId the
* Client sent in the ClientHello. */
if (conn->actual_protocol_version <= S2N_TLS12 && conn->mode == S2N_SERVER && s2n_allowed_to_cache_connection(conn)) {
int r = s2n_resume_from_cache(conn);
if (r == S2N_SUCCESS || (r < S2N_SUCCESS && S2N_ERROR_IS_BLOCKING(s2n_errno))) {
return r;
}
POSIX_GUARD_RESULT(s2n_validate_ems_status(conn));
}
skip_cache_lookup:
if (conn->mode == S2N_CLIENT && conn->client_session_resumed == 1) {
return S2N_SUCCESS;
}
/* If we're doing full handshake, generate a new session id. */
POSIX_GUARD(s2n_generate_new_client_session_id(conn));
/* If we get this far, it's a full handshake */
POSIX_GUARD_RESULT(s2n_handshake_type_set_flag(conn, FULL_HANDSHAKE));
bool is_ephemeral = false;
POSIX_GUARD_RESULT(s2n_kex_is_ephemeral(conn->secure->cipher_suite->key_exchange_alg, &is_ephemeral));
if (is_ephemeral) {
POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, TLS12_PERFECT_FORWARD_SECRECY));
}
if (s2n_server_can_send_ocsp(conn) || s2n_server_sent_ocsp(conn)) {
POSIX_GUARD_RESULT(s2n_handshake_type_set_tls12_flag(conn, OCSP_STATUS));
}
return S2N_SUCCESS;
}