/*
 * 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 "tls/s2n_resume.h"

#include "s2n_test.h"
#include "tests/testlib/s2n_testlib.h"
#include "tls/s2n_tls.h"
/* To test static function */
#include "tls/s2n_resume.c"
#include "utils/s2n_safety.h"

#define TICKET_ISSUE_TIME_BYTES          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
#define TICKET_AGE_ADD_BYTES             0x01, 0x01, 0x01, 0x01
#define TICKET_AGE_ADD                   16843009
#define SECRET_LEN                       0x02
#define SECRET                           0x03, 0x04
#define KEYING_MATERIAL_EXPIRATION_BYTES 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08
#define EMPTY_EARLY_DATA_SIZE            0x00, 0x00, 0x00, 0x00
#define CLIENT_TICKET                    0x10, 0x10

#define NONEMPTY_EARLY_DATA_SIZE 0x12
#define APP_PROTOCOL_LEN         0x02
#define APP_PROTOCOL             0x05, 0x06
#define EARLY_DATA_CONTEXT_LEN   0x03
#define EARLY_DATA_CONTEXT       0x07, 0x08, 0x09

#define SIZE_OF_MAX_EARLY_DATA_SIZE sizeof(uint32_t)
#define SIZE_OF_KEYING_EXPIRATION   sizeof(uint64_t)

#define S2N_TLS12_STATE_SIZE_IN_BYTES_WITHOUT_EMS S2N_TLS12_STATE_SIZE_IN_BYTES - 1

#define SECONDS_TO_NANOS(seconds) ((seconds) * (uint64_t) ONE_SEC_IN_NANOS)

const uint64_t ticket_issue_time = 283686952306183;
const uint64_t keying_material_expiration = 283686952306184;

static int s2n_test_session_ticket_callback(struct s2n_connection *conn, void *ctx, struct s2n_session_ticket *ticket)
{
    return S2N_SUCCESS;
}

static int mock_time(void *data, uint64_t *nanoseconds)
{
    *nanoseconds = ticket_issue_time;
    return S2N_SUCCESS;
}

int main(int argc, char **argv)
{
    BEGIN_TEST();

    /* Two random secrets of different sizes */
    S2N_BLOB_FROM_HEX(test_master_secret,
            "ee85dd54781bd4d8a100589a9fe6ac9a3797b811e977f549cd"
            "531be2441d7c63e2b9729d145c11d84af35957727565a4");

    S2N_BLOB_FROM_HEX(test_session_secret,
            "18df06843d13a08bf2a449844c5f8a"
            "478001bc4d4c627984d5a41da8d0402919");

    uint8_t tls12_ticket[S2N_TLS12_STATE_SIZE_IN_BYTES_WITHOUT_EMS] = {
        S2N_SERIALIZED_FORMAT_TLS12_V1,
        S2N_TLS12,
        TLS_RSA_WITH_AES_128_GCM_SHA256,
        TICKET_ISSUE_TIME_BYTES,
    };

    uint8_t tls12_ticket_with_ems[S2N_TLS12_STATE_SIZE_IN_BYTES] = {
        S2N_SERIALIZED_FORMAT_TLS12_V3,
        S2N_TLS12,
        TLS_RSA_WITH_AES_128_GCM_SHA256,
        TICKET_ISSUE_TIME_BYTES,
    };

    uint8_t tls13_ticket[] = {
        S2N_SERIALIZED_FORMAT_TLS13_V1,
        S2N_TLS13,
        TLS_AES_128_GCM_SHA256,
        TICKET_ISSUE_TIME_BYTES,
        TICKET_AGE_ADD_BYTES,
        SECRET_LEN,
        SECRET,
        EMPTY_EARLY_DATA_SIZE,
    };

    uint8_t tls13_server_ticket[] = {
        S2N_SERIALIZED_FORMAT_TLS13_V1,
        S2N_TLS13,
        TLS_AES_128_GCM_SHA256,
        TICKET_ISSUE_TIME_BYTES,
        TICKET_AGE_ADD_BYTES,
        SECRET_LEN,
        SECRET,
        KEYING_MATERIAL_EXPIRATION_BYTES,
        EMPTY_EARLY_DATA_SIZE,
    };

    uint8_t tls13_ticket_with_early_data[] = {
        S2N_SERIALIZED_FORMAT_TLS13_V1,
        S2N_TLS13,
        TLS_AES_128_GCM_SHA256,
        TICKET_ISSUE_TIME_BYTES,
        TICKET_AGE_ADD_BYTES,
        SECRET_LEN,
        SECRET,
        0x00,
        0x00,
        0x00,
        NONEMPTY_EARLY_DATA_SIZE,
        APP_PROTOCOL_LEN,
        APP_PROTOCOL,
        0x00,
        EARLY_DATA_CONTEXT_LEN,
        EARLY_DATA_CONTEXT,
    };

    uint8_t faulty_format_ticket[] = {
        0xFF,
    };

    /* s2n_connection_get_session_state_size */
    {
        /* Safety */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            size_t size = 0;
            EXPECT_ERROR_WITH_ERRNO(s2n_connection_get_session_state_size(NULL, &size), S2N_ERR_NULL);
            EXPECT_ERROR_WITH_ERRNO(s2n_connection_get_session_state_size(conn, NULL), S2N_ERR_NULL);
            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* TLS1.2: session state is fixed */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            conn->actual_protocol_version = S2N_TLS12;
            conn->secure->cipher_suite = &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256;

            /* Result matches constant */
            size_t actual_size = 0;
            EXPECT_OK(s2n_connection_get_session_state_size(conn, &actual_size));
            EXPECT_EQUAL(actual_size, S2N_TLS12_STATE_SIZE_IN_BYTES);

            /* Result matches actual size of data */
            DEFER_CLEANUP(struct s2n_stuffer actual_data = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&actual_data, actual_size));
            EXPECT_SUCCESS(s2n_tls12_serialize_resumption_state(conn, &actual_data));
            const uint32_t expected_size = s2n_stuffer_data_available(&actual_data);
            if (expected_size != actual_size) {
                fprintf(stderr, "\nS2N_TLS12_STATE_SIZE_IN_BYTES (%i) should be set to %u\n\n",
                        S2N_TLS12_STATE_SIZE_IN_BYTES, expected_size);
            }
            EXPECT_EQUAL(actual_size, s2n_stuffer_data_available(&actual_data));

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* TLS1.3 with all variables empty except non-zero session secret */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_128_gcm_sha256;

            /* Set non-zero length secret */
            uint8_t secret_size = 0;
            EXPECT_SUCCESS(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
            EXPECT_SUCCESS(s2n_realloc(&conn->tls13_ticket_fields.session_secret, secret_size));

            /* Result matches constant */
            size_t actual_size = 0;
            EXPECT_OK(s2n_connection_get_session_state_size(conn, &actual_size));
            EXPECT_EQUAL(actual_size, S2N_TLS13_FIXED_STATE_SIZE + secret_size);

            /* Result matches actual size of data */
            DEFER_CLEANUP(struct s2n_stuffer actual_data = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&actual_data, actual_size));
            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &actual_data));
            const uint32_t expected_size = s2n_stuffer_data_available(&actual_data);
            if (actual_size != expected_size) {
                fprintf(stderr, "\nS2N_TLS13_FIXED_STATE_SIZE (%i) should be set to %u\n\n",
                        S2N_TLS13_FIXED_STATE_SIZE, expected_size);
            }
            EXPECT_EQUAL(actual_size, expected_size);
            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* TLS1.3 with all variables empty except non-zero session secret */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            conn->actual_protocol_version = S2N_TLS13;
            /* use a different hash digest to get more coverage/certainty */
            conn->secure->cipher_suite = &s2n_tls13_aes_256_gcm_sha384;

            /* Set non-zero length secret */
            uint8_t secret_size = 0;
            EXPECT_SUCCESS(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
            EXPECT_SUCCESS(s2n_realloc(&conn->tls13_ticket_fields.session_secret, secret_size));

            /* Result matches constant */
            size_t actual_size = 0;
            EXPECT_OK(s2n_connection_get_session_state_size(conn, &actual_size));
            EXPECT_EQUAL(actual_size, S2N_TLS13_FIXED_STATE_SIZE + secret_size);

            /* Result matches actual size of data */
            DEFER_CLEANUP(struct s2n_stuffer actual_data = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&actual_data, actual_size));
            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &actual_data));
            EXPECT_EQUAL(actual_size, s2n_stuffer_data_available(&actual_data));

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Minimal TLS1.3 with early data: all variable fields empty except non-zero session secret */
        {
            DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free);
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, 1));

            /* Set non-zero length secret */
            uint8_t secret_size = 0;
            EXPECT_SUCCESS(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
            EXPECT_SUCCESS(s2n_alloc(&conn->tls13_ticket_fields.session_secret, secret_size));

            /* Result matches constants */
            size_t actual_size = 0;
            EXPECT_OK(s2n_connection_get_session_state_size(conn, &actual_size));
            EXPECT_EQUAL(actual_size, S2N_TLS13_FIXED_STATE_SIZE + S2N_TLS13_FIXED_EARLY_DATA_STATE_SIZE + secret_size);

            /* Result matches actual size of data */
            DEFER_CLEANUP(struct s2n_stuffer actual_data = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&actual_data, actual_size));
            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &actual_data));
            const uint32_t expected_size = s2n_stuffer_data_available(&actual_data);
            if (actual_size != expected_size) {
                fprintf(stderr, "\nS2N_TLS13_FIXED_EARLY_DATA_STATE_SIZE (%i) should be set to %u\n\n",
                        S2N_TLS13_FIXED_EARLY_DATA_STATE_SIZE, expected_size - S2N_TLS13_FIXED_STATE_SIZE);
            }
            EXPECT_EQUAL(actual_size, expected_size);
        };

        /* TLS1.3 with early data: all variable fields set */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_256_gcm_sha384;

            /* Set non-zero length secret */
            uint8_t secret_size = 0;
            EXPECT_SUCCESS(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
            EXPECT_SUCCESS(s2n_alloc(&conn->tls13_ticket_fields.session_secret, secret_size));

            /* Set early data fields */
            const uint8_t data[] = "test data";
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, 1));
            EXPECT_MEMCPY_SUCCESS(conn->application_protocol, data, sizeof(data));
            EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(conn, data, sizeof(data)));

            /* Result matches constants */
            size_t actual_size = 0;
            EXPECT_OK(s2n_connection_get_session_state_size(conn, &actual_size));
            EXPECT_NOT_EQUAL(actual_size, 0);

            /* Result matches actual size of data */
            DEFER_CLEANUP(struct s2n_stuffer actual_data = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&actual_data, actual_size));
            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &actual_data));
            EXPECT_EQUAL(actual_size, s2n_stuffer_data_available(&actual_data));

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };
    };

    /* s2n_connection_get_session_length */
    {
        /* Safety */
        EXPECT_EQUAL(s2n_connection_get_session_length(NULL), 0);

        /* Session Ticket */
        {
            const uint16_t client_ticket_size = 10;

            DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, true));

            /* TLS 1.2 */
            {
                DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
                EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, client_ticket_size));
                conn->actual_protocol_version = S2N_TLS12;
                int session_length = s2n_connection_get_session_length(conn);
                EXPECT_NOT_EQUAL(session_length, 0);

                /* Result matches size expected by s2n_connection_get_session */
                DEFER_CLEANUP(struct s2n_blob session_data = { 0 }, s2n_free);
                EXPECT_SUCCESS(s2n_alloc(&session_data, session_length));
                EXPECT_SUCCESS(s2n_connection_get_session(conn, session_data.data, session_data.size));
            }

            /* TLS 1.3 */
            {
                DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT), s2n_connection_ptr_free);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
                EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, client_ticket_size));
                conn->actual_protocol_version = S2N_TLS13;
                conn->secure->cipher_suite = &s2n_tls13_aes_256_gcm_sha384;

                /* Set non-zero length secret */
                uint8_t secret_size = 0;
                EXPECT_SUCCESS(s2n_hmac_digest_size(conn->secure->cipher_suite->prf_alg, &secret_size));
                EXPECT_SUCCESS(s2n_alloc(&conn->tls13_ticket_fields.session_secret, secret_size));
                int session_length = s2n_connection_get_session_length(conn);
                EXPECT_NOT_EQUAL(session_length, 0);

                /* Result matches size expected by s2n_connection_get_session */
                DEFER_CLEANUP(struct s2n_blob session_data = { 0 }, s2n_free);
                EXPECT_SUCCESS(s2n_alloc(&session_data, session_length));
                EXPECT_SUCCESS(s2n_connection_get_session(conn, session_data.data, session_data.size));
            }
        };

        /* Session ID */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, true));
            EXPECT_SUCCESS(s2n_config_set_session_cache_onoff(config, true));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->session_id_len = 5;

            /* TLS1.3: Always zero. Stateful tickets are not yet supported. */
            {
                conn->actual_protocol_version = S2N_TLS13;
                uint8_t data = 0;
                EXPECT_EQUAL(s2n_connection_get_session_length(conn), 0);
                EXPECT_SUCCESS(s2n_connection_get_session(conn, &data, 1));
                EXPECT_EQUAL(data, 0);
            };

            /* TLS1.2 */
            {
                conn->actual_protocol_version = S2N_TLS12;

                int session_length = s2n_connection_get_session_length(conn);
                EXPECT_NOT_EQUAL(session_length, 0);

                /* Result matches size expected by s2n_connection_get_session */
                DEFER_CLEANUP(struct s2n_blob session_id_data = { 0 }, s2n_free);
                EXPECT_SUCCESS(s2n_alloc(&session_id_data, session_length));
                EXPECT_SUCCESS(s2n_connection_get_session(conn, session_id_data.data, session_id_data.size));
            };

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };
    };

    /* s2n_connection_get_session_id_length */
    {
        struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
        EXPECT_NOT_NULL(conn);

        EXPECT_FAILURE_WITH_ERRNO(s2n_connection_get_session_id_length(NULL), S2N_ERR_NULL);

        conn->session_id_len = 5;
        conn->actual_protocol_version = S2N_TLS12;
        EXPECT_EQUAL(s2n_connection_get_session_id_length(conn), 5);

        conn->actual_protocol_version = S2N_TLS13;
        EXPECT_EQUAL(s2n_connection_get_session_id_length(conn), 0);

        EXPECT_SUCCESS(s2n_connection_free(conn));
    };

    /* s2n_tls12_serialize_resumption_state */
    {
        struct s2n_connection *conn = NULL;
        EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
        conn->actual_protocol_version = S2N_TLS12;

        struct s2n_blob blob = { 0 };
        struct s2n_stuffer stuffer = { 0 };
        EXPECT_SUCCESS(s2n_blob_init(&blob, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN));
        EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &blob));
        EXPECT_SUCCESS(s2n_stuffer_write_bytes(&stuffer, test_master_secret.data, S2N_TLS_SECRET_LEN));
        conn->secure->cipher_suite = &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256;

        uint8_t ems_state[] = { false, true };
        for (size_t i = 0; i < s2n_array_len(ems_state); i++) {
            /* Test the two different EMS states */
            conn->ems_negotiated = ems_state[i];

            uint8_t s_data[S2N_TLS12_STATE_SIZE_IN_BYTES] = { 0 };
            struct s2n_blob state_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
            struct s2n_stuffer output = { 0 };

            EXPECT_SUCCESS(s2n_stuffer_init(&output, &state_blob));
            EXPECT_SUCCESS(s2n_tls12_serialize_resumption_state(conn, &output));

            uint8_t serial_id = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &serial_id));
            EXPECT_EQUAL(serial_id, S2N_SERIALIZED_FORMAT_TLS12_V3);

            uint8_t version = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &version));
            EXPECT_EQUAL(version, S2N_TLS12);

            uint8_t iana_value[2] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, iana_value, S2N_TLS_CIPHER_SUITE_LEN));
            EXPECT_BYTEARRAY_EQUAL(conn->secure->cipher_suite->iana_value, &iana_value, S2N_TLS_CIPHER_SUITE_LEN);

            /* Current time */
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, sizeof(uint64_t)));

            uint8_t master_secret[S2N_TLS_SECRET_LEN] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, master_secret, S2N_TLS_SECRET_LEN));
            EXPECT_BYTEARRAY_EQUAL(test_master_secret.data, master_secret, S2N_TLS_SECRET_LEN);

            uint8_t ems_info = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &ems_info));
            EXPECT_EQUAL(ems_info, ems_state[i]);
        }

        EXPECT_SUCCESS(s2n_connection_free(conn));
    };

    /* s2n_tls13_serialize_resumption_state */
    {
        /* Safety checks */
        {
            struct s2n_connection *conn = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            struct s2n_stuffer output = { 0 };

            EXPECT_ERROR_WITH_ERRNO(s2n_tls13_serialize_resumption_state(NULL, &output), S2N_ERR_NULL);
            EXPECT_ERROR_WITH_ERRNO(s2n_tls13_serialize_resumption_state(conn, NULL), S2N_ERR_NULL);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Test TLS1.3 client serialization */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));

            struct s2n_connection *conn = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256;

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
            EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));

            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));

            uint8_t serial_id = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &serial_id));
            EXPECT_EQUAL(serial_id, S2N_SERIALIZED_FORMAT_TLS13_V1);

            uint8_t version = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &version));
            EXPECT_EQUAL(version, S2N_TLS13);

            uint8_t iana_value[2] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, iana_value, S2N_TLS_CIPHER_SUITE_LEN));
            EXPECT_BYTEARRAY_EQUAL(conn->secure->cipher_suite->iana_value, &iana_value, S2N_TLS_CIPHER_SUITE_LEN);

            uint64_t actual_ticket_issue_time = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint64(&output, &actual_ticket_issue_time));
            EXPECT_EQUAL(actual_ticket_issue_time, ticket_issue_time);

            uint32_t ticket_age_add = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &ticket_age_add));
            EXPECT_EQUAL(ticket_age_add, conn->tls13_ticket_fields.ticket_age_add);

            uint8_t secret_len = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &secret_len));
            EXPECT_EQUAL(secret_len, conn->tls13_ticket_fields.session_secret.size);

            uint8_t session_secret[S2N_TLS_SECRET_LEN] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, session_secret, secret_len));
            EXPECT_BYTEARRAY_EQUAL(test_session_secret.data, session_secret, secret_len);

            uint32_t max_early_data_size = 1;
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &max_early_data_size));
            EXPECT_EQUAL(max_early_data_size, 0);

            EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0);
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Test TLS1.3 server serialization: keying material expiration time */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            EXPECT_SUCCESS(s2n_connection_set_server_keying_material_lifetime(conn, 1));
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256;

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
            EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));

            /* New expiration time */
            {
                uint64_t expected_expiration_time = ticket_issue_time + ONE_SEC_IN_NANOS;

                EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));
                EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, s2n_stuffer_data_available(&output)));
                EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_MAX_EARLY_DATA_SIZE));
                EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_KEYING_EXPIRATION));

                uint64_t actual_keying_material_expiration = 0;
                EXPECT_SUCCESS(s2n_stuffer_read_uint64(&output, &actual_keying_material_expiration));
                EXPECT_EQUAL(actual_keying_material_expiration, expected_expiration_time);

                EXPECT_EQUAL(s2n_stuffer_data_available(&output), SIZE_OF_MAX_EARLY_DATA_SIZE);
                EXPECT_SUCCESS(s2n_stuffer_wipe(&output));
            };

            DEFER_CLEANUP(struct s2n_psk *chosen_psk = s2n_test_psk_new(conn), s2n_psk_free);
            EXPECT_NOT_NULL(chosen_psk);
            chosen_psk->type = S2N_PSK_TYPE_RESUMPTION;
            conn->psk_params.chosen_psk = chosen_psk;

            /* Existing expiration time */
            {
                uint64_t expected_expiration_time = ticket_issue_time + 1;
                chosen_psk->keying_material_expiration = expected_expiration_time;

                EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));
                EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, s2n_stuffer_data_available(&output)));
                EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_MAX_EARLY_DATA_SIZE));
                EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_KEYING_EXPIRATION));

                uint64_t actual_keying_material_expiration = 0;
                EXPECT_SUCCESS(s2n_stuffer_read_uint64(&output, &actual_keying_material_expiration));
                EXPECT_EQUAL(actual_keying_material_expiration, expected_expiration_time);

                EXPECT_EQUAL(s2n_stuffer_data_available(&output), SIZE_OF_MAX_EARLY_DATA_SIZE);
                EXPECT_SUCCESS(s2n_stuffer_wipe(&output));
            };

            /* Existing expiration time not supported by server settings */
            {
                uint64_t expected_expiration_time = ticket_issue_time + ONE_SEC_IN_NANOS;
                chosen_psk->keying_material_expiration = UINT64_MAX;

                EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));
                EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, s2n_stuffer_data_available(&output)));
                EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_MAX_EARLY_DATA_SIZE));
                EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_KEYING_EXPIRATION));

                uint64_t actual_keying_material_expiration = 0;
                EXPECT_SUCCESS(s2n_stuffer_read_uint64(&output, &actual_keying_material_expiration));
                EXPECT_EQUAL(actual_keying_material_expiration, expected_expiration_time);

                EXPECT_EQUAL(s2n_stuffer_data_available(&output), SIZE_OF_MAX_EARLY_DATA_SIZE);
                EXPECT_SUCCESS(s2n_stuffer_wipe(&output));
            };

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Test TLS1.3 serialization with early data */
        {
            const uint32_t test_max_early_data_size = UINT8_MAX;
            const uint8_t test_early_data_context[] = "context";
            const uint8_t test_app_protocol[] = "protocol";

            struct s2n_connection *conn = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(conn, test_early_data_context, sizeof(test_early_data_context)));
            EXPECT_MEMCPY_SUCCESS(conn->application_protocol, test_app_protocol, sizeof(test_app_protocol));
            conn->secure->cipher_suite = &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256;
            conn->actual_protocol_version = S2N_TLS13;

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
            EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));

            /* Write ticket without early data. Save size for comparison. */
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, 0));
            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));
            size_t basic_state_size = s2n_stuffer_data_available(&output);
            EXPECT_SUCCESS(s2n_stuffer_wipe(&output));

            /* Write ticket with early data. Skip the non-early-data information. */
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, test_max_early_data_size));
            EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, basic_state_size));
            EXPECT_SUCCESS(s2n_stuffer_rewind_read(&output, SIZE_OF_MAX_EARLY_DATA_SIZE));

            uint32_t max_early_data_size = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &max_early_data_size));
            EXPECT_EQUAL(max_early_data_size, test_max_early_data_size);

            uint8_t app_protocol_size = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &app_protocol_size));
            EXPECT_NOT_EQUAL(app_protocol_size, 0);
            EXPECT_EQUAL(app_protocol_size, strlen((const char *) test_app_protocol));

            uint8_t app_protocol[sizeof(test_app_protocol)] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, app_protocol, app_protocol_size));
            EXPECT_BYTEARRAY_EQUAL(app_protocol, test_app_protocol, sizeof(test_app_protocol));

            uint16_t early_data_context_size = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&output, &early_data_context_size));
            EXPECT_NOT_EQUAL(early_data_context_size, 0);
            EXPECT_EQUAL(early_data_context_size, sizeof(test_early_data_context));

            uint8_t early_data_context[sizeof(test_early_data_context)] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, early_data_context, early_data_context_size));
            EXPECT_BYTEARRAY_EQUAL(early_data_context, test_early_data_context, sizeof(test_early_data_context));

            EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0);
            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Erroneous secret size */
        {
            struct {
                uint32_t secret_size;
                bool success;
            } test_cases[] = {
                {
                        /* too small */
                        .secret_size = 0,
                        .success = false,
                },
                {
                        .secret_size = 1,
                        .success = true,
                },
                {
                        .secret_size = UINT8_MAX,
                        .success = true,
                },
                {
                        /* too large */
                        .secret_size = UINT8_MAX + 1,
                        .success = false,
                }
            };

            for (int i = 0; i < s2n_array_len(test_cases); i++) {
                DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free);
                EXPECT_NOT_NULL(conn);
                conn->actual_protocol_version = S2N_TLS13;

                DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
                EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

                conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
                EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));

                EXPECT_SUCCESS(s2n_realloc(&conn->tls13_ticket_fields.session_secret, test_cases[i].secret_size));
                if (test_cases[i].success) {
                    EXPECT_OK(s2n_tls13_serialize_resumption_state(conn, &output));
                } else {
                    EXPECT_ERROR_WITH_ERRNO(s2n_tls13_serialize_resumption_state(conn, &output), S2N_ERR_SAFETY);
                }
            }
        }
    };

    /* s2n_deserialize_resumption_state */
    {
        /* Deserialize ticket with incorrect format errors */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, faulty_format_ticket, sizeof(faulty_format_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, sizeof(faulty_format_ticket)));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);

            EXPECT_ERROR_WITH_ERRNO(s2n_deserialize_resumption_state(conn, NULL, &ticket_stuffer),
                    S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Deserialized ticket without EMS data errors */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls12_ticket, sizeof(tls12_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, sizeof(tls12_ticket) - S2N_TLS_SECRET_LEN));
            /* The secret needs to be written to the ticket separately as it has a fixed length */
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, test_master_secret.data, S2N_TLS_SECRET_LEN));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            /* Security policy must allow cipher suite hard coded into ticket */
            EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(conn, "test_all"));

            EXPECT_ERROR_WITH_ERRNO(s2n_deserialize_resumption_state(conn, NULL, &ticket_stuffer), S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Client processes hardcoded TLS1.2 ticket with EMS data correctly */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls12_ticket_with_ems, sizeof(tls12_ticket_with_ems)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, sizeof(tls12_ticket_with_ems) - S2N_TLS_SECRET_LEN - 1));
            /* The secret needs to be written to the ticket separately as it has a fixed length */
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, test_master_secret.data, S2N_TLS_SECRET_LEN));

            /* Write EMS data */
            EXPECT_SUCCESS(s2n_stuffer_write_uint8(&ticket_stuffer, 1));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            /* Security policy must allow cipher suite hard coded into ticket */
            EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(conn, "test_all"));

            EXPECT_OK(s2n_deserialize_resumption_state(conn, NULL, &ticket_stuffer));

            EXPECT_TRUE(conn->ems_negotiated);
            EXPECT_EQUAL(conn->resume_protocol_version, S2N_TLS12);
            EXPECT_EQUAL(conn->secure->cipher_suite, &s2n_rsa_with_aes_128_gcm_sha256);

            EXPECT_BYTEARRAY_EQUAL(test_master_secret.data, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Client processes TLS1.2 ticket with EMS data correctly */
        {
            struct s2n_connection *conn = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
            conn->actual_protocol_version = S2N_TLS12;
            /* Security policy must allow chosen cipher suite */
            EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(conn, "test_all"));

            struct s2n_blob blob = { 0 };
            struct s2n_stuffer stuffer = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&blob, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN));
            EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &blob));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&stuffer, test_master_secret.data, S2N_TLS_SECRET_LEN));
            conn->secure->cipher_suite = &s2n_rsa_with_aes_128_gcm_sha256;
            conn->ems_negotiated = true;

            uint8_t s_data[S2N_TLS12_STATE_SIZE_IN_BYTES] = { 0 };
            struct s2n_blob state_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
            struct s2n_stuffer output = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&output, &state_blob));

            EXPECT_SUCCESS(s2n_tls12_serialize_resumption_state(conn, &output));
            EXPECT_OK(s2n_deserialize_resumption_state(conn, NULL, &output));

            EXPECT_TRUE(conn->ems_negotiated);
            EXPECT_EQUAL(conn->actual_protocol_version, S2N_TLS12);
            EXPECT_EQUAL(conn->secure->cipher_suite, &s2n_rsa_with_aes_128_gcm_sha256);

            EXPECT_BYTEARRAY_EQUAL(test_master_secret.data, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Server processes TLS1.2 ticket with EMS data correctly */
        {
            struct s2n_connection *conn = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            conn->actual_protocol_version = S2N_TLS12;

            struct s2n_blob blob = { 0 };
            struct s2n_stuffer stuffer = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&blob, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN));
            EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &blob));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&stuffer, test_master_secret.data, S2N_TLS_SECRET_LEN));
            conn->secure->cipher_suite = &s2n_rsa_with_aes_128_gcm_sha256;
            conn->ems_negotiated = true;

            uint8_t s_data[S2N_TLS12_STATE_SIZE_IN_BYTES] = { 0 };
            struct s2n_blob state_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
            struct s2n_stuffer output = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&output, &state_blob));

            EXPECT_SUCCESS(s2n_tls12_serialize_resumption_state(conn, &output));

            /* EMS state in current session matches EMS state in previous session */
            conn->ems_negotiated = true;
            EXPECT_OK(s2n_deserialize_resumption_state(conn, NULL, &output));
            EXPECT_TRUE(conn->ems_negotiated);

            /**
             *= https://www.rfc-editor.org/rfc/rfc7627#section-5.3
             *= type=test
             *# If the original session used the "extended_master_secret"
             *# extension but the new ClientHello does not contain it, the server
             *# MUST abort the abbreviated handshake.
             **/
            conn->ems_negotiated = false;
            EXPECT_SUCCESS(s2n_stuffer_reread(&output));
            EXPECT_ERROR_WITH_ERRNO(s2n_deserialize_resumption_state(conn, NULL, &output),
                    S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
            EXPECT_TRUE(conn->ems_negotiated);

            /**
             *= https://www.rfc-editor.org/rfc/rfc7627#section-5.3
             *= type=test
             *# If the original session did not use the "extended_master_secret"
             *# extension but the new ClientHello contains the extension, then the
             *# server MUST NOT perform the abbreviated handshake.  Instead, it
             *# SHOULD continue with a full handshake (as described in
             *# Section 5.2) to negotiate a new session.
             **/
            EXPECT_SUCCESS(s2n_stuffer_wipe_n(&output, 1));
            EXPECT_SUCCESS(s2n_stuffer_write_uint8(&output, 0));
            conn->ems_negotiated = true;
            EXPECT_SUCCESS(s2n_stuffer_reread(&output));
            EXPECT_ERROR_WITH_ERRNO(s2n_deserialize_resumption_state(conn, NULL, &output),
                    S2N_ERR_INVALID_SERIALIZED_SESSION_STATE);
            EXPECT_FALSE(conn->ems_negotiated);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Deserialized ticket sets correct PSK values for session resumption in TLS1.3 */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls13_ticket, sizeof(tls13_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, sizeof(tls13_ticket)));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            const uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer));

            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);

            EXPECT_EQUAL(psk->type, S2N_PSK_TYPE_RESUMPTION);
            EXPECT_BYTEARRAY_EQUAL(psk->identity.data, client_ticket, sizeof(client_ticket));

            EXPECT_EQUAL(psk->secret.size, SECRET_LEN);
            uint8_t secret[] = { SECRET };
            EXPECT_BYTEARRAY_EQUAL(psk->secret.data, secret, sizeof(secret));

            EXPECT_EQUAL(psk->hmac_alg, S2N_HMAC_SHA256);

            EXPECT_EQUAL(psk->ticket_age_add, TICKET_AGE_ADD);
            EXPECT_EQUAL(psk->ticket_issue_time, ticket_issue_time);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Deserialized TLS1.3 server ticket sets correct keying material value */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls13_server_ticket, sizeof(tls13_server_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, ticket_blob.size));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            const uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer));

            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);

            EXPECT_EQUAL(psk->ticket_issue_time, ticket_issue_time);
            EXPECT_EQUAL(psk->keying_material_expiration, keying_material_expiration);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Deserializing TLS1.3 server ticket fails for expired keying material */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls13_server_ticket, sizeof(tls13_server_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, ticket_blob.size));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            uint64_t current_time = keying_material_expiration;
            EXPECT_OK(s2n_config_mock_wall_clock(config, &current_time));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            const uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            EXPECT_ERROR_WITH_ERRNO(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer),
                    S2N_ERR_KEYING_MATERIAL_EXPIRED);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Deserialized ticket sets correct PSK values for early data */
        {
            const uint8_t expected_app_protocol[] = { APP_PROTOCOL };
            const uint8_t expected_context[] = { EARLY_DATA_CONTEXT };

            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls13_ticket_with_early_data, sizeof(tls13_ticket_with_early_data)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, ticket_blob.size));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            const uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer));

            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);

            EXPECT_EQUAL(psk->early_data_config.protocol_version, S2N_TLS13);
            EXPECT_EQUAL(psk->early_data_config.max_early_data_size, NONEMPTY_EARLY_DATA_SIZE);
            EXPECT_EQUAL(psk->early_data_config.application_protocol.size, APP_PROTOCOL_LEN);
            EXPECT_BYTEARRAY_EQUAL(psk->early_data_config.application_protocol.data, expected_app_protocol, APP_PROTOCOL_LEN);
            EXPECT_EQUAL(psk->early_data_config.context.size, EARLY_DATA_CONTEXT_LEN);
            EXPECT_BYTEARRAY_EQUAL(psk->early_data_config.context.data, expected_context, EARLY_DATA_CONTEXT_LEN);
            EXPECT_EQUAL(psk->early_data_config.cipher_suite, &s2n_tls13_aes_128_gcm_sha256);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Deserializing state ignores extra data.
         * This will make it possible to easily add new fields in the future, without needing
         * to worry about versioning. */
        {
            uint8_t extra_data[] = "more ticket data, maybe from the future";

            DEFER_CLEANUP(struct s2n_stuffer ticket_stuffer = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&ticket_stuffer, 0));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, tls13_ticket_with_early_data,
                    sizeof(tls13_ticket_with_early_data)));
            /* Add some unexpected data */
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, extra_data, sizeof(extra_data)));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            const uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer));
            EXPECT_EQUAL(conn->psk_params.psk_list.len, 1);
            EXPECT_EQUAL(s2n_stuffer_data_available(&ticket_stuffer), sizeof(extra_data));

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Any existing psks are removed when creating a new resumption psk */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls13_ticket, sizeof(tls13_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, sizeof(tls13_ticket)));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            /* Add existing resumption psk */
            const uint8_t resumption_data[] = "resumption data";
            DEFER_CLEANUP(struct s2n_psk resumption_psk = { 0 }, s2n_psk_wipe);
            EXPECT_OK(s2n_psk_init(&resumption_psk, S2N_PSK_TYPE_RESUMPTION));
            EXPECT_SUCCESS(s2n_psk_set_identity(&resumption_psk, resumption_data, sizeof(resumption_data)));
            EXPECT_SUCCESS(s2n_psk_set_secret(&resumption_psk, resumption_data, sizeof(resumption_data)));
            EXPECT_SUCCESS(s2n_connection_append_psk(conn, &resumption_psk));

            EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer));

            EXPECT_EQUAL(conn->psk_params.psk_list.len, 1);
            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);

            EXPECT_EQUAL(psk->type, S2N_PSK_TYPE_RESUMPTION);
            EXPECT_BYTEARRAY_EQUAL(psk->identity.data, client_ticket, sizeof(client_ticket));

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Fails if external PSKs already set */
        {
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, tls13_ticket, sizeof(tls13_ticket)));
            struct s2n_stuffer ticket_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_init(&ticket_stuffer, &ticket_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&ticket_stuffer, sizeof(tls13_ticket)));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Initialize client ticket */
            uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            /* Add existing external psk */
            const uint8_t external_data[] = "external data";
            DEFER_CLEANUP(struct s2n_psk *external_psk = s2n_external_psk_new(), s2n_psk_free);
            EXPECT_SUCCESS(s2n_psk_set_identity(external_psk, external_data, sizeof(external_data)));
            EXPECT_SUCCESS(s2n_psk_set_secret(external_psk, external_data, sizeof(external_data)));
            EXPECT_SUCCESS(s2n_connection_append_psk(conn, external_psk));

            EXPECT_ERROR_WITH_ERRNO(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &ticket_stuffer), S2N_ERR_PSK_MODE);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Functional test: Both TLS1.3 client and server can deserialize what they serialize */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));

            for (s2n_mode mode = S2N_SERVER; mode <= S2N_CLIENT; mode++) {
                struct s2n_connection *conn = s2n_connection_new(mode);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

                conn->actual_protocol_version = S2N_TLS13;
                conn->secure->cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
                DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
                EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));

                conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = TICKET_AGE_ADD };
                EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));

                /* Initialize client ticket */
                uint8_t client_ticket[] = { CLIENT_TICKET };
                EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
                EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

                EXPECT_OK(s2n_serialize_resumption_state(conn, &stuffer));
                EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &stuffer));

                /* Check PSK values are correct */
                struct s2n_psk *psk = NULL;
                EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
                EXPECT_NOT_NULL(psk);

                EXPECT_EQUAL(psk->type, S2N_PSK_TYPE_RESUMPTION);
                EXPECT_BYTEARRAY_EQUAL(psk->identity.data, client_ticket, sizeof(client_ticket));

                EXPECT_EQUAL(psk->secret.size, test_session_secret.size);
                EXPECT_BYTEARRAY_EQUAL(psk->secret.data, test_session_secret.data, test_session_secret.size);

                EXPECT_EQUAL(psk->hmac_alg, conn->secure->cipher_suite->prf_alg);

                EXPECT_EQUAL(psk->ticket_age_add, TICKET_AGE_ADD);
                EXPECT_EQUAL(psk->ticket_issue_time, ticket_issue_time);

                EXPECT_SUCCESS(s2n_connection_free(conn));
            }

            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Functional test: The TLS1.3 client can deserialize what it serializes with early data */
        {
            const uint32_t test_max_early_data_size = 100;
            const uint8_t test_early_data_context[] = "test context";
            const uint8_t test_app_protocol[] = "test protocol";
            const uint8_t test_app_protocol_len = strlen((const char *) test_app_protocol);

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));

            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, test_max_early_data_size));
            EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(conn, test_early_data_context, sizeof(test_early_data_context)));
            EXPECT_MEMCPY_SUCCESS(conn->application_protocol, test_app_protocol, sizeof(test_app_protocol));
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_256_gcm_sha384;

            DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));

            /* Initialize client ticket */
            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = TICKET_AGE_ADD };
            EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));
            uint8_t client_ticket[] = { CLIENT_TICKET };
            EXPECT_SUCCESS(s2n_realloc(&conn->client_ticket, sizeof(client_ticket)));
            EXPECT_MEMCPY_SUCCESS(conn->client_ticket.data, client_ticket, sizeof(client_ticket));

            EXPECT_OK(s2n_serialize_resumption_state(conn, &stuffer));
            EXPECT_OK(s2n_deserialize_resumption_state(conn, &conn->client_ticket, &stuffer));

            /* Check PSK values are correct */
            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);

            EXPECT_EQUAL(psk->early_data_config.protocol_version, S2N_TLS13);
            EXPECT_EQUAL(psk->early_data_config.max_early_data_size, test_max_early_data_size);
            EXPECT_EQUAL(psk->early_data_config.cipher_suite, &s2n_tls13_aes_256_gcm_sha384);
            EXPECT_EQUAL(psk->early_data_config.application_protocol.size, test_app_protocol_len);
            EXPECT_BYTEARRAY_EQUAL(psk->early_data_config.application_protocol.data, test_app_protocol, test_app_protocol_len);
            EXPECT_EQUAL(psk->early_data_config.context.size, sizeof(test_early_data_context));
            EXPECT_BYTEARRAY_EQUAL(psk->early_data_config.context.data, test_early_data_context, sizeof(test_early_data_context));

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Functional test: Both TLS1.2 client and server can deserialize what they serialize */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));

            for (s2n_mode mode = S2N_SERVER; mode <= S2N_CLIENT; mode++) {
                struct s2n_connection *conn = s2n_connection_new(mode);
                EXPECT_NOT_NULL(conn);
                conn->actual_protocol_version = S2N_TLS12;
                conn->secure->cipher_suite = &s2n_rsa_with_aes_128_gcm_sha256;
                /* Security policy must allow chosen cipher suite */
                EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(conn, "test_all"));

                uint8_t s_data[S2N_TLS12_STATE_SIZE_IN_BYTES] = { 0 };
                struct s2n_blob state_blob = { 0 };
                EXPECT_SUCCESS(s2n_blob_init(&state_blob, s_data, sizeof(s_data)));
                struct s2n_stuffer stuffer = { 0 };

                EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &state_blob));

                EXPECT_OK(s2n_serialize_resumption_state(conn, &stuffer));
                EXPECT_OK(s2n_deserialize_resumption_state(conn, NULL, &stuffer));

                EXPECT_SUCCESS(s2n_connection_free(conn));
            }

            EXPECT_SUCCESS(s2n_config_free(config));
        };
    };

    /* s2n_validate_ticket_age */
    {
        /* Ticket issue time is beyond MAX_ALLOWED_CLOCK_SKEW */
        {
            uint64_t current_time = SECONDS_TO_NANOS(0);
            uint64_t issue_time = SECONDS_TO_NANOS(MAX_ALLOWED_CLOCK_SKEW_SEC + 1);
            EXPECT_ERROR_WITH_ERRNO(s2n_validate_ticket_age(current_time, issue_time), S2N_ERR_INVALID_SESSION_TICKET);
        };

        /* Ticket issue time is within MAX_ALLOWED_CLOCK_SKEW
         * Distributed deployments with clock skew may see a ticket issue time in
         * the future.
         */
        {
            uint64_t current_time = SECONDS_TO_NANOS(0);
            EXPECT_OK(s2n_validate_ticket_age(current_time, SECONDS_TO_NANOS(MAX_ALLOWED_CLOCK_SKEW_SEC - 1)));
            EXPECT_OK(s2n_validate_ticket_age(current_time, SECONDS_TO_NANOS(MAX_ALLOWED_CLOCK_SKEW_SEC)));
        };

        /** Ticket age is longer than a week
         *= https://www.rfc-editor.org/rfc/rfc8446#section-4.6.1
         *= type=test
         *# Clients MUST NOT cache
         *# tickets for longer than 7 days, regardless of the ticket_lifetime,
         *# and MAY delete tickets earlier based on local policy.
         */
        {
            uint64_t current_time = SECONDS_TO_NANOS(ONE_WEEK_IN_SEC + 1);
            uint64_t issue_time = 0;
            EXPECT_ERROR_WITH_ERRNO(s2n_validate_ticket_age(current_time, issue_time), S2N_ERR_INVALID_SESSION_TICKET);
        };

        /* Ticket age is a exactly a week */
        {
            uint64_t current_time = SECONDS_TO_NANOS(ONE_WEEK_IN_SEC);
            uint64_t issue_time = 0;
            EXPECT_OK(s2n_validate_ticket_age(current_time, issue_time));
        };
    };

    /* s2n_resume_encrypt/decrypt_session_ticket */
    {
        /* Check error is thrown when no ticket key is available */
        {
            DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER),
                    s2n_connection_ptr_free);
            EXPECT_NOT_NULL(conn);
            EXPECT_ERROR_WITH_ERRNO(s2n_resume_encrypt_session_ticket(conn, NULL, &conn->client_ticket_to_decrypt),
                    S2N_ERR_NO_TICKET_ENCRYPT_DECRYPT_KEY);
        }

        /* Check error is thrown when stuffer is out of memory for the ticket */
        {
            DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
            EXPECT_NOT_NULL(config);

            DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER),
                    s2n_connection_ptr_free);
            EXPECT_NOT_NULL(conn);

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            struct s2n_stuffer output = { 0 };
            EXPECT_ERROR_WITH_ERRNO(s2n_resume_encrypt_session_ticket(conn, key, &output), S2N_ERR_STUFFER_IS_FULL);
        }

        /* Check encrypted data can be decrypted correctly for TLS12 */
        {
            struct s2n_connection *conn = NULL;
            struct s2n_config *config = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->actual_protocol_version = S2N_TLS12;
            conn->handshake.handshake_type = NEGOTIATED;

            struct s2n_blob secret = { 0 };
            struct s2n_stuffer secret_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&secret, conn->secrets.version.tls12.master_secret, S2N_TLS_SECRET_LEN));
            EXPECT_SUCCESS(s2n_stuffer_init(&secret_stuffer, &secret));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&secret_stuffer, test_master_secret.data, S2N_TLS_SECRET_LEN));
            conn->secure->cipher_suite = &s2n_ecdhe_ecdsa_with_aes_128_gcm_sha256;

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            EXPECT_OK(s2n_resume_encrypt_session_ticket(conn, key, &conn->client_ticket_to_decrypt));
            EXPECT_NOT_EQUAL(s2n_stuffer_data_available(&conn->client_ticket_to_decrypt), 0);

            /* Wiping the master secret to prove that the decryption function actually writes the master secret */
            memset(conn->secrets.version.tls12.master_secret, 0, test_master_secret.size);

            EXPECT_OK(s2n_resume_decrypt_session(conn, &conn->client_ticket_to_decrypt));
            EXPECT_EQUAL(s2n_stuffer_data_available(&conn->client_ticket_to_decrypt), 0);

            /* Check decryption was successful by comparing master key */
            EXPECT_BYTEARRAY_EQUAL(conn->secrets.version.tls12.master_secret, test_master_secret.data, test_master_secret.size);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Check session ticket can be decrypted with a small secret in TLS13 session resumption. */
        {
            struct s2n_connection *conn = NULL;
            struct s2n_config *config = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_128_gcm_sha256;

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));
            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
            EXPECT_SUCCESS(s2n_dup(&test_session_secret, &conn->tls13_ticket_fields.session_secret));

            /* This secret is smaller than the maximum secret length */
            EXPECT_TRUE(conn->tls13_ticket_fields.session_secret.size < S2N_TLS_SECRET_LEN);

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            EXPECT_OK(s2n_resume_encrypt_session_ticket(conn, key, &output));
            EXPECT_OK(s2n_resume_decrypt_session(conn, &output));

            EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0);

            /* Check decryption was successful */
            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);
            EXPECT_EQUAL(psk->hmac_alg, s2n_tls13_aes_128_gcm_sha256.prf_alg);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Check session ticket can be decrypted with the maximum size secret in TLS13 session resumption. */
        {
            struct s2n_connection *conn = NULL;
            struct s2n_config *config = NULL;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_128_gcm_sha256;

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));
            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
            EXPECT_SUCCESS(s2n_dup(&test_master_secret, &conn->tls13_ticket_fields.session_secret));

            /* This secret is equal to the maximum secret length */
            EXPECT_EQUAL(conn->tls13_ticket_fields.session_secret.size, S2N_TLS_SECRET_LEN);

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            EXPECT_OK(s2n_resume_encrypt_session_ticket(conn, key, &output));
            EXPECT_OK(s2n_resume_decrypt_session(conn, &output));

            EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0);

            /* Check decryption was successful */
            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);
            EXPECT_EQUAL(psk->hmac_alg, s2n_tls13_aes_128_gcm_sha256.prf_alg);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };

        /* Check error is thrown when wrong version number is read */
        {
            DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER),
                    s2n_connection_ptr_free);
            EXPECT_NOT_NULL(conn);
            DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
            EXPECT_NOT_NULL(config);

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->actual_protocol_version = S2N_TLS12;
            conn->handshake.handshake_type = NEGOTIATED;

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            EXPECT_OK(s2n_resume_encrypt_session_ticket(conn, key, &conn->client_ticket_to_decrypt));
            EXPECT_NOT_EQUAL(s2n_stuffer_data_available(&conn->client_ticket_to_decrypt), 0);

            /* Modify the version number of the ticket */
            uint8_t *version_num = conn->client_ticket_to_decrypt.blob.data;
            EXPECT_EQUAL(*version_num, S2N_PRE_ENCRYPTED_STATE_V1);
            *version_num = S2N_PRE_ENCRYPTED_STATE_V1 + 100;

            EXPECT_ERROR_WITH_ERRNO(s2n_resume_decrypt_session(conn, &conn->client_ticket_to_decrypt),
                    S2N_ERR_SAFETY);

            /* The correct version number should succeed */
            *version_num = S2N_PRE_ENCRYPTED_STATE_V1;
            EXPECT_SUCCESS(s2n_stuffer_reread(&conn->client_ticket_to_decrypt));
            EXPECT_OK(s2n_resume_decrypt_session(conn, &conn->client_ticket_to_decrypt));
        }

        /* Check error is thrown when info bytes used to generate the ticket key are incorrect */
        {
            DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER),
                    s2n_connection_ptr_free);
            EXPECT_NOT_NULL(conn);
            DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
            EXPECT_NOT_NULL(config);

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->actual_protocol_version = S2N_TLS12;
            conn->handshake.handshake_type = NEGOTIATED;

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            DEFER_CLEANUP(struct s2n_stuffer valid_ticket = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&valid_ticket, 0));
            EXPECT_OK(s2n_resume_encrypt_session_ticket(conn, key, &valid_ticket));
            uint32_t ticket_size = s2n_stuffer_data_available(&valid_ticket);

            /* Copy ticket so that we don't modify the original ticket */
            EXPECT_SUCCESS(s2n_stuffer_copy(&valid_ticket, &conn->client_ticket_to_decrypt,
                    ticket_size));

            /* We assert that everything up to the info bytes is as expected since this test checks
             * a failure condition. This will cause this test to fail earlier if we change the
             * serialization format in the future. */
            uint8_t version_number = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&conn->client_ticket_to_decrypt, &version_number));
            EXPECT_EQUAL(version_number, S2N_PRE_ENCRYPTED_STATE_V1);
            uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&conn->client_ticket_to_decrypt, key_name, sizeof(key_name)));
            EXPECT_BYTEARRAY_EQUAL(key_name, "2016.07.26.15\0\0", S2N_TICKET_KEY_NAME_LEN);
            uint8_t *info_ptr = s2n_stuffer_raw_read(&conn->client_ticket_to_decrypt, S2N_TICKET_INFO_SIZE);
            EXPECT_NOT_NULL(info_ptr);

            /* Zero out the info bytes on the ticket.*/
            memset(info_ptr, 0, S2N_TICKET_INFO_SIZE);
            EXPECT_SUCCESS(s2n_stuffer_reread(&conn->client_ticket_to_decrypt));

            EXPECT_ERROR_WITH_ERRNO(s2n_resume_decrypt_session(conn, &conn->client_ticket_to_decrypt),
                    S2N_ERR_DECRYPT);

            /* The correct info bytes should succeed */
            EXPECT_SUCCESS(s2n_stuffer_reread(&valid_ticket));
            EXPECT_OK(s2n_resume_decrypt_session(conn, &valid_ticket));
        }

        /* Check session ticket can never be encrypted with a zero-filled ticket key */
        {
            DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_SERVER), s2n_connection_ptr_free);
            EXPECT_NOT_NULL(conn);

            DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
            EXPECT_NOT_NULL(config);

            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Manually zero out key bytes */
            struct s2n_ticket_key *key = NULL;
            EXPECT_OK(s2n_array_get(config->ticket_keys, 0, (void **) &key));
            EXPECT_NOT_NULL(key);
            POSIX_CHECKED_MEMSET((uint8_t *) key->aes_key, 0, S2N_AES256_KEY_LEN);

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

            EXPECT_ERROR_WITH_ERRNO(s2n_resume_encrypt_session_ticket(conn, key, &output), S2N_ERR_KEY_CHECK);
        };

        /* Check session ticket is correct when using early data with TLS1.3. */
        {
            const uint8_t test_early_data_context[] = "context";
            const char test_app_proto[] = "https";

            /* Setting up session resumption encryption key */
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_OK(s2n_resumption_test_ticket_key_setup(config));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, 10));
            EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(conn, test_early_data_context, sizeof(test_early_data_context)));
            EXPECT_MEMCPY_SUCCESS(conn->application_protocol, test_app_proto, sizeof(test_app_proto));
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure->cipher_suite = &s2n_tls13_aes_128_gcm_sha256;

            DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));
            conn->tls13_ticket_fields = (struct s2n_ticket_fields){ .ticket_age_add = 1 };
            EXPECT_SUCCESS(s2n_dup(&test_master_secret, &conn->tls13_ticket_fields.session_secret));

            struct s2n_ticket_key *key = s2n_get_ticket_encrypt_decrypt_key(conn->config);
            EXPECT_NOT_NULL(key);

            EXPECT_OK(s2n_resume_encrypt_session_ticket(conn, key, &output));
            EXPECT_OK(s2n_resume_decrypt_session(conn, &output));

            EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0);

            /* Check decryption was successful */
            struct s2n_psk *psk = NULL;
            EXPECT_OK(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
            EXPECT_NOT_NULL(psk);
            EXPECT_EQUAL(psk->early_data_config.cipher_suite, &s2n_tls13_aes_128_gcm_sha256);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        };
    };

    /* s2n_config_set_initial_ticket_count */
    {
        struct s2n_connection *conn = NULL;
        struct s2n_config *config = NULL;
        uint8_t num_tickets = 1;

        EXPECT_NOT_NULL(config = s2n_config_new());
        EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
        EXPECT_EQUAL(conn->tickets_to_send, 0);
        EXPECT_FALSE(config->use_tickets);

        EXPECT_SUCCESS(s2n_config_set_initial_ticket_count(config, 0));
        EXPECT_TRUE(config->use_tickets);

        EXPECT_SUCCESS(s2n_config_set_initial_ticket_count(config, num_tickets));
        EXPECT_TRUE(config->use_tickets);

        EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
        EXPECT_EQUAL(conn->tickets_to_send, num_tickets);

        EXPECT_SUCCESS(s2n_config_free(config));
        EXPECT_SUCCESS(s2n_connection_free(conn));
    };

    /* s2n_connection_add_new_tickets_to_send */
    {
        /* New number of session tickets can be set */
        {
            struct s2n_connection *conn = NULL;
            uint8_t original_num_tickets = 1;
            uint8_t new_num_tickets = 10;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
            conn->tickets_to_send = original_num_tickets;

            EXPECT_SUCCESS(s2n_connection_add_new_tickets_to_send(conn, new_num_tickets));

            EXPECT_EQUAL(conn->tickets_to_send, original_num_tickets + new_num_tickets);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Overflow error is caught */
        {
            struct s2n_connection *conn = NULL;
            uint8_t new_num_tickets = 1;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
            conn->tickets_to_send = UINT16_MAX;

            EXPECT_FAILURE_WITH_ERRNO(s2n_connection_add_new_tickets_to_send(conn, new_num_tickets), S2N_ERR_INTEGER_OVERFLOW);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };

        /* Fails if keying material expired */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            conn->tickets_to_send = UINT16_MAX;

            DEFER_CLEANUP(struct s2n_psk *chosen_psk = s2n_test_psk_new(conn), s2n_psk_free);
            EXPECT_NOT_NULL(chosen_psk);
            chosen_psk->type = S2N_PSK_TYPE_RESUMPTION;
            chosen_psk->keying_material_expiration = 0;
            conn->psk_params.chosen_psk = chosen_psk;

            EXPECT_FAILURE_WITH_ERRNO(s2n_connection_add_new_tickets_to_send(conn, 1), S2N_ERR_KEYING_MATERIAL_EXPIRED);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        };
    };

    /* s2n_config_set_session_ticket_cb */
    {
        struct s2n_config *config = NULL;
        EXPECT_NOT_NULL(config = s2n_config_new());
        void *ctx = NULL;

        /* Safety check */
        {
            EXPECT_FAILURE_WITH_ERRNO(s2n_config_set_session_ticket_cb(NULL, s2n_test_session_ticket_callback, ctx), S2N_ERR_NULL);
        };

        EXPECT_NULL(config->session_ticket_cb);
        EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_callback, ctx));
        EXPECT_EQUAL(config->session_ticket_cb, s2n_test_session_ticket_callback);
        EXPECT_SUCCESS(s2n_config_free(config));
    };

    /* s2n_session_ticket_get_data_len */
    {
        /* Safety checks */
        {
            struct s2n_session_ticket session_ticket = { 0 };
            size_t data_len = 0;
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_data_len(NULL, &data_len), S2N_ERR_NULL);
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_data_len(&session_ticket, NULL), S2N_ERR_NULL);
        };

        /* Empty ticket */
        {
            struct s2n_session_ticket session_ticket = { 0 };
            size_t data_len = 0;
            EXPECT_SUCCESS(s2n_session_ticket_get_data_len(&session_ticket, &data_len));
            EXPECT_EQUAL(data_len, 0);
        };

        /* Valid ticket */
        {
            uint8_t ticket_data[] = "session ticket data";
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, ticket_data, sizeof(ticket_data)));
            struct s2n_session_ticket session_ticket = { .ticket_data = ticket_blob };

            size_t data_len = 0;
            EXPECT_SUCCESS(s2n_session_ticket_get_data_len(&session_ticket, &data_len));
            EXPECT_EQUAL(data_len, sizeof(ticket_data));
        };
    };

    /* s2n_session_ticket_get_data */
    {
        /* Safety checks */
        {
            struct s2n_session_ticket session_ticket = { 0 };
            size_t max_data_len = 0;
            uint8_t *data = NULL;
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_data(NULL, max_data_len, data), S2N_ERR_NULL);
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_data(&session_ticket, max_data_len, NULL), S2N_ERR_NULL);
        };

        /* Valid ticket */
        {
            uint8_t ticket_data[] = "session ticket data";
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, ticket_data, sizeof(ticket_data)));
            struct s2n_session_ticket session_ticket = { .ticket_data = ticket_blob };

            uint8_t data[sizeof(ticket_data)];
            size_t max_data_len = sizeof(data);
            EXPECT_SUCCESS(s2n_session_ticket_get_data(&session_ticket, max_data_len, data));
            EXPECT_BYTEARRAY_EQUAL(data, ticket_data, sizeof(ticket_data));
        };

        /* Ticket data is larger than customer buffer */
        {
            uint8_t ticket_data[] = "session ticket data";
            struct s2n_blob ticket_blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&ticket_blob, ticket_data, sizeof(ticket_data)));
            struct s2n_session_ticket session_ticket = { .ticket_data = ticket_blob };

            uint8_t data[sizeof(ticket_data) - 1];
            size_t max_data_len = sizeof(data);
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_data(&session_ticket, max_data_len, data),
                    S2N_ERR_SERIALIZED_SESSION_STATE_TOO_LONG);
        };
    };

    /* s2n_session_ticket_get_lifetime */
    {
        /* Safety checks */
        {
            struct s2n_session_ticket session_ticket = { 0 };
            uint32_t lifetime = 0;
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_lifetime(NULL, &lifetime), S2N_ERR_NULL);
            EXPECT_FAILURE_WITH_ERRNO(s2n_session_ticket_get_lifetime(&session_ticket, NULL), S2N_ERR_NULL);
        };

        /* Valid lifetime */
        {
            uint32_t lifetime = 100;
            struct s2n_session_ticket session_ticket = { .session_lifetime = lifetime };

            uint32_t ticket_lifetime = 0;
            EXPECT_SUCCESS(s2n_session_ticket_get_lifetime(&session_ticket, &ticket_lifetime));
            EXPECT_EQUAL(lifetime, ticket_lifetime);
        };
    };

    /* s2n_connection_set_server_keying_material_lifetime */
    {
        struct s2n_connection conn = { 0 };

        EXPECT_FAILURE_WITH_ERRNO(s2n_connection_set_server_keying_material_lifetime(NULL, 0), S2N_ERR_NULL);

        EXPECT_SUCCESS(s2n_connection_set_server_keying_material_lifetime(&conn, 1));
        EXPECT_EQUAL(conn.server_keying_material_lifetime, 1);

        EXPECT_SUCCESS(s2n_connection_set_server_keying_material_lifetime(&conn, 0));
        EXPECT_EQUAL(conn.server_keying_material_lifetime, 0);

        EXPECT_SUCCESS(s2n_connection_set_server_keying_material_lifetime(&conn, UINT32_MAX));
        EXPECT_EQUAL(conn.server_keying_material_lifetime, UINT32_MAX);
    };

    /* s2n_allowed_to_cache_connection */
    {
        struct s2n_connection *conn = NULL;
        EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
        struct s2n_config *config = NULL;
        EXPECT_NOT_NULL(config = s2n_config_new());
        EXPECT_SUCCESS(s2n_config_set_client_auth_type(config, S2N_CERT_AUTH_REQUIRED));

        /* Turn session caching on */
        config->use_session_cache = 1;
        EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

        /* Cannot cache connection if client auth is required */
        EXPECT_FALSE(s2n_allowed_to_cache_connection(conn));

        EXPECT_SUCCESS(s2n_config_set_client_auth_type(config, S2N_CERT_AUTH_NONE));
        EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

        /* Allowed to cache connection if client auth is not required */
        EXPECT_TRUE(s2n_allowed_to_cache_connection(conn));

        EXPECT_SUCCESS(s2n_connection_free(conn));
        EXPECT_SUCCESS(s2n_config_free(config));
    };

    /* Test s2n_connection_set_session */
    {
        uint8_t server_state[] = "encrypted state";

        DEFER_CLEANUP(struct s2n_config *config = s2n_config_new(), s2n_config_ptr_free);
        EXPECT_NOT_NULL(config);
        EXPECT_SUCCESS(s2n_config_set_wall_clock(config, mock_time, NULL));
        EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "test_all"));

        /* Invalid TLS1.2 tickets should not modify the connection.
         *
         * This basically tests that deserialization errors aren't fatal / unrecoverable.
         */
        {
            DEFER_CLEANUP(struct s2n_stuffer ticket_stuffer = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&ticket_stuffer, 0));
            EXPECT_SUCCESS(s2n_stuffer_write_uint8(&ticket_stuffer, S2N_STATE_WITH_SESSION_TICKET));
            EXPECT_SUCCESS(s2n_stuffer_write_uint16(&ticket_stuffer, sizeof(server_state)));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, server_state, sizeof(server_state)));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer,
                    tls12_ticket_with_ems, sizeof(tls12_ticket_with_ems)));

            size_t ticket_size = s2n_stuffer_data_available(&ticket_stuffer);
            uint8_t *ticket_bytes = s2n_stuffer_raw_read(&ticket_stuffer, ticket_size);
            EXPECT_NOT_NULL(ticket_bytes);

            /* Test that deserialize modifies the connection in limited ways.
             *
             * No mechanism exists to do more than a shallow comparison of two connections.
             * To prove that a shallow comparison is sufficient, we need to prove
             * that s2n_deserialize_resumption_state does not modify the memory
             * associated with pointers on the connection. To prove that, we can
             * test that s2n_deserialize_resumption_state can successfully operate
             * on an s2n_connection with a limited number of its pointers initialized.
             */
            {
                struct s2n_connection empty_conn = { 0 };
                struct s2n_crypto_parameters crypto_params = { .cipher_suite = &s2n_null_cipher_suite };
                empty_conn.secure = &crypto_params;
                empty_conn.mode = S2N_CLIENT;
                /* We can safely assume that a connection doesn't modify its config */
                empty_conn.config = config;
                EXPECT_SUCCESS(s2n_connection_set_session(&empty_conn, ticket_bytes, ticket_size));
                EXPECT_SUCCESS(s2n_free(&empty_conn.client_ticket));
            };

            /* Test that deserialize does not modify the connection on parsing failure,
             * given the constraints proven above.
             */
            {
                DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
                        s2n_connection_ptr_free);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

                /* Trigger the deserialization failure as late as possible.
                 * The last byte is optional, so drop the last two bytes.
                 */
                size_t bad_ticket_size = ticket_size - 2;

                /* Test the connection is not modified by a failed deserialize */
                uint8_t saved_conn[sizeof(struct s2n_connection)] = { 0 };
                EXPECT_MEMCPY_SUCCESS(saved_conn, conn, sizeof(struct s2n_connection));
                uint8_t saved_secure[sizeof(struct s2n_crypto_parameters)] = { 0 };
                EXPECT_MEMCPY_SUCCESS(saved_secure, conn->secure, sizeof(struct s2n_crypto_parameters));
                EXPECT_FAILURE_WITH_ERRNO(s2n_connection_set_session(conn, ticket_bytes, bad_ticket_size),
                        S2N_ERR_STUFFER_OUT_OF_DATA);
                EXPECT_BYTEARRAY_EQUAL(saved_conn, conn, sizeof(struct s2n_connection));
                EXPECT_BYTEARRAY_EQUAL(saved_secure, conn->secure, sizeof(struct s2n_crypto_parameters));

                /* No valid ticket */
                EXPECT_EQUAL(s2n_connection_get_session_length(conn), 0);
            };

            /* Test that deserialize does not modify the connection on a cipher selection failure,
             * given the constraints proven above.
             */
            {
                DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
                        s2n_connection_ptr_free);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

                /* Trigger the deserialization failure when checking the validity
                 * of the chosen cipher, not when parsing the ticket.
                 */
                EXPECT_SUCCESS(s2n_connection_set_cipher_preferences(conn, "null"));

                /* Test the connection is not modified by a failed deserialize */
                uint8_t saved_conn[sizeof(struct s2n_connection)] = { 0 };
                EXPECT_MEMCPY_SUCCESS(saved_conn, conn, sizeof(struct s2n_connection));
                uint8_t saved_secure[sizeof(struct s2n_crypto_parameters)] = { 0 };
                EXPECT_MEMCPY_SUCCESS(saved_secure, conn->secure, sizeof(struct s2n_crypto_parameters));
                EXPECT_FAILURE_WITH_ERRNO(s2n_connection_set_session(conn, ticket_bytes, ticket_size),
                        S2N_ERR_CIPHER_NOT_SUPPORTED);
                EXPECT_BYTEARRAY_EQUAL(saved_conn, conn, sizeof(struct s2n_connection));
                EXPECT_BYTEARRAY_EQUAL(saved_secure, conn->secure, sizeof(struct s2n_crypto_parameters));

                /* No valid ticket */
                EXPECT_EQUAL(s2n_connection_get_session_length(conn), 0);
            };
        };

        /* Invalid TLS1.3 tickets should not modify the connection.
         *
         * This basically tests that deserialization errors aren't fatal / unrecoverable.
         */
        {
            DEFER_CLEANUP(struct s2n_stuffer ticket_stuffer = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&ticket_stuffer, 0));
            EXPECT_SUCCESS(s2n_stuffer_write_uint8(&ticket_stuffer, S2N_STATE_WITH_SESSION_TICKET));
            EXPECT_SUCCESS(s2n_stuffer_write_uint16(&ticket_stuffer, sizeof(server_state)));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, server_state, sizeof(server_state)));
            EXPECT_SUCCESS(s2n_stuffer_write_bytes(&ticket_stuffer, tls13_ticket, sizeof(tls13_ticket)));

            size_t ticket_size = s2n_stuffer_data_available(&ticket_stuffer);
            uint8_t *ticket_bytes = s2n_stuffer_raw_read(&ticket_stuffer, ticket_size);
            EXPECT_NOT_NULL(ticket_bytes);

            /* Test that the connection is only shallowly modified by a successful deserialize.
             *
             * No mechanism exists to do more than a shallow comparison of two connections.
             * To prove that a shallow comparison is sufficient, we need to prove
             * that s2n_deserialize_resumption_state does not modify the memory
             * associated with pointers on the connection. To prove that, we can
             * test that s2n_deserialize_resumption_state can successfully operate
             * on an s2n_connection with none of its pointers initialized.
             */
            {
                struct s2n_connection empty_conn = { 0 };
                empty_conn.mode = S2N_CLIENT;
                /* We can safely assume that a connection doesn't modify its config */
                empty_conn.config = config;
                EXPECT_SUCCESS(s2n_connection_set_session(&empty_conn, ticket_bytes, ticket_size));
                EXPECT_OK(s2n_psk_parameters_wipe(&empty_conn.psk_params));
            };

            /* Test that deserialize does not modify the connection on failure,
             * given the constraints proven above.
             */
            {
                DEFER_CLEANUP(struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT),
                        s2n_connection_ptr_free);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

                /* Trigger the deserialization failure as late as possible in parsing.
                 * Drop the last byte we expect.
                 */
                size_t bad_ticket_size = ticket_size - 1;

                /* Test the connection is not modified by a failed deserialize */
                uint8_t saved[sizeof(struct s2n_connection)] = { 0 };
                EXPECT_MEMCPY_SUCCESS(saved, conn, sizeof(struct s2n_connection));
                EXPECT_FAILURE_WITH_ERRNO(s2n_connection_set_session(conn, ticket_bytes, bad_ticket_size),
                        S2N_ERR_STUFFER_OUT_OF_DATA);
                EXPECT_BYTEARRAY_EQUAL(saved, conn, sizeof(struct s2n_connection));

                /* No valid ticket */
                EXPECT_EQUAL(s2n_connection_get_session_length(conn), 0);
            };
        };
    };

    END_TEST();
}
