static S2N_RESULT s2n_tls13_deserialize_session_state()

in tls/s2n_resume.c [304:378]


static S2N_RESULT s2n_tls13_deserialize_session_state(struct s2n_connection *conn, struct s2n_blob *psk_identity, struct s2n_stuffer *from)
{
    RESULT_ENSURE_REF(conn);
    RESULT_ENSURE_REF(psk_identity);
    RESULT_ENSURE_REF(from);

    DEFER_CLEANUP(struct s2n_psk psk = { 0 }, s2n_psk_wipe);
    RESULT_GUARD(s2n_psk_init(&psk, S2N_PSK_TYPE_RESUMPTION));
    RESULT_GUARD_POSIX(s2n_psk_set_identity(&psk, psk_identity->data, psk_identity->size));

    uint8_t protocol_version = 0;
    RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &protocol_version));
    RESULT_ENSURE_GTE(protocol_version, S2N_TLS13);

    uint8_t iana_id[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
    RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, iana_id, S2N_TLS_CIPHER_SUITE_LEN));
    struct s2n_cipher_suite *cipher_suite = NULL;
    RESULT_GUARD(s2n_cipher_suite_from_iana(iana_id, sizeof(iana_id), &cipher_suite));
    RESULT_ENSURE_REF(cipher_suite);
    psk.hmac_alg = cipher_suite->prf_alg;

    RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(from, &psk.ticket_issue_time));

    /**
     *= https://www.rfc-editor.org/rfc/rfc8446#section-4.6.1
     *# 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 = 0;
    RESULT_GUARD(s2n_config_wall_clock(conn->config, &current_time));
    RESULT_GUARD(s2n_validate_ticket_age(current_time, psk.ticket_issue_time));

    RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(from, &psk.ticket_age_add));

    uint8_t secret_len = 0;
    RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &secret_len));
    RESULT_ENSURE_LTE(secret_len, S2N_TLS_SECRET_LEN);
    uint8_t *secret_data = s2n_stuffer_raw_read(from, secret_len);
    RESULT_ENSURE_REF(secret_data);
    RESULT_GUARD_POSIX(s2n_psk_set_secret(&psk, secret_data, secret_len));

    if (conn->mode == S2N_SERVER) {
        RESULT_GUARD_POSIX(s2n_stuffer_read_uint64(from, &psk.keying_material_expiration));
        RESULT_ENSURE(psk.keying_material_expiration > current_time, S2N_ERR_KEYING_MATERIAL_EXPIRED);
    }

    uint32_t max_early_data_size = 0;
    RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(from, &max_early_data_size));
    if (max_early_data_size > 0) {
        RESULT_GUARD_POSIX(s2n_psk_configure_early_data(&psk, max_early_data_size,
                iana_id[0], iana_id[1]));

        uint8_t app_proto_size = 0;
        RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &app_proto_size));
        uint8_t *app_proto_data = s2n_stuffer_raw_read(from, app_proto_size);
        RESULT_ENSURE_REF(app_proto_data);
        RESULT_GUARD_POSIX(s2n_psk_set_application_protocol(&psk, app_proto_data, app_proto_size));

        uint16_t early_data_context_size = 0;
        RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(from, &early_data_context_size));
        uint8_t *early_data_context_data = s2n_stuffer_raw_read(from, early_data_context_size);
        RESULT_ENSURE_REF(early_data_context_data);
        RESULT_GUARD_POSIX(s2n_psk_set_early_data_context(&psk, early_data_context_data, early_data_context_size));
    }

    /* Make sure that this connection is configured for resumption PSKs, not external PSKs */
    RESULT_GUARD(s2n_connection_set_psk_type(conn, S2N_PSK_TYPE_RESUMPTION));
    /* Remove all previously-set PSKs. To keep the session ticket API behavior consistent
     * across protocol versions, we currently only support setting a single resumption PSK. */
    RESULT_GUARD(s2n_psk_parameters_wipe(&conn->psk_params));
    RESULT_GUARD_POSIX(s2n_connection_append_psk(conn, &psk));

    return S2N_RESULT_OK;
}