/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "avb_ops.h"

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#include <string>

#include <android-base/macros.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <libavb/libavb.h>
#include <libdm/dm.h>
#include <utils/Compat.h>

#include "util.h"

using namespace std::literals;

namespace android {
namespace fs_mgr {

static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
                                       size_t num_bytes, void* buffer, size_t* out_num_read) {
    return FsManagerAvbOps::GetInstanceFromAvbOps(ops)->ReadFromPartition(
            partition, offset, num_bytes, buffer, out_num_read);
}

static AvbIOResult no_op_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED,
                                            size_t rollback_index_location ATTRIBUTE_UNUSED,
                                            uint64_t* out_rollback_index) {
    // rollback_index has been checked in bootloader phase.
    // In user-space, returns the smallest value 0 to pass the check.
    *out_rollback_index = 0;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult no_op_validate_vbmeta_public_key(
        AvbOps* ops ATTRIBUTE_UNUSED, const uint8_t* public_key_data ATTRIBUTE_UNUSED,
        size_t public_key_length ATTRIBUTE_UNUSED,
        const uint8_t* public_key_metadata ATTRIBUTE_UNUSED,
        size_t public_key_metadata_length ATTRIBUTE_UNUSED, bool* out_is_trusted) {
    // vbmeta public key has been checked in bootloader phase.
    // In user-space, returns true to pass the check.
    //
    // Addtionally, user-space should check
    // androidboot.vbmeta.{hash_alg, size, digest} against the digest
    // of all vbmeta images after invoking avb_slot_verify().
    *out_is_trusted = true;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult no_op_read_is_device_unlocked(AvbOps* ops ATTRIBUTE_UNUSED,
                                                bool* out_is_unlocked) {
    // The function is for bootloader to update the value into
    // androidboot.vbmeta.device_state in kernel cmdline.
    // In user-space, returns true as we don't need to update it anymore.
    *out_is_unlocked = true;
    return AVB_IO_RESULT_OK;
}

static AvbIOResult no_op_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNUSED,
                                                      const char* partition ATTRIBUTE_UNUSED,
                                                      char* guid_buf, size_t guid_buf_size) {
    // The function is for bootloader to set the correct UUID
    // for a given partition in kernel cmdline.
    // In user-space, returns a faking one as we don't need to update
    // it anymore.
    snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
    return AVB_IO_RESULT_OK;
}

static AvbIOResult no_op_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED,
                                              const char* partition ATTRIBUTE_UNUSED,
                                              uint64_t* out_size_num_byte) {
    // The function is for bootloader to load entire content of AVB HASH partitions.
    // In user-space, returns 0 as we only need to set up AVB HASHTHREE partitions.
    *out_size_num_byte = 0;
    return AVB_IO_RESULT_OK;
}

// Converts a partition name (with ab_suffix) to the corresponding mount point.
// e.g., "system_a" => "/system",
// e.g., "vendor_a" => "/vendor",
static std::string DeriveMountPoint(const std::string& partition_name) {
    const std::string ab_suffix = fs_mgr_get_slot_suffix();
    std::string mount_point(partition_name);
    auto found = partition_name.rfind(ab_suffix);
    if (found != std::string::npos) {
        mount_point.erase(found);  // converts system_a => system
    }

    return "/" + mount_point;
}

FsManagerAvbOps::FsManagerAvbOps() {
    // We only need to provide the implementation of read_from_partition()
    // operation since that's all what is being used by the avb_slot_verify().
    // Other I/O operations are only required in bootloader but not in
    // user-space so we set them as no-op operations. Also zero the entire
    // struct so operations added in the future will be set to NULL.
    memset(&avb_ops_, 0, sizeof(AvbOps));
    avb_ops_.read_from_partition = read_from_partition;
    avb_ops_.read_rollback_index = no_op_read_rollback_index;
    avb_ops_.validate_vbmeta_public_key = no_op_validate_vbmeta_public_key;
    avb_ops_.read_is_device_unlocked = no_op_read_is_device_unlocked;
    avb_ops_.get_unique_guid_for_partition = no_op_get_unique_guid_for_partition;
    avb_ops_.get_size_of_partition = no_op_get_size_of_partition;

    // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
    avb_ops_.user_data = this;
}

// Given a partition name (with ab_suffix), e.g., system_a, returns the corresponding
// dm-linear path for it. e.g., /dev/block/dm-0. If not found, returns an empty string.
// This assumes that the prefix of the partition name and the mount point are the same.
// e.g., partition vendor_a is mounted under /vendor, product_a is mounted under /product, etc.
// This might not be true for some special fstab files, e.g., fstab.postinstall.
// But it's good enough for the default fstab. Also note that the logical path is a
// fallback solution when the physical path (/dev/block/by-name/<partition>) cannot be found.
std::string FsManagerAvbOps::GetLogicalPath(const std::string& partition_name) {
    if (fstab_.empty() && !ReadDefaultFstab(&fstab_)) {
        return "";
    }

    const auto mount_point = DeriveMountPoint(partition_name);
    if (mount_point.empty()) return "";

    auto fstab_entry = GetEntryForMountPoint(&fstab_, mount_point);
    if (!fstab_entry) return "";

    std::string device_path;
    if (fstab_entry->fs_mgr_flags.logical) {
        dm::DeviceMapper& dm = dm::DeviceMapper::Instance();
        if (!dm.GetDmDevicePathByName(fstab_entry->blk_device, &device_path)) {
            LERROR << "Failed to resolve logical device path for: " << fstab_entry->blk_device;
            return "";
        }
        return device_path;
    }

    return "";
}

AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
                                               size_t num_bytes, void* buffer,
                                               size_t* out_num_read) {
    std::string path = "/dev/block/by-name/"s + partition;

    // Ensures the device path (a symlink created by init) is ready to access.
    if (!WaitForFile(path, 1s)) {
        LERROR << "Device path not found: " << path;
        // Falls back to logical path if the physical path is not found.
        // This mostly only works for emulator (no bootloader). Because in normal
        // device, bootloader is unable to read logical partitions. So if libavb in
        // the bootloader failed to read a physical partition, it will failed to boot
        // the HLOS and we won't reach the code here.
        path = GetLogicalPath(partition);
        if (path.empty() || !WaitForFile(path, 1s)) return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
        LINFO << "Fallback to use logical device path: " << path;
    }

    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
    if (fd < 0) {
        PERROR << "Failed to open " << path;
        return AVB_IO_RESULT_ERROR_IO;
    }

    // If offset is negative, interprets its absolute value as the
    //  number of bytes from the end of the partition.
    if (offset < 0) {
        off64_t total_size = lseek64(fd, 0, SEEK_END);
        if (total_size == -1) {
            PERROR << "Failed to lseek64 to end of the partition";
            return AVB_IO_RESULT_ERROR_IO;
        }
        offset = total_size + offset;
        // Repositions the offset to the beginning.
        if (lseek64(fd, 0, SEEK_SET) == -1) {
            PERROR << "Failed to lseek64 to the beginning of the partition";
            return AVB_IO_RESULT_ERROR_IO;
        }
    }

    // On Linux, we never get partial reads from block devices (except
    // for EOF).
    ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
    if (num_read < 0 || (size_t)num_read != num_bytes) {
        PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset;
        return AVB_IO_RESULT_ERROR_IO;
    }

    if (out_num_read != nullptr) {
        *out_num_read = num_read;
    }

    return AVB_IO_RESULT_OK;
}

AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix,
                                                   AvbSlotVerifyFlags flags,
                                                   std::vector<VBMetaData>* out_vbmeta_images) {
    // Invokes avb_slot_verify() to load and verify all vbmeta images.
    // Sets requested_partitions to nullptr as it's to copy the contents
    // of HASH partitions into handle>avb_slot_data_, which is not required as
    // fs_mgr only deals with HASHTREE partitions.
    const char* requested_partitions[] = {nullptr};

    // Local resource to store vbmeta images from avb_slot_verify();
    AvbSlotVerifyData* avb_slot_data;

    // The |hashtree_error_mode| field doesn't matter as it only
    // influences the generated kernel cmdline parameters.
    auto verify_result =
            avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags,
                            AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_slot_data);

    if (!avb_slot_data) return verify_result;
    // Copies avb_slot_data->vbmeta_images[].
    for (size_t i = 0; i < avb_slot_data->num_vbmeta_images; i++) {
        out_vbmeta_images->emplace_back(VBMetaData(avb_slot_data->vbmeta_images[i].vbmeta_data,
                                                   avb_slot_data->vbmeta_images[i].vbmeta_size,
                                                   avb_slot_data->vbmeta_images[i].partition_name));
    }

    // Free the local resource.
    avb_slot_verify_data_free(avb_slot_data);

    return verify_result;
}

}  // namespace fs_mgr
}  // namespace android
