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, ¤t_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;
}