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

#include "testlib/s2n_testlib.h"

#include "tls/s2n_tls.h"
/* To test static functions */
#include "tls/s2n_server_new_session_ticket.c"

#define TEST_TICKET_AGE_ADD  0x01, 0x02, 0x03, 0x04
#define TEST_LIFETIME        0x00, 0x01, 0x01, 0x01
#define TEST_TICKET          0x01, 0xFF, 0x23

#define ONE_HOUR_IN_NANOS   3600000000000
#define TWO_HOURS_IN_NANOS  ONE_HOUR_IN_NANOS * 2

#define TICKET_AGE_ADD_MARKER sizeof(uint8_t)  + /* message id  */ \
                              SIZEOF_UINT24    + /* message len */ \
                              sizeof(uint32_t)   /* ticket lifetime */
#define RECORD_LEN_MARKER     sizeof(uint8_t) +  /* message type */ \
                              sizeof(uint16_t)   /* protocol version */

#define MAX_TEST_SESSION_SIZE 300

size_t cb_session_data_len = 0;
uint8_t cb_session_data[MAX_TEST_SESSION_SIZE] = { 0 };
uint32_t cb_session_lifetime = 0;
static int s2n_test_session_ticket_cb(struct s2n_connection *conn, void *ctx, struct s2n_session_ticket *ticket)
{
    POSIX_ENSURE_REF(conn);
    POSIX_ENSURE_REF(ticket);

    EXPECT_SUCCESS(s2n_session_ticket_get_data_len(ticket, &cb_session_data_len));
    EXPECT_SUCCESS(s2n_session_ticket_get_data(ticket, cb_session_data_len, cb_session_data));
    EXPECT_SUCCESS(s2n_session_ticket_get_lifetime(ticket, &cb_session_lifetime));

    return S2N_SUCCESS;
}

static int s2n_setup_test_ticket_key(struct s2n_config *config)
{
    POSIX_ENSURE_REF(config);

    /**
     *= https://tools.ietf.org/rfc/rfc5869#appendix-A.1
     *# PRK  = 0x077709362c2e32df0ddc3f0dc47bba63
     *#        90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets)
     **/
    S2N_BLOB_FROM_HEX(ticket_key,
    "077709362c2e32df0ddc3f0dc47bba63"
    "90b6c73bb50f9c3122ec844ad7c2b3e5");

    /* Set up encryption key */
    uint64_t current_time;
    uint8_t ticket_key_name[16] = "2016.07.26.15\0";
    EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
    EXPECT_SUCCESS(config->wall_clock(config->sys_clock_ctx, &current_time));
    EXPECT_SUCCESS(s2n_config_add_ticket_crypto_key(config, ticket_key_name, strlen((char *)ticket_key_name),
                    ticket_key.data, ticket_key.size, current_time/ONE_SEC_IN_NANOS));

    return S2N_SUCCESS;
}

static int s2n_setup_test_resumption_secret(struct s2n_connection *conn)
{
    POSIX_ENSURE_REF(conn);
    /**
     *= https://tools.ietf.org/rfc/rfc8448#section-3
     *# PRK (32 octets):  7d f2 35 f2 03 1d 2a 05 12 87 d0 2b 02 41 b0 bf
     *# da f8 6c c8 56 23 1f 2d 5a ba 46 c4 34 ec 19 6c
     **/
    S2N_BLOB_FROM_HEX(test_resumption_secret,
    "7d f2 35 f2 03 1d 2a 05 12 87 d0 2b 02 41 b0 bf \
         da f8 6c c8 56 23 1f 2d 5a ba 46 c4 34 ec 19 6c");

    /* Set up resumption secret */
    struct s2n_blob secret = { 0 };
    struct s2n_stuffer secret_stuffer = { 0 };
    EXPECT_SUCCESS(s2n_blob_init(&secret, conn->resumption_master_secret, S2N_TLS_SECRET_LEN));
    EXPECT_SUCCESS(s2n_stuffer_init(&secret_stuffer, &secret));
    EXPECT_SUCCESS(s2n_stuffer_write_bytes(&secret_stuffer, test_resumption_secret.data, test_resumption_secret.size));

    return S2N_SUCCESS;
}

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

    /* s2n_tls13_server_nst_write */
    {
        /* Check session ticket message is correctly written. */
        {
            struct s2n_config *config;
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());

            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            conn->actual_protocol_version = S2N_TLS13;
            conn->secure.cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
            uint16_t test_tickets_sent = 10;
            conn->tickets_sent = test_tickets_sent;

            /* Set up output stuffer */
            struct s2n_stuffer output = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));
            
            EXPECT_OK(s2n_tls13_server_nst_write(conn, &output));

            uint8_t message_type = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &message_type));
            EXPECT_EQUAL(TLS_SERVER_NEW_SESSION_TICKET, message_type);

            uint32_t message_size = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint24(&output, &message_size));
            EXPECT_EQUAL(message_size, s2n_stuffer_data_available(&output));

            uint32_t ticket_lifetime = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &ticket_lifetime));
            uint32_t key_lifetime_in_secs = S2N_TICKET_DECRYPT_KEY_LIFETIME_IN_NANOS / ONE_SEC_IN_NANOS;
            EXPECT_EQUAL(key_lifetime_in_secs, ticket_lifetime);

            /* Skipping random data */
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, sizeof(uint32_t)));

            uint8_t ticket_nonce_len = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint8(&output, &ticket_nonce_len));
            EXPECT_EQUAL(sizeof(uint16_t), ticket_nonce_len);

            uint8_t ticket_nonce[sizeof(uint16_t)] = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_read_bytes(&output, ticket_nonce, ticket_nonce_len));

            uint8_t tickets_sent_array[sizeof(uint16_t)] = { 0 };
            struct s2n_blob blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&blob, tickets_sent_array, sizeof(uint16_t)));
            EXPECT_OK(s2n_generate_ticket_nonce(test_tickets_sent, &blob));
            EXPECT_BYTEARRAY_EQUAL(ticket_nonce, blob.data, ticket_nonce_len);

            uint16_t session_ticket_len = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&output, &session_ticket_len));
            uint8_t size_of_extensions_size = sizeof(uint16_t);
            EXPECT_EQUAL(session_ticket_len, (s2n_stuffer_data_available(&output) - size_of_extensions_size));

            /* Skipping encrypted ticket data */
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, session_ticket_len));

            uint16_t extensions_len = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&output, &extensions_len));
            EXPECT_EQUAL(extensions_len, 0);

            EXPECT_EQUAL(s2n_stuffer_data_available(&output), 0);

            EXPECT_TRUE(conn->tickets_sent == test_tickets_sent + 1);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&output));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* tickets_sent overflow */
        {
            struct s2n_config *config;
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());
            
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            conn->actual_protocol_version = S2N_TLS13;
            conn->secure.cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
            conn->tickets_sent = UINT16_MAX;

            /* Set up output stuffer */
            struct s2n_stuffer output = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

            EXPECT_ERROR_WITH_ERRNO(s2n_tls13_server_nst_write(conn, &output), S2N_ERR_INTEGER_OVERFLOW);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&output));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /** ticket_age_add values do not repeat after sending multiple new session tickets
         *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
         *= type=test
         *#  The server MUST generate a fresh value
         *#  for each ticket it sends.
         **/
        {
            struct s2n_config *config;
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());

            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            conn->actual_protocol_version = S2N_TLS13;
            conn->secure.cipher_suite = &s2n_tls13_aes_256_gcm_sha384;

            /* Set up output stuffer */
            struct s2n_stuffer output = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));

            EXPECT_OK(s2n_tls13_server_nst_write(conn, &output));

            uint32_t original_ticket_age_add = 0;
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, TICKET_AGE_ADD_MARKER));
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &original_ticket_age_add));

            EXPECT_SUCCESS(s2n_stuffer_wipe(&output));
            EXPECT_OK(s2n_tls13_server_nst_write(conn, &output));

            uint32_t new_ticket_age_add = 0;
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output, TICKET_AGE_ADD_MARKER));
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &new_ticket_age_add));

            EXPECT_NOT_EQUAL(original_ticket_age_add, new_ticket_age_add);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&output));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Test that the message written by the server includes extensions.
         * Specifically, check for the early_data_indication extension. */
        {
            const uint32_t expected_max_early_data_size = 10;

            /* Calculate extension list offset. Extension list should be last. */
            const uint32_t extension_list_offset = sizeof(uint32_t) /* max_early_data_size */
                    + sizeof(uint16_t) /* size of extension */
                    + sizeof(uint16_t) /* type of extension */;

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(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, expected_max_early_data_size));
            conn->actual_protocol_version = S2N_TLS13;
            conn->secure.cipher_suite = &s2n_tls13_aes_256_gcm_sha384;

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

            EXPECT_OK(s2n_tls13_server_nst_write(conn, &output));
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&output,
                    s2n_stuffer_data_available(&output) - extension_list_offset));

            uint16_t extension_type = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&output, &extension_type));
            EXPECT_EQUAL(extension_type, TLS_EXTENSION_EARLY_DATA);

            uint16_t extension_size = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&output, &extension_size));
            EXPECT_EQUAL(extension_size, sizeof(uint32_t));

            uint32_t actual_max_early_data_size = 0;
            EXPECT_SUCCESS(s2n_stuffer_read_uint32(&output, &actual_max_early_data_size));
            EXPECT_EQUAL(actual_max_early_data_size, expected_max_early_data_size);

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&output));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Can't write ticket larger than allowed size of a PSK identity */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));

            struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(server_conn);
            EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config));
            server_conn->actual_protocol_version = S2N_TLS13;
            server_conn->secure.cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(server_conn, 10));

            /* Set context to be UINT16_MAX */
            uint8_t early_data_context[UINT16_MAX] = { 0 };
            EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(server_conn,
                    early_data_context, sizeof(early_data_context)));

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

            EXPECT_ERROR_WITH_ERRNO(s2n_tls13_server_nst_write(server_conn, &stuffer), S2N_ERR_SIZE_MISMATCH);

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

    /* s2n_generate_ticket_lifetime */
    {
        uint32_t min_lifetime = 0;
        struct s2n_connection *conn;
        EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));

        /* Test: Decrypt key has shortest lifetime */
        conn->config->decrypt_key_lifetime_in_nanos = ONE_HOUR_IN_NANOS;
        conn->config->session_state_lifetime_in_nanos = TWO_HOURS_IN_NANOS;

        EXPECT_OK(s2n_generate_ticket_lifetime(conn, &min_lifetime));
        EXPECT_EQUAL(min_lifetime, conn->config->decrypt_key_lifetime_in_nanos / ONE_SEC_IN_NANOS);

        /* Test: Session state has shortest lifetime */
        conn->config->decrypt_key_lifetime_in_nanos = TWO_HOURS_IN_NANOS;
        conn->config->session_state_lifetime_in_nanos = ONE_HOUR_IN_NANOS;

        EXPECT_OK(s2n_generate_ticket_lifetime(conn, &min_lifetime));
        EXPECT_EQUAL(min_lifetime, conn->config->session_state_lifetime_in_nanos / ONE_SEC_IN_NANOS);        

        /** Test: Both session state and decrypt key have longer lifetimes than a week
         *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
         *= type=test
         *# Servers MUST NOT use any value greater than
         *# 604800 seconds (7 days).
         **/
        /* Note: We turn these integer literals into uint64_t values because otherwise
         * they will be interpreted as uint32_t values and an faulty integer overflow error
         * will be thrown. */
        uint64_t one_week_in_sec = ONE_WEEK_IN_SEC;
        uint64_t one_sec_in_nanos = ONE_SEC_IN_NANOS;
        uint64_t one_week_in_nanos = one_week_in_sec * one_sec_in_nanos;
        conn->config->decrypt_key_lifetime_in_nanos = one_week_in_nanos + 1;
        conn->config->session_state_lifetime_in_nanos = one_week_in_nanos + 1;

        EXPECT_OK(s2n_generate_ticket_lifetime(conn, &min_lifetime));
        EXPECT_EQUAL(min_lifetime, ONE_WEEK_IN_SEC);

        EXPECT_SUCCESS(s2n_connection_free(conn));
    }

    /* s2n_generate_ticket_nonce */
    {
        struct {
            uint16_t value;
            uint8_t expected_output[2];
        } test_cases[] = {
            { .value = 0, .expected_output = { 0 , 0 } },
            { .value = 1, .expected_output = { 0 , 1 } },
            { .value = 20, .expected_output = { 0 , 20 } },
            { .value = UINT8_MAX, .expected_output = { 0 , UINT8_MAX } },
            { .value = UINT8_MAX + 1, .expected_output = { 1 , 0 } },
            { .value = UINT16_MAX, .expected_output = { UINT8_MAX, UINT8_MAX } },
            { .value = UINT16_MAX - 1, .expected_output = { UINT8_MAX, UINT8_MAX - 1 } },
        };

        for (size_t i = 0; i < s2n_array_len(test_cases); i++) {
            uint8_t data[sizeof(uint16_t)] = { 0 };
            struct s2n_blob blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&blob, data, sizeof(data)));

            EXPECT_OK(s2n_generate_ticket_nonce(test_cases[i].value, &blob));

            EXPECT_EQUAL(test_cases[i].expected_output[0], data[0]);
            EXPECT_EQUAL(test_cases[i].expected_output[1], data[1]);
        }
    }

    /* s2n_generate_ticket_age_add */
    {
        struct {
            uint8_t value[4];
            uint32_t expected_output;
        } test_cases[] = {
            { .value = { 0, 0, 0, 0 }, .expected_output = 0 },
            { .value = { 0, 0, 0, 1 }, .expected_output = 1 },
            { .value = { 0, 0, 0, 20 }, .expected_output = 20 },
            { .value = { 0, 0, 1, 0 }, .expected_output = UINT8_MAX + 1 },
            { .value = { 0, 1, 0, 0 }, .expected_output = UINT16_MAX + 1 },
            { .value = { 0, 0, UINT8_MAX, UINT8_MAX }, .expected_output = UINT16_MAX },
            { .value = { UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX }, .expected_output = UINT32_MAX },
            { .value = { UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX - 1}, .expected_output = UINT32_MAX - 1 },
        };

        for (size_t i = 0; i < s2n_array_len(test_cases); i++) {
            uint32_t output = 0;
            struct s2n_blob blob = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&blob, test_cases[i].value, sizeof(test_cases[i].value)));
            EXPECT_OK(s2n_generate_ticket_age_add(&blob, &output));

            EXPECT_EQUAL(output, test_cases[i].expected_output);
        }
    }

    /* s2n_generate_session_secret */
    {
        /**
         *= https://tools.ietf.org/rfc/rfc8448#section-3
         *# expanded (32 octets):  4e cd 0e b6 ec 3b 4d 87 f5 d6 02 8f 92 2c
         *# a4 c5 85 1a 27 7f d4 13 11 c9 e6 2d 2c 94 92 e1 c4 f3
         **/
        S2N_BLOB_FROM_HEX(expected_session_secret,
        "4e cd 0e b6 ec 3b 4d 87 f5 d6 02 8f 92 2c \
            a4 c5 85 1a 27 7f d4 13 11 c9 e6 2d 2c 94 92 e1 c4 f3");

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

        conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
        EXPECT_SUCCESS(s2n_setup_test_resumption_secret(conn));

        uint8_t nonce_data[sizeof(uint16_t)] = { 0 };
        struct s2n_blob nonce = { 0 };
        EXPECT_SUCCESS(s2n_blob_init(&nonce, nonce_data, sizeof(nonce_data)));

        struct s2n_blob *output = &conn->tls13_ticket_fields.session_secret;
        EXPECT_SUCCESS(s2n_generate_session_secret(conn, &nonce, output));
        EXPECT_EQUAL(output->size, expected_session_secret.size);
        EXPECT_BYTEARRAY_EQUAL(output->data, expected_session_secret.data, expected_session_secret.size);

        EXPECT_SUCCESS(s2n_connection_free(conn));
    }

    /* s2n_tls13_server_nst_recv */
    {
        uint8_t test_ticket[] = { TEST_TICKET };
        uint8_t nst_data[] = {
            TEST_LIFETIME,       /* ticket lifetime */
            TEST_TICKET_AGE_ADD, /* ticket age add */
            0x02,                /* nonce len */
            0x00, 0x00,          /* nonce */
            0x00, 0x03,          /* ticket len */
            TEST_TICKET,         /* ticket */
            0x00, 0x00,          /* extensions len */
        };

        /* Does not read ticket message if config->use_tickets is not set */
        {
            struct s2n_config *config = s2n_config_new();
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            EXPECT_NOT_NULL(config);

            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* Set up input stuffer */
            DEFER_CLEANUP(struct s2n_stuffer input = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, 0));

            struct s2n_blob nst_message = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&nst_message, nst_data, sizeof(nst_data)));
            EXPECT_SUCCESS(s2n_stuffer_write(&input, &nst_message));

            EXPECT_OK(s2n_tls13_server_nst_recv(conn, &input));

            EXPECT_EQUAL(conn->client_ticket.size, 0);
            EXPECT_TRUE(s2n_stuffer_data_available(&input) > 0);

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

        /* Not allowed in TLS1.2 */
        {
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            conn->actual_protocol_version = S2N_TLS12;

            /* Set up input stuffer */
            DEFER_CLEANUP(struct s2n_stuffer input = { 0 }, s2n_stuffer_free);
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, 0));

            struct s2n_blob nst_message = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&nst_message, nst_data, sizeof(nst_data)));
            EXPECT_SUCCESS(s2n_stuffer_write(&input, &nst_message));

            EXPECT_ERROR_WITH_ERRNO(s2n_tls13_server_nst_recv(conn, &input), S2N_ERR_BAD_MESSAGE);

            EXPECT_EQUAL(conn->client_ticket.size, 0);
            EXPECT_TRUE(s2n_stuffer_data_available(&input) > 0);

            EXPECT_SUCCESS(s2n_connection_free(conn));
        }

        /* Tests session_ticket_cb correctly serializes session data from an arbitrary new session ticket message */
        {
            struct s2n_config *config = s2n_config_new();
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            EXPECT_NOT_NULL(config);

            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

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

            /* Set up input stuffer */
            struct s2n_stuffer input = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, 0));

            struct s2n_blob nst_message = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&nst_message, nst_data, sizeof(nst_data)));
            EXPECT_SUCCESS(s2n_stuffer_write(&input, &nst_message));

            EXPECT_OK(s2n_tls13_server_nst_recv(conn, &input));
            EXPECT_BYTEARRAY_EQUAL(conn->client_ticket.data, test_ticket, sizeof(test_ticket));
            EXPECT_EQUAL(s2n_stuffer_data_available(&input), 0);

            /* Initialize a stuffer to examine the serialized data returned in the session ticket callback */
            struct s2n_blob session_blob = { 0 };
            struct s2n_stuffer session_stuffer = { 0 };
            EXPECT_SUCCESS(s2n_blob_init(&session_blob, cb_session_data, cb_session_data_len));
            EXPECT_SUCCESS(s2n_stuffer_init(&session_stuffer, &session_blob));
            EXPECT_SUCCESS(s2n_stuffer_skip_write(&session_stuffer, cb_session_data_len));

            /* Check the serialized ticket is what was in the arbitrary nst message */
            {
                /* Skip to encrypted ticket size */
                EXPECT_SUCCESS((s2n_stuffer_skip_read(&session_stuffer, sizeof(uint8_t))));

                uint16_t ticket_size = 0;
                EXPECT_SUCCESS(s2n_stuffer_read_uint16(&session_stuffer, &ticket_size));
                EXPECT_EQUAL(ticket_size, sizeof(test_ticket));

                uint8_t *ticket = s2n_stuffer_raw_read(&session_stuffer, ticket_size);
                EXPECT_NOT_NULL(ticket);
                EXPECT_BYTEARRAY_EQUAL(ticket, test_ticket, ticket_size);
            }

            /* Check the serialized ticket_age_add is what was in the arbitrary nst message*/ 
            {
                uint8_t test_ticket_age_add[] = { TEST_TICKET_AGE_ADD };
                uint8_t ticket_age_add_marker = sizeof(uint8_t) + /* client state format */ \
                                                sizeof(uint8_t) + /* protocol version */ \
                                                sizeof(uint16_t) + /* cipher suite */ \
                                                sizeof(uint64_t);  /* time */
                /* Skip to ticket_age_add */
                EXPECT_SUCCESS((s2n_stuffer_skip_read(&session_stuffer, ticket_age_add_marker)));

                uint8_t ticket_age_add[sizeof(uint32_t)] = { 0 };
                EXPECT_SUCCESS(s2n_stuffer_read_bytes(&session_stuffer, ticket_age_add, sizeof(uint32_t)));
                EXPECT_BYTEARRAY_EQUAL(ticket_age_add, test_ticket_age_add, sizeof(uint32_t));
            }

            /* Check ticket lifetime is what was in the arbitrary nst message */
            {
                uint8_t test_lifetime[] = { TEST_LIFETIME };
                uint32_t expected_lifetime = test_lifetime[3] | (test_lifetime[2] << 8) | \
                                            (test_lifetime[1] << 16) | (test_lifetime[0] << 24);
                EXPECT_EQUAL(expected_lifetime, cb_session_lifetime);
            }
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&input));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Known values test */
        {
            /**
             * NewSessionTicket handshake message
             * 
             *= https://tools.ietf.org/rfc/rfc8448#section-3
             *# NewSessionTicket (205 octets):  04 00 00 c9 00 00 00 1e fa d6 aa
             *#    c5 02 00 00 00 b2 2c 03 5d 82 93 59 ee 5f f7 af 4e c9 00 00 00
             *#    00 26 2a 64 94 dc 48 6d 2c 8a 34 cb 33 fa 90 bf 1b 00 70 ad 3c
             *#    49 88 83 c9 36 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9 82 11
             *#    72 83 f8 2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 be 7f d6 1d 28
             *#    27 db 27 9c ce 14 50 77 d4 54 a3 66 4d 4e 6d a4 d2 9e e0 37 25
             *#    a6 a4 da fc d0 fc 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5 90 6c
             *#    5b 3f 7d 8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 97 b5 ae a6
             *#    17 64 6f ac 5c 03 27 2e 97 07 27 c6 21 a7 91 41 ef 5f 7d e6 50
             *#    5e 5b fb c3 88 e9 33 43 69 40 93 93 4a e4 d3 57 00 08 00 2a 00
             *#    04 00 00 04 00
             **/
            S2N_BLOB_FROM_HEX(nst_message, 
            "04 00 00 c9 00 00 00 1e fa d6 aa \
                c5 02 00 00 00 b2 2c 03 5d 82 93 59 ee 5f f7 af 4e c9 00 00 00 \
                00 26 2a 64 94 dc 48 6d 2c 8a 34 cb 33 fa 90 bf 1b 00 70 ad 3c \
                49 88 83 c9 36 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9 82 11 \
                72 83 f8 2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 be 7f d6 1d 28 \
                27 db 27 9c ce 14 50 77 d4 54 a3 66 4d 4e 6d a4 d2 9e e0 37 25 \
                a6 a4 da fc d0 fc 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5 90 6c \
                5b 3f 7d 8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 97 b5 ae a6 \
                17 64 6f ac 5c 03 27 2e 97 07 27 c6 21 a7 91 41 ef 5f 7d e6 50 \
                5e 5b fb c3 88 e9 33 43 69 40 93 93 4a e4 d3 57 00 08 00 2a 00 \
                04 00 00 04 00");
            
            struct s2n_config *config = s2n_config_new();
            struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(conn);
            EXPECT_NOT_NULL(config);

            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

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

            /* Set up input stuffer */
            struct s2n_stuffer input = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, 0));

            EXPECT_SUCCESS(s2n_stuffer_write(&input, &nst_message));
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&input, sizeof(uint8_t) + SIZEOF_UINT24));
            EXPECT_OK(s2n_tls13_server_nst_recv(conn, &input));

            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&input));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Self-talk test */
        {
            struct s2n_config *config = s2n_config_new();
            struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(client_conn);
            EXPECT_NOT_NULL(config);

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

            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));
            EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config));

            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));
            EXPECT_SUCCESS(s2n_connection_set_config(client_conn, config));

            client_conn->actual_protocol_version = S2N_TLS13;
            server_conn->actual_protocol_version = S2N_TLS13;
            client_conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
            server_conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;

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

            EXPECT_OK(s2n_tls13_server_nst_write(server_conn, &stuffer));
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, sizeof(uint8_t) + SIZEOF_UINT24));
            EXPECT_OK(s2n_tls13_server_nst_recv(client_conn, &stuffer));

            EXPECT_SUCCESS(s2n_connection_free(client_conn));
            EXPECT_SUCCESS(s2n_connection_free(server_conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Test that the client processes extensions.
         * Specifically, check for the early_data_indication extension. */
        {
            const uint32_t expected_max_early_data_size = 17;

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));

            struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(client_conn);
            client_conn->actual_protocol_version = S2N_TLS13;
            client_conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
            EXPECT_SUCCESS(s2n_connection_set_config(client_conn, config));

            struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(server_conn);
            server_conn->actual_protocol_version = S2N_TLS13;
            server_conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
            EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config));
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(server_conn, expected_max_early_data_size));

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

            EXPECT_EQUAL(client_conn->server_max_early_data_size, 0);
            EXPECT_OK(s2n_tls13_server_nst_write(server_conn, &stuffer));
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, sizeof(uint8_t) + SIZEOF_UINT24));
            EXPECT_OK(s2n_tls13_server_nst_recv(client_conn, &stuffer));
            EXPECT_EQUAL(client_conn->server_max_early_data_size, expected_max_early_data_size);

            EXPECT_SUCCESS(s2n_connection_free(client_conn));
            EXPECT_SUCCESS(s2n_connection_free(server_conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Test that the client can handle different max_early_data_size values. */
        {
            const uint32_t expected_max_early_data_sizes[] = { 17, 0, UINT16_MAX, 0, 20, UINT32_MAX, 5, 0 };

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));

            struct s2n_connection *client_conn = s2n_connection_new(S2N_CLIENT);
            EXPECT_NOT_NULL(client_conn);
            client_conn->actual_protocol_version = S2N_TLS13;
            client_conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
            EXPECT_SUCCESS(s2n_connection_set_config(client_conn, config));

            struct s2n_connection *server_conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(server_conn);
            server_conn->actual_protocol_version = S2N_TLS13;
            server_conn->secure.cipher_suite = &s2n_tls13_aes_128_gcm_sha256;
            EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config));

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

            for (size_t i = 0; i < s2n_array_len(expected_max_early_data_sizes); i++) {
                EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(server_conn, expected_max_early_data_sizes[i]));
                EXPECT_OK(s2n_tls13_server_nst_write(server_conn, &stuffer));
                EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, sizeof(uint8_t) + SIZEOF_UINT24));
                EXPECT_OK(s2n_tls13_server_nst_recv(client_conn, &stuffer));
                EXPECT_EQUAL(client_conn->server_max_early_data_size, expected_max_early_data_sizes[i]);
                EXPECT_SUCCESS(s2n_stuffer_wipe(&stuffer));
            }

            EXPECT_SUCCESS(s2n_connection_free(client_conn));
            EXPECT_SUCCESS(s2n_connection_free(server_conn));
            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Test that the client rejects tickets with invalid ticket_lifetime */
        {
            const size_t lifetime_size = sizeof(uint32_t);
            const uint8_t *nst_data_without_lifetime = nst_data + lifetime_size;
            const size_t nst_data_without_lifetime_size = sizeof(nst_data) - lifetime_size;

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
            EXPECT_SUCCESS(s2n_config_set_session_ticket_cb(config, s2n_test_session_ticket_cb, NULL));

            /**
             *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
             *= type=test
             *# The value of zero indicates that the
             *# ticket should be discarded immediately.
             */
            {
                struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
                conn->actual_protocol_version = S2N_TLS13;

                DEFER_CLEANUP(struct s2n_stuffer input = { 0 }, s2n_stuffer_free);
                EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, sizeof(nst_data)));
                EXPECT_SUCCESS(s2n_stuffer_write_uint32(&input, 0));
                EXPECT_SUCCESS(s2n_stuffer_write_bytes(&input, nst_data_without_lifetime, nst_data_without_lifetime_size));

                EXPECT_OK(s2n_tls13_server_nst_recv(conn, &input));
                /* Verify that the client only got as far as the ticket_lifetime when parsing */
                EXPECT_EQUAL(s2n_stuffer_data_available(&input), nst_data_without_lifetime_size);
                /* Verify that the client did not accept + store the ticket */
                EXPECT_EQUAL(s2n_connection_get_session_length(conn), 0);

                EXPECT_SUCCESS(s2n_connection_free(conn));
            }

            /**
             *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
             *= type=test
             *# Servers MUST NOT use any value greater than
             *# 604800 seconds (7 days).
             */
            {
                struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);
                EXPECT_NOT_NULL(conn);
                EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
                conn->actual_protocol_version = S2N_TLS13;

                DEFER_CLEANUP(struct s2n_stuffer input = { 0 }, s2n_stuffer_free);
                EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&input, sizeof(nst_data)));
                EXPECT_SUCCESS(s2n_stuffer_write_uint32(&input, UINT32_MAX));
                EXPECT_SUCCESS(s2n_stuffer_write_bytes(&input, nst_data_without_lifetime, nst_data_without_lifetime_size));

                EXPECT_ERROR_WITH_ERRNO(s2n_tls13_server_nst_recv(conn, &input), S2N_ERR_BAD_MESSAGE);
                /* Verify that the client only got as far as the ticket_lifetime when parsing */
                EXPECT_EQUAL(s2n_stuffer_data_available(&input), nst_data_without_lifetime_size);
                /* Verify that the client did not accept + store the ticket */
                EXPECT_EQUAL(s2n_connection_get_session_length(conn), 0);

                EXPECT_SUCCESS(s2n_connection_free(conn));
            }

            EXPECT_SUCCESS(s2n_config_free(config));
        }
    }

    /* s2n_tls13_server_nst_send */
    {
        /* Mode is not server */
        {
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_CLIENT));
            conn->actual_protocol_version = S2N_TLS13;
            conn->tickets_to_send = 1;

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));

            EXPECT_EQUAL(0, s2n_stuffer_data_available(&stuffer));

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
        }

        /* Protocol is less than TLS13 */
        {
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            conn->actual_protocol_version = S2N_TLS12;
            conn->tickets_to_send = 1;

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));

            EXPECT_EQUAL(0, s2n_stuffer_data_available(&stuffer));

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
        }

        /* 0 tickets are requested */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->actual_protocol_version = S2N_TLS13;
            conn->tickets_to_send = 0;
            EXPECT_NOT_EQUAL(0, s2n_stuffer_space_remaining(&conn->handshake.io));

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));

            /* Check no tickets are written */
            EXPECT_EQUAL(0, s2n_stuffer_data_available(&stuffer));

            /* Check handshake.io is cleaned up */
            EXPECT_EQUAL(0, s2n_stuffer_space_remaining(&conn->handshake.io));

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Sends one new session ticket */
        {
            struct s2n_config *config;
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(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;
            conn->tickets_to_send = 1;
            EXPECT_NOT_EQUAL(s2n_stuffer_space_remaining(&conn->handshake.io), 0);

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));

            /* Check only one record was written */
            uint16_t record_len = 0;
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, RECORD_LEN_MARKER));
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&stuffer, &record_len));
            EXPECT_TRUE(record_len > 0);
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, record_len));
            EXPECT_EQUAL(s2n_stuffer_data_available(&stuffer), 0);

            /* Check handshake.io is cleaned up */
            EXPECT_EQUAL(s2n_stuffer_space_remaining(&conn->handshake.io), 0);

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Send no more tickets if keying material is expired
         *
         *= https://tools.ietf.org/rfc/rfc8446#section-4.6.1
         *= type=test
         *# Note that in principle it is possible to continue issuing new tickets
         *# which indefinitely extend the lifetime of the keying material
         *# originally derived from an initial non-PSK handshake (which was most
         *# likely tied to the peer's certificate). It is RECOMMENDED that
         *# implementations place limits on the total lifetime of such keying
         *# material; these limits should take into account the lifetime of the
         *# peer's certificate, the likelihood of intervening revocation, and the
         *# time since the peer's online CertificateVerify signature.
         */
        {
            const uint8_t current_tickets = 10;
            const uint8_t new_tickets = 5;

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));
            conn->actual_protocol_version = S2N_TLS13;
            conn->tickets_sent = current_tickets;
            conn->tickets_to_send = current_tickets;

            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            /* Can request new tickets */
            EXPECT_SUCCESS(s2n_connection_add_new_tickets_to_send(conn, new_tickets));
            EXPECT_EQUAL(conn->tickets_sent, current_tickets);
            EXPECT_EQUAL(conn->tickets_to_send, current_tickets + new_tickets);

            /* Add expired keying material */
            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;

            /* Despite tickets requested, no tickets sent */
            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
            EXPECT_EQUAL(s2n_stuffer_data_available(&stuffer), 0);
            EXPECT_EQUAL(conn->tickets_sent, current_tickets);
            EXPECT_EQUAL(conn->tickets_to_send, current_tickets);

            /* Can't request more tickets */
            EXPECT_FAILURE_WITH_ERRNO(s2n_connection_add_new_tickets_to_send(conn, new_tickets),
                    S2N_ERR_KEYING_MATERIAL_EXPIRED);
            EXPECT_EQUAL(conn->tickets_sent, current_tickets);
            EXPECT_EQUAL(conn->tickets_to_send, current_tickets);

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* s2n_config_set_session_tickets_onoff used to enable tickets */
        {
            uint8_t test_data[S2N_TICKET_KEY_NAME_LEN] = "data";
            uint64_t current_time = 0;

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, true));
            EXPECT_SUCCESS(config->wall_clock(config->sys_clock_ctx, &current_time));
            EXPECT_SUCCESS(s2n_config_add_ticket_crypto_key(config, test_data, sizeof(test_data),
                    test_data, sizeof(test_data), current_time / ONE_SEC_IN_NANOS));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            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_128_gcm_sha256;

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
            EXPECT_NOT_EQUAL(0, s2n_stuffer_data_available(&stuffer));
            EXPECT_SUCCESS(s2n_stuffer_wipe(&stuffer));

            /* Request more tickets */
            EXPECT_SUCCESS(s2n_connection_add_new_tickets_to_send(conn, 1));
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
            EXPECT_NOT_EQUAL(0, s2n_stuffer_data_available(&stuffer));
            EXPECT_SUCCESS(s2n_stuffer_wipe(&stuffer));

            /* Turn tickets off */
            EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, false));

            /* Request more tickets */
            EXPECT_SUCCESS(s2n_connection_add_new_tickets_to_send(conn, 1));
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
            EXPECT_EQUAL(0, s2n_stuffer_data_available(&stuffer));

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* s2n_config_set_initial_ticket_count used to enable tickets */
        {
            uint8_t test_data[S2N_TICKET_KEY_NAME_LEN] = "data";
            uint64_t current_time = 0;

            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_config_set_initial_ticket_count(config, 1));
            EXPECT_SUCCESS(config->wall_clock(config->sys_clock_ctx, &current_time));
            EXPECT_SUCCESS(s2n_config_add_ticket_crypto_key(config, test_data, sizeof(test_data),
                    test_data, sizeof(test_data), current_time / ONE_SEC_IN_NANOS));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            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_128_gcm_sha256;

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
            EXPECT_NOT_EQUAL(0, s2n_stuffer_data_available(&stuffer));

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Sends multiple new session tickets */
        {
            struct s2n_config *config;
            struct s2n_connection *conn;
            EXPECT_NOT_NULL(conn = s2n_connection_new(S2N_SERVER));
            EXPECT_NOT_NULL(config = s2n_config_new());

            EXPECT_SUCCESS(s2n_setup_test_ticket_key(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;
            uint16_t tickets_to_send = 5;
            conn->tickets_to_send = tickets_to_send;

            /* Setup io */
            struct s2n_stuffer stuffer;
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&stuffer, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&stuffer, &stuffer, conn));

            s2n_blocked_status blocked = 0;
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));

            /* Check five records were written */
            uint16_t record_len = 0;
            for (size_t i = 0; i < tickets_to_send; i++) {
                EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, RECORD_LEN_MARKER));
                EXPECT_SUCCESS(s2n_stuffer_read_uint16(&stuffer, &record_len));
                EXPECT_TRUE(record_len > 0);
                EXPECT_SUCCESS(s2n_stuffer_skip_read(&stuffer, record_len));
            }
            EXPECT_TRUE(s2n_stuffer_data_available(&stuffer) == 0);

            /* No more tickets to send */
            EXPECT_SUCCESS(s2n_stuffer_rewrite(&stuffer));
            EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
            EXPECT_EQUAL(0, s2n_stuffer_data_available(&stuffer));

            EXPECT_SUCCESS(s2n_stuffer_free(&stuffer));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }

        /* Test S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE */
        {
            struct s2n_config *config = s2n_config_new();
            EXPECT_NOT_NULL(config);
            EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));

            struct s2n_connection *conn = s2n_connection_new(S2N_SERVER);
            EXPECT_NOT_NULL(conn);
            EXPECT_SUCCESS(s2n_connection_set_config(conn, config));

            /* TLS1.3 tickets contain extra fields */
            conn->actual_protocol_version = S2N_TLS13;
            /* Largest possible TLS1.3 secret size */
            conn->secure.cipher_suite = &s2n_tls13_aes_256_gcm_sha384;
            /* Necessary for extensions, which contribute to size */
            EXPECT_SUCCESS(s2n_connection_set_server_max_early_data_size(conn, 10));

            /* Setup io */
            struct s2n_stuffer output = { 0 };
            EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&output, 0));
            EXPECT_SUCCESS(s2n_connection_set_io_stuffers(&output, &output, conn));

            /* Test with no variable fields */
            {
                size_t session_state_size = 0;
                EXPECT_OK(s2n_connection_get_session_state_size(conn, &session_state_size));
                EXPECT_NOT_EQUAL(session_state_size, 0);

                s2n_blocked_status blocked = 0;
                EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
                EXPECT_NOT_EQUAL(s2n_stuffer_data_available(&output), 0);

                uint32_t expected_max_size = s2n_stuffer_data_available(&output) - S2N_TLS_RECORD_HEADER_LENGTH;
                uint32_t expected_max_fixed_size = expected_max_size - session_state_size;
                if (S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE != expected_max_fixed_size) {
                    fprintf(stdout, "\nS2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE (%i) should be %i\n",
                            (int) S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE, expected_max_fixed_size);
                }
                EXPECT_EQUAL(S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE, expected_max_fixed_size);
            }

            EXPECT_SUCCESS(s2n_stuffer_wipe(&output));
            conn->tickets_to_send++;

            /* Test with some variable fields */
            {
                const uint8_t early_data_context[] = "early data context";
                EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(conn,
                        early_data_context, sizeof(early_data_context)));

                size_t session_state_size = 0;
                EXPECT_OK(s2n_connection_get_session_state_size(conn, &session_state_size));
                EXPECT_NOT_EQUAL(session_state_size, 0);

                s2n_blocked_status blocked = 0;
                EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
                EXPECT_NOT_EQUAL(s2n_stuffer_data_available(&output), 0);

                uint32_t expected_max_size = s2n_stuffer_data_available(&output) - S2N_TLS_RECORD_HEADER_LENGTH;
                uint32_t expected_max_fixed_size = expected_max_size - session_state_size;
                EXPECT_EQUAL(S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE, expected_max_fixed_size);
            }

            EXPECT_SUCCESS(s2n_stuffer_wipe(&output));
            conn->tickets_to_send++;

            /* Test with all variable fields */
            {
                const uint8_t early_data_context[] = "different early data context";
                EXPECT_SUCCESS(s2n_connection_set_server_early_data_context(conn,
                        early_data_context, sizeof(early_data_context)));

                const uint8_t app_protocol[] = "https";
                EXPECT_MEMCPY_SUCCESS(conn->application_protocol, app_protocol, sizeof(app_protocol));

                size_t session_state_size = 0;
                EXPECT_OK(s2n_connection_get_session_state_size(conn, &session_state_size));
                EXPECT_NOT_EQUAL(session_state_size, 0);

                s2n_blocked_status blocked = 0;
                EXPECT_OK(s2n_tls13_server_nst_send(conn, &blocked));
                EXPECT_NOT_EQUAL(s2n_stuffer_data_available(&output), 0);

                uint32_t expected_max_size = s2n_stuffer_data_available(&output) - S2N_TLS_RECORD_HEADER_LENGTH;
                uint32_t expected_max_fixed_size = expected_max_size - session_state_size;
                EXPECT_EQUAL(S2N_TLS13_MAX_FIXED_NEW_SESSION_TICKET_SIZE, expected_max_fixed_size);
            }

            EXPECT_SUCCESS(s2n_stuffer_free(&output));
            EXPECT_SUCCESS(s2n_connection_free(conn));
            EXPECT_SUCCESS(s2n_config_free(config));
        }
    }

    /* Functional test: s2n_negotiate sends new session tickets after the handshake is complete */
    {
        /* Setup connections */
        struct s2n_connection *client_conn, *server_conn;
        EXPECT_NOT_NULL(client_conn = s2n_connection_new(S2N_CLIENT));
        EXPECT_NOT_NULL(server_conn = s2n_connection_new(S2N_SERVER));

        /* Setup config */
        struct s2n_cert_chain_and_key *chain_and_key;
        EXPECT_SUCCESS(s2n_test_cert_chain_and_key_new(&chain_and_key,
                S2N_DEFAULT_ECDSA_TEST_CERT_CHAIN, S2N_DEFAULT_ECDSA_TEST_PRIVATE_KEY));
        struct s2n_config *config;
        EXPECT_NOT_NULL(config = s2n_config_new());
        EXPECT_SUCCESS(s2n_config_set_cipher_preferences(config, "default_tls13"));
        EXPECT_SUCCESS(s2n_config_set_unsafe_for_testing(config));
        EXPECT_SUCCESS(s2n_config_add_cert_chain_and_key_to_store(config, chain_and_key));
        EXPECT_SUCCESS(s2n_config_set_session_tickets_onoff(config, 1));
        EXPECT_SUCCESS(s2n_connection_set_config(client_conn, config));

        EXPECT_SUCCESS(s2n_setup_test_ticket_key(config));
        EXPECT_SUCCESS(s2n_connection_set_config(server_conn, config));

        uint16_t tickets_to_send = 5;
        server_conn->tickets_to_send = tickets_to_send;

        struct s2n_stuffer client_to_server;
        struct s2n_stuffer server_to_client;

        EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&client_to_server, 0));
        EXPECT_SUCCESS(s2n_stuffer_growable_alloc(&server_to_client, 0));

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

        /* Do handshake */
        EXPECT_SUCCESS(s2n_negotiate_test_server_and_client(server_conn, client_conn));

        /* Check handshake.io was cleaned up.
         * If a ticket was written, this happens afterwards. */
        EXPECT_EQUAL(s2n_stuffer_space_remaining(&server_conn->handshake.io), 0);
        EXPECT_EQUAL(s2n_stuffer_space_remaining(&client_conn->handshake.io), 0);

        /* Check there are five records corresponding to five new session tickets
         * not read as part of the handshake */
        uint16_t record_len = 0;
        for (size_t i = 0; i < tickets_to_send; i++) {
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&server_to_client, RECORD_LEN_MARKER));
            EXPECT_SUCCESS(s2n_stuffer_read_uint16(&server_to_client, &record_len));
            EXPECT_TRUE(record_len > 0);
            EXPECT_SUCCESS(s2n_stuffer_skip_read(&server_to_client, record_len));
        }
        EXPECT_TRUE(s2n_stuffer_data_available(&server_to_client) == 0);

        /* Call s2n_negotiate again to ensure no more tickets are sent */
        EXPECT_SUCCESS(s2n_negotiate_test_server_and_client(server_conn, client_conn));
        EXPECT_EQUAL(0, s2n_stuffer_data_available(&server_to_client));

        EXPECT_SUCCESS(s2n_stuffer_free(&client_to_server));
        EXPECT_SUCCESS(s2n_stuffer_free(&server_to_client));
        EXPECT_SUCCESS(s2n_connection_free(server_conn));
        EXPECT_SUCCESS(s2n_connection_free(client_conn));
        EXPECT_SUCCESS(s2n_cert_chain_and_key_free(chain_and_key));
        EXPECT_SUCCESS(s2n_config_free(config));
    }

    END_TEST();
}
