S2N_RESULT s2n_resume_decrypt_session()

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;
}