in tls/s2n_resume.c [892:958]
S2N_RESULT s2n_resume_decrypt_session(struct s2n_connection *conn, struct s2n_stuffer *from)
{
RESULT_ENSURE_REF(conn);
RESULT_ENSURE_REF(from);
RESULT_ENSURE_REF(conn->config);
/* Read version number */
uint8_t version = 0;
RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(from, &version));
RESULT_ENSURE_EQ(version, S2N_PRE_ENCRYPTED_STATE_V1);
/* Read key name */
uint8_t key_name[S2N_TICKET_KEY_NAME_LEN] = { 0 };
RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, key_name, sizeof(key_name)));
struct s2n_ticket_key *key = s2n_find_ticket_key(conn->config, key_name);
/* Key has expired; do full handshake */
RESULT_ENSURE(key != NULL, S2N_ERR_KEY_USED_IN_SESSION_TICKET_NOT_FOUND);
struct s2n_unique_ticket_key ticket_key = { 0 };
RESULT_GUARD_POSIX(s2n_blob_init(&ticket_key.initial_key, key->aes_key, sizeof(key->aes_key)));
RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(from, ticket_key.info, sizeof(ticket_key.info)));
RESULT_GUARD(s2n_resume_generate_unique_ticket_key(&ticket_key));
/* Read IV */
uint8_t iv_data[S2N_TLS_GCM_IV_LEN] = { 0 };
struct s2n_blob iv = { 0 };
RESULT_GUARD_POSIX(s2n_blob_init(&iv, iv_data, sizeof(iv_data)));
RESULT_GUARD_POSIX(s2n_stuffer_read(from, &iv));
/* Initialize AES key */
struct s2n_blob aes_key_blob = { 0 };
RESULT_GUARD_POSIX(s2n_blob_init(&aes_key_blob, ticket_key.output_key, sizeof(ticket_key.output_key)));
DEFER_CLEANUP(struct s2n_session_key aes_ticket_key = { 0 }, s2n_session_key_free);
RESULT_GUARD_POSIX(s2n_session_key_alloc(&aes_ticket_key));
RESULT_GUARD(s2n_aes256_gcm.init(&aes_ticket_key));
RESULT_GUARD(s2n_aes256_gcm.set_decryption_key(&aes_ticket_key, &aes_key_blob));
/* Initialize Additional Authenticated Data */
uint8_t aad_data[S2N_TICKET_AAD_LEN] = { 0 };
struct s2n_blob aad_blob = { 0 };
RESULT_GUARD_POSIX(s2n_blob_init(&aad_blob, aad_data, sizeof(aad_data)));
struct s2n_stuffer aad = { 0 };
RESULT_GUARD_POSIX(s2n_stuffer_init(&aad, &aad_blob));
RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&aad, key->implicit_aad, sizeof(key->implicit_aad)));
RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&aad, key->key_name, sizeof(key->key_name)));
/* Initialize blob to be decrypted */
struct s2n_blob en_blob = { 0 };
uint32_t en_blob_size = s2n_stuffer_data_available(from);
uint8_t *en_blob_data = s2n_stuffer_raw_read(from, en_blob_size);
RESULT_ENSURE_REF(en_blob_data);
RESULT_GUARD_POSIX(s2n_blob_init(&en_blob, en_blob_data, en_blob_size));
RESULT_GUARD_POSIX(s2n_aes256_gcm.io.aead.decrypt(&aes_ticket_key, &iv, &aad_blob, &en_blob, &en_blob));
/* Parse decrypted state */
struct s2n_blob state_blob = { 0 };
uint32_t state_blob_size = en_blob_size - S2N_TLS_GCM_TAG_LEN;
RESULT_GUARD_POSIX(s2n_blob_init(&state_blob, en_blob.data, state_blob_size));
struct s2n_stuffer state_stuffer = { 0 };
RESULT_GUARD_POSIX(s2n_stuffer_init(&state_stuffer, &state_blob));
RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&state_stuffer, state_blob_size));
RESULT_GUARD(s2n_deserialize_resumption_state(conn, &from->blob, &state_stuffer));
return S2N_RESULT_OK;
}