/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#include "api/s2n.h"
#include "crypto/s2n_rsa_signing.h"
#include "pq-crypto/s2n_pq.h"
#include "s2n_test.h"
#include "testlib/s2n_testlib.h"
#include "tls/s2n_ecc_preferences.h"
#include "tls/s2n_handshake.h"
#include "tls/s2n_kem_preferences.h"
#include "tls/s2n_security_policies.h"

/* Include C file directly to access static functions */
#include "tls/s2n_handshake_io.c"

int s2n_test_tls13_pq_handshake(const struct s2n_security_policy *client_sec_policy,
        const struct s2n_security_policy *server_sec_policy, const struct s2n_kem_group *expected_kem_group,
        const struct s2n_ecc_named_curve *expected_curve, bool hrr_expected, bool len_prefix_expected)
{
    /* XOR check: can expect to negotiate either a KEM group, or a classic EC curve, but not both/neither */
    POSIX_ENSURE((expected_kem_group == NULL) != (expected_curve == NULL), S2N_ERR_SAFETY);

    /* Set up connections */
    struct s2n_connection *client_conn = NULL, *server_conn = NULL;
    POSIX_ENSURE_REF(client_conn = s2n_connection_new(S2N_CLIENT));
    POSIX_ENSURE_REF(server_conn = s2n_connection_new(S2N_SERVER));

    struct s2n_config *client_config = NULL, *server_config = NULL;
    POSIX_ENSURE_REF(client_config = s2n_config_new());
    POSIX_ENSURE_REF(server_config = s2n_config_new());

    char cert_chain[S2N_MAX_TEST_PEM_SIZE] = { 0 }, private_key[S2N_MAX_TEST_PEM_SIZE] = { 0 };
    struct s2n_cert_chain_and_key *chain_and_key = NULL;
    POSIX_ENSURE_REF(chain_and_key = s2n_cert_chain_and_key_new());
    POSIX_GUARD(s2n_read_test_pem(S2N_ECDSA_P384_PKCS1_CERT_CHAIN, cert_chain, S2N_MAX_TEST_PEM_SIZE));
    POSIX_GUARD(s2n_read_test_pem(S2N_ECDSA_P384_PKCS1_KEY, private_key, S2N_MAX_TEST_PEM_SIZE));
    POSIX_GUARD(s2n_cert_chain_and_key_load_pem(chain_and_key, cert_chain, private_key));
    POSIX_GUARD(s2n_config_add_cert_chain_and_key_to_store(client_config, chain_and_key));
    POSIX_GUARD(s2n_config_add_cert_chain_and_key_to_store(server_config, chain_and_key));

    POSIX_GUARD(s2n_connection_set_config(client_conn, client_config));
    POSIX_GUARD(s2n_connection_set_config(server_conn, server_config));

    struct s2n_stuffer client_to_server = { 0 }, server_to_client = { 0 };
    POSIX_GUARD(s2n_stuffer_growable_alloc(&client_to_server, 2048));
    POSIX_GUARD(s2n_stuffer_growable_alloc(&server_to_client, 2048));

    POSIX_GUARD(s2n_connection_set_io_stuffers(&server_to_client, &client_to_server, client_conn));
    POSIX_GUARD(s2n_connection_set_io_stuffers(&client_to_server, &server_to_client, server_conn));

    client_conn->security_policy_override = client_sec_policy;
    server_conn->security_policy_override = server_sec_policy;

    /* Client sends ClientHello */
    POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(client_conn), CLIENT_HELLO);
    POSIX_GUARD(s2n_handshake_write_io(client_conn));

    POSIX_ENSURE_EQ(client_conn->actual_protocol_version, S2N_TLS13);
    POSIX_ENSURE_EQ(server_conn->actual_protocol_version, 0); /* Won't get set until after server reads ClientHello */
    POSIX_ENSURE_EQ(client_conn->handshake.handshake_type, INITIAL);

    /* Server reads ClientHello */
    POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), CLIENT_HELLO);
    POSIX_GUARD(s2n_handshake_read_io(server_conn));

    POSIX_ENSURE_EQ(server_conn->actual_protocol_version, S2N_TLS13); /* Server is now on TLS13 */

    /* Assert that the server chose the correct group */
    if (expected_kem_group) {
        /* Client should always determine whether the Hybrid KEM used len_prefixed format, and server should match client's behavior. */
        POSIX_ENSURE_EQ(len_prefix_expected, client_conn->kex_params.client_kem_group_params.kem_params.len_prefixed);
        POSIX_ENSURE_EQ(len_prefix_expected, s2n_tls13_client_must_use_hybrid_kem_length_prefix(client_sec_policy->kem_preferences));
        POSIX_ENSURE_EQ(server_conn->kex_params.client_kem_group_params.kem_params.len_prefixed, client_conn->kex_params.client_kem_group_params.kem_params.len_prefixed);

        POSIX_ENSURE_EQ(expected_kem_group, server_conn->kex_params.server_kem_group_params.kem_group);
        POSIX_ENSURE_EQ(expected_kem_group->kem, server_conn->kex_params.server_kem_group_params.kem_params.kem);
        POSIX_ENSURE_EQ(expected_kem_group->curve, server_conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_ecc_evp_params.negotiated_curve);
    } else {
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_kem_group_params.kem_group);
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_kem_group_params.kem_params.kem);
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
        POSIX_ENSURE_EQ(expected_curve, server_conn->kex_params.server_ecc_evp_params.negotiated_curve);
    }

    /* Server sends ServerHello or HRR */
    POSIX_GUARD(s2n_conn_set_handshake_type(server_conn));
    if (hrr_expected) {
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), HELLO_RETRY_MSG);
    } else {
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), SERVER_HELLO);
    }
    POSIX_GUARD(s2n_handshake_write_io(server_conn));

    /* Server sends CCS */
    POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), SERVER_CHANGE_CIPHER_SPEC);
    POSIX_GUARD(s2n_handshake_write_io(server_conn));

    if (hrr_expected) {
        /* Client reads HRR */
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(client_conn), SERVER_HELLO);
        POSIX_GUARD(s2n_handshake_read_io(client_conn));
        POSIX_GUARD(s2n_conn_set_handshake_type(client_conn));
        POSIX_ENSURE_NE(0, client_conn->handshake.handshake_type & HELLO_RETRY_REQUEST);

        /* Client reads CCS */
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(client_conn), CLIENT_CHANGE_CIPHER_SPEC);
        POSIX_GUARD(s2n_handshake_read_io(client_conn));

        /* Client sends CCS and new ClientHello */
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(client_conn), CLIENT_CHANGE_CIPHER_SPEC);
        POSIX_GUARD(s2n_handshake_write_io(client_conn));
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(client_conn), CLIENT_HELLO);
        POSIX_GUARD(s2n_handshake_write_io(client_conn));

        /* Server reads CCS (doesn't change state machine) */
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), CLIENT_HELLO);
        POSIX_GUARD(s2n_handshake_read_io(server_conn));

        /* Server reads new ClientHello */
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), CLIENT_HELLO);
        POSIX_GUARD(s2n_handshake_read_io(server_conn));

        /* Server sends ServerHello */
        POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(server_conn), SERVER_HELLO);
        POSIX_GUARD(s2n_handshake_write_io(server_conn));
    }

    /* Client reads ServerHello */
    POSIX_ENSURE_EQ(s2n_conn_get_current_message_type(client_conn), SERVER_HELLO);
    POSIX_GUARD(s2n_handshake_read_io(client_conn));

    /* We've gotten far enough in the handshake that both client and server should have
     * derived the shared secrets, so we don't send/receive any more messages. */

    /* Assert that the correct group was negotiated (we re-check the server group to assert that
     * nothing unexpected changed between then and now while e.g. processing HRR) */
    if (expected_kem_group) {
        POSIX_ENSURE_EQ(expected_kem_group, client_conn->kex_params.server_kem_group_params.kem_group);
        POSIX_ENSURE_EQ(expected_kem_group->kem, client_conn->kex_params.server_kem_group_params.kem_params.kem);
        POSIX_ENSURE_EQ(expected_kem_group->curve, client_conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
        POSIX_ENSURE_EQ(NULL, client_conn->kex_params.server_ecc_evp_params.negotiated_curve);

        POSIX_ENSURE_EQ(expected_kem_group, server_conn->kex_params.server_kem_group_params.kem_group);
        POSIX_ENSURE_EQ(expected_kem_group->kem, server_conn->kex_params.server_kem_group_params.kem_params.kem);
        POSIX_ENSURE_EQ(expected_kem_group->curve, server_conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_ecc_evp_params.negotiated_curve);
    } else {
        POSIX_ENSURE_EQ(NULL, client_conn->kex_params.server_kem_group_params.kem_group);
        POSIX_ENSURE_EQ(NULL, client_conn->kex_params.server_kem_group_params.kem_params.kem);
        POSIX_ENSURE_EQ(NULL, client_conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
        POSIX_ENSURE_EQ(expected_curve, client_conn->kex_params.server_ecc_evp_params.negotiated_curve);

        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_kem_group_params.kem_group);
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_kem_group_params.kem_params.kem);
        POSIX_ENSURE_EQ(NULL, server_conn->kex_params.server_kem_group_params.ecc_params.negotiated_curve);
        POSIX_ENSURE_EQ(expected_curve, server_conn->kex_params.server_ecc_evp_params.negotiated_curve);
    }

    /* Verify basic properties of secrets */
    s2n_tls13_connection_keys(server_secret_info, server_conn);
    s2n_tls13_connection_keys(client_secret_info, client_conn);
    POSIX_ENSURE_EQ(server_conn->secure->cipher_suite, client_conn->secure->cipher_suite);
    if (server_conn->secure->cipher_suite == &s2n_tls13_aes_256_gcm_sha384) {
        POSIX_ENSURE_EQ(server_secret_info.size, 48);
        POSIX_ENSURE_EQ(client_secret_info.size, 48);
    } else {
        POSIX_ENSURE_EQ(server_secret_info.size, 32);
        POSIX_ENSURE_EQ(client_secret_info.size, 32);
    }

    /* Verify secrets aren't just zero'ed memory */
    uint8_t all_zeros[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
    POSIX_CHECKED_MEMSET((void *) all_zeros, 0, S2N_TLS13_SECRET_MAX_LEN);
    struct s2n_tls13_secrets *client_secrets = &client_conn->secrets.version.tls13;
    struct s2n_tls13_secrets *server_secrets = &server_conn->secrets.version.tls13;
    POSIX_ENSURE_EQ(server_secret_info.size, client_secret_info.size);
    uint8_t size = server_secret_info.size;
    POSIX_ENSURE_EQ(client_conn->secrets.extract_secret_type, S2N_HANDSHAKE_SECRET);
    POSIX_ENSURE_NE(0, memcmp(all_zeros, client_secrets->extract_secret, size));
    POSIX_ENSURE_NE(0, memcmp(all_zeros, client_secrets->client_handshake_secret, size));
    POSIX_ENSURE_NE(0, memcmp(all_zeros, client_secrets->server_handshake_secret, size));
    POSIX_ENSURE_EQ(server_conn->secrets.extract_secret_type, S2N_HANDSHAKE_SECRET);
    POSIX_ENSURE_NE(0, memcmp(all_zeros, server_secrets->extract_secret, size));
    POSIX_ENSURE_NE(0, memcmp(all_zeros, server_secrets->client_handshake_secret, size));
    POSIX_ENSURE_NE(0, memcmp(all_zeros, server_secrets->server_handshake_secret, size));

    /* Verify client and server secrets are equal to each other */
    POSIX_ENSURE_EQ(0, memcmp(server_secrets->extract_secret, client_secrets->extract_secret, size));
    POSIX_ENSURE_EQ(0, memcmp(server_secrets->client_handshake_secret, client_secrets->client_handshake_secret, size));
    POSIX_ENSURE_EQ(0, memcmp(server_secrets->server_handshake_secret, client_secrets->server_handshake_secret, size));

    /* Clean up */
    POSIX_GUARD(s2n_stuffer_free(&client_to_server));
    POSIX_GUARD(s2n_stuffer_free(&server_to_client));

    POSIX_GUARD(s2n_connection_free(client_conn));
    POSIX_GUARD(s2n_connection_free(server_conn));

    POSIX_GUARD(s2n_cert_chain_and_key_free(chain_and_key));
    POSIX_GUARD(s2n_config_free(server_config));
    POSIX_GUARD(s2n_config_free(client_config));

    return S2N_SUCCESS;
}

int main()
{
    BEGIN_TEST();

    if (!s2n_is_tls13_fully_supported()) {
        END_TEST();
    }

    /* Additional KEM preferences/security policies to test against. These policies can only be used
     * as the server's policy in this test: when generating the ClientHello, the client relies on
     * the security_policy_selection[] array (in s2n_security_policies.c) to determine if it should
     * write the supported_groups extension. Because these unofficial policies don't exist in that
     * array, the supported_groups extension won't get sent and the handshake won't complete as expected. */

    /* Kyber */
    const struct s2n_kem_group *kyber_test_groups[] = {
#if EVP_APIS_SUPPORTED
        &s2n_x25519_kyber_512_r3,
#endif
        &s2n_secp256r1_kyber_512_r3,
    };

    const struct s2n_kem_preferences kyber_test_prefs_draft0 = {
        .kem_count = 0,
        .kems = NULL,
        .tls13_kem_group_count = s2n_array_len(kyber_test_groups),
        .tls13_kem_groups = kyber_test_groups,
        .tls13_pq_hybrid_draft_revision = 0
    };

    const struct s2n_security_policy kyber_test_policy_draft0 = {
        .minimum_protocol_version = S2N_TLS10,
        .cipher_preferences = &cipher_preferences_20190801,
        .kem_preferences = &kyber_test_prefs_draft0,
        .signature_preferences = &s2n_signature_preferences_20200207,
        .ecc_preferences = &s2n_ecc_preferences_20200310,
    };

    const struct s2n_kem_preferences kyber_test_prefs_draft5 = {
        .kem_count = 0,
        .kems = NULL,
        .tls13_kem_group_count = s2n_array_len(kyber_test_groups),
        .tls13_kem_groups = kyber_test_groups,
        .tls13_pq_hybrid_draft_revision = 5
    };

    const struct s2n_security_policy kyber_test_policy_draft5 = {
        .minimum_protocol_version = S2N_TLS10,
        .cipher_preferences = &cipher_preferences_20190801,
        .kem_preferences = &kyber_test_prefs_draft5,
        .signature_preferences = &s2n_signature_preferences_20200207,
        .ecc_preferences = &s2n_ecc_preferences_20200310,
    };

    const struct s2n_security_policy ecc_retry_policy = {
        .minimum_protocol_version = security_policy_pq_tls_1_0_2020_12.minimum_protocol_version,
        .cipher_preferences = security_policy_pq_tls_1_0_2020_12.cipher_preferences,
        .kem_preferences = security_policy_pq_tls_1_0_2020_12.kem_preferences,
        .signature_preferences = security_policy_pq_tls_1_0_2020_12.signature_preferences,
        .ecc_preferences = security_policy_test_tls13_retry.ecc_preferences,
    };

    const struct s2n_kem_group *expected_kyber_r3_group = &s2n_x25519_kyber_512_r3;
    const struct s2n_ecc_named_curve *expected_curve = &s2n_ecc_curve_x25519;

    if (!s2n_is_evp_apis_supported()) {
        expected_kyber_r3_group = &s2n_secp256r1_kyber_512_r3;
        expected_curve = &s2n_ecc_curve_secp256r1;
    }

    struct pq_handshake_test_vector {
        const struct s2n_security_policy *client_policy;
        const struct s2n_security_policy *server_policy;
        const struct s2n_kem_group *expected_kem_group;
        const struct s2n_ecc_named_curve *expected_curve;
        bool hrr_expected;
        bool len_prefix_expected;
    };

    /* Test vectors that expect to negotiate PQ assume that PQ is enabled in s2n.
     * If PQ is disabled, the expected negotiation outcome is overridden below
     * before performing the handshake test. */
    const struct pq_handshake_test_vector test_vectors[] = {
        /* Server and Client both support PQ and TLS 1.3 */
        {
                .client_policy = &security_policy_pq_tls_1_1_2021_05_21,
                .server_policy = &security_policy_pq_tls_1_1_2021_05_21,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2021_05_22,
                .server_policy = &security_policy_pq_tls_1_0_2021_05_22,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2021_05_23,
                .server_policy = &security_policy_pq_tls_1_0_2021_05_23,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2021_05_24,
                .server_policy = &security_policy_pq_tls_1_0_2021_05_24,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2021_05_26,
                .server_policy = &security_policy_pq_tls_1_0_2021_05_26,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2023_01_24,
                .server_policy = &security_policy_pq_tls_1_0_2023_01_24,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = false,
        },

        /* Check that we're backwards and forwards compatible with different Hybrid PQ draft revisions*/
        {
                .client_policy = &kyber_test_policy_draft0,
                .server_policy = &kyber_test_policy_draft5,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &kyber_test_policy_draft5,
                .server_policy = &kyber_test_policy_draft0,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = false,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2021_05_24,
                .server_policy = &security_policy_pq_tls_1_0_2023_01_24,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },
        {
                .client_policy = &security_policy_pq_tls_1_0_2023_01_24,
                .server_policy = &security_policy_pq_tls_1_0_2021_05_24,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = false,
        },

        /* Server supports all KEM groups; client sends a PQ key share and an EC key
         * share; server chooses to negotiate client's first choice PQ without HRR. */
        {
                .client_policy = &security_policy_pq_tls_1_0_2020_12,
                .server_policy = &security_policy_pq_tls_1_0_2020_12,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },

        /* Server supports only one KEM group and it is the client's first choice;
         * client sends a PQ share and an EC share; server chooses to negotiate PQ
         * without HRR. */
        {
                .client_policy = &security_policy_pq_tls_1_0_2020_12,
                .server_policy = &kyber_test_policy_draft0,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },

        /* Server supports only one KEM group and it is the client's first choice;
         * client sends a PQ share and an EC share; server chooses to negotiate PQ
         * without HRR. */
        {
                .client_policy = &security_policy_pq_tls_1_0_2020_12,
                .server_policy = &kyber_test_policy_draft5,
                .expected_kem_group = expected_kyber_r3_group,
                .expected_curve = NULL,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },

        /* Server does not support PQ; client sends a PQ key share and an EC key share;
         * server should negotiate EC without HRR. */
        {
                .client_policy = &security_policy_pq_tls_1_0_2020_12,
                .server_policy = &security_policy_test_all_tls13,
                .expected_kem_group = NULL,
                .expected_curve = expected_curve,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },

        /* Server does not support PQ; client sends a PQ key share, but no EC shares;
         * server should negotiate EC and send HRR. */
        {
                .client_policy = &ecc_retry_policy,
                .server_policy = &security_policy_test_all_tls13,
                .expected_kem_group = NULL,
                .expected_curve = expected_curve,
                .hrr_expected = true,
                .len_prefix_expected = true,
        },

        /* Server supports PQ, but client does not. Client sent an EC share,
         * EC should be negotiated without HRR */
        {
                .client_policy = &security_policy_test_all_tls13,
                .server_policy = &security_policy_pq_tls_1_0_2020_12,
                .expected_kem_group = NULL,
                .expected_curve = expected_curve,
                .hrr_expected = false,
                .len_prefix_expected = true,
        },

        /* Server supports PQ, but client does not. Client did not send any EC shares,
         * EC should be negotiated after exchanging HRR */
        {
                .client_policy = &security_policy_test_tls13_retry,
                .server_policy = &security_policy_pq_tls_1_0_2020_12,
                .expected_kem_group = NULL,
                .expected_curve = expected_curve,
                .hrr_expected = true,
                .len_prefix_expected = true,
        },
    };

    for (size_t i = 0; i < s2n_array_len(test_vectors); i++) {
        const struct pq_handshake_test_vector *vector = &test_vectors[i];
        const struct s2n_security_policy *client_policy = vector->client_policy;
        const struct s2n_security_policy *server_policy = vector->server_policy;
        const struct s2n_kem_group *kem_group = vector->expected_kem_group;
        const struct s2n_ecc_named_curve *curve = vector->expected_curve;
        bool hrr_expected = vector->hrr_expected;
        bool len_prefix_expected = vector->len_prefix_expected;

        if (!s2n_pq_is_enabled()) {
            /* If PQ is disabled, we always expected to negotiate ECC. */
            kem_group = NULL;
            curve = expected_curve;
        }

        EXPECT_SUCCESS(s2n_test_tls13_pq_handshake(client_policy, server_policy, kem_group, curve, hrr_expected, len_prefix_expected));
    }

    END_TEST();
}
