int s2n_conn_set_handshake_type()

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;
}