/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "fs_avb/fs_avb.h"

#include <fcntl.h>
#include <libgen.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>

#include <algorithm>
#include <sstream>
#include <string>
#include <vector>

#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <libavb/libavb.h>
#include <libdm/dm.h>
#include <libgsi/libgsi.h>

#include "avb_ops.h"
#include "avb_util.h"
#include "sha.h"
#include "util.h"

using android::base::Basename;
using android::base::ParseUint;
using android::base::ReadFileToString;
using android::base::Split;
using android::base::StringPrintf;

namespace android {
namespace fs_mgr {

template <typename Hasher>
std::pair<size_t, bool> VerifyVbmetaDigest(const std::vector<VBMetaData>& vbmeta_images,
                                           const uint8_t* expected_digest) {
    size_t total_size = 0;
    Hasher hasher;
    for (const auto& vbmeta : vbmeta_images) {
        hasher.update(vbmeta.data(), vbmeta.size());
        total_size += vbmeta.size();
    }

    bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0);

    return std::make_pair(total_size, matched);
}

template <typename Hasher>
std::pair<std::string, size_t> CalculateVbmetaDigest(const std::vector<VBMetaData>& vbmeta_images) {
    std::string digest;
    size_t total_size = 0;

    Hasher hasher;
    for (const auto& vbmeta : vbmeta_images) {
        hasher.update(vbmeta.data(), vbmeta.size());
        total_size += vbmeta.size();
    }

    // Converts digest bytes to a hex string.
    digest = BytesToHex(hasher.finalize(), Hasher::DIGEST_SIZE);
    return std::make_pair(digest, total_size);
}

// class AvbVerifier
// -----------------
// Reads the following values from kernel cmdline and provides the
// VerifyVbmetaImages() to verify AvbSlotVerifyData.
//   - androidboot.vbmeta.hash_alg
//   - androidboot.vbmeta.size
//   - androidboot.vbmeta.digest
class AvbVerifier {
  public:
    // The factory method to return a unique_ptr<AvbVerifier>
    static std::unique_ptr<AvbVerifier> Create();
    bool VerifyVbmetaImages(const std::vector<VBMetaData>& vbmeta_images);

  protected:
    AvbVerifier() = default;

  private:
    HashAlgorithm hash_alg_;
    uint8_t digest_[SHA512_DIGEST_LENGTH];
    size_t vbmeta_size_;
};

std::unique_ptr<AvbVerifier> AvbVerifier::Create() {
    std::unique_ptr<AvbVerifier> avb_verifier(new AvbVerifier());
    if (!avb_verifier) {
        LERROR << "Failed to create unique_ptr<AvbVerifier>";
        return nullptr;
    }

    std::string value;
    if (!fs_mgr_get_boot_config("vbmeta.size", &value) ||
        !ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
        LERROR << "Invalid hash size: " << value.c_str();
        return nullptr;
    }

    // Reads hash algorithm.
    size_t expected_digest_size = 0;
    std::string hash_alg;
    fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg);
    if (hash_alg == "sha256") {
        expected_digest_size = SHA256_DIGEST_LENGTH * 2;
        avb_verifier->hash_alg_ = HashAlgorithm::kSHA256;
    } else if (hash_alg == "sha512") {
        expected_digest_size = SHA512_DIGEST_LENGTH * 2;
        avb_verifier->hash_alg_ = HashAlgorithm::kSHA512;
    } else {
        LERROR << "Unknown hash algorithm: " << hash_alg.c_str();
        return nullptr;
    }

    // Reads digest.
    std::string digest;
    fs_mgr_get_boot_config("vbmeta.digest", &digest);
    if (digest.size() != expected_digest_size) {
        LERROR << "Unexpected digest size: " << digest.size()
               << " (expected: " << expected_digest_size << ")";
        return nullptr;
    }

    if (!HexToBytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
        LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str();
        return nullptr;
    }

    return avb_verifier;
}

bool AvbVerifier::VerifyVbmetaImages(const std::vector<VBMetaData>& vbmeta_images) {
    if (vbmeta_images.empty()) {
        LERROR << "No vbmeta images";
        return false;
    }

    size_t total_size = 0;
    bool digest_matched = false;

    if (hash_alg_ == HashAlgorithm::kSHA256) {
        std::tie(total_size, digest_matched) =
                VerifyVbmetaDigest<SHA256Hasher>(vbmeta_images, digest_);
    } else if (hash_alg_ == HashAlgorithm::kSHA512) {
        std::tie(total_size, digest_matched) =
                VerifyVbmetaDigest<SHA512Hasher>(vbmeta_images, digest_);
    }

    if (total_size != vbmeta_size_) {
        LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_
               << ")";
        return false;
    }

    if (!digest_matched) {
        LERROR << "vbmeta digest mismatch";
        return false;
    }

    return true;
}

// class AvbHandle
// ---------------
AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(
        const std::string& partition_name, const std::string& ab_suffix,
        const std::string& ab_other_suffix, const std::string& expected_public_key_path,
        const HashAlgorithm& hash_algorithm, bool allow_verification_error,
        bool load_chained_vbmeta, bool rollback_protection,
        std::function<std::string(const std::string&)> custom_device_path) {
    AvbUniquePtr avb_handle(new AvbHandle());
    if (!avb_handle) {
        LERROR << "Failed to allocate AvbHandle";
        return nullptr;
    }

    std::string expected_key_blob;
    if (!expected_public_key_path.empty()) {
        if (access(expected_public_key_path.c_str(), F_OK) != 0) {
            LERROR << "Expected public key path doesn't exist: " << expected_public_key_path;
            return nullptr;
        } else if (!ReadFileToString(expected_public_key_path, &expected_key_blob)) {
            LERROR << "Failed to load: " << expected_public_key_path;
            return nullptr;
        }
    }

    auto android_by_name_symlink = [](const std::string& partition_name_with_ab) {
        return "/dev/block/by-name/" + partition_name_with_ab;
    };

    auto device_path = custom_device_path ? custom_device_path : android_by_name_symlink;

    auto verify_result = LoadAndVerifyVbmetaByPartition(
        partition_name, ab_suffix, ab_other_suffix, expected_key_blob, allow_verification_error,
        load_chained_vbmeta, rollback_protection, device_path, false,
        /* is_chained_vbmeta */ &avb_handle->vbmeta_images_);
    switch (verify_result) {
        case VBMetaVerifyResult::kSuccess:
            avb_handle->status_ = AvbHandleStatus::kSuccess;
            break;
        case VBMetaVerifyResult::kErrorVerification:
            avb_handle->status_ = AvbHandleStatus::kVerificationError;
            break;
        default:
            LERROR << "LoadAndVerifyVbmetaByPartition failed, result: " << verify_result;
            return nullptr;
    }

    // Validity check here because we have to use vbmeta_images_[0] below.
    if (avb_handle->vbmeta_images_.size() < 1) {
        LERROR << "LoadAndVerifyVbmetaByPartition failed, no vbmeta loaded";
        return nullptr;
    }

    // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
    avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);

    // Checks any disabled flag is set.
    std::unique_ptr<AvbVBMetaImageHeader> vbmeta_header =
            avb_handle->vbmeta_images_[0].GetVBMetaHeader();
    bool verification_disabled = ((AvbVBMetaImageFlags)vbmeta_header->flags &
                                  AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
    bool hashtree_disabled =
            ((AvbVBMetaImageFlags)vbmeta_header->flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
    if (verification_disabled) {
        avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
    } else if (hashtree_disabled) {
        avb_handle->status_ = AvbHandleStatus::kHashtreeDisabled;
    }

    // Calculates the summary info for all vbmeta_images_;
    std::string digest;
    size_t total_size;
    if (hash_algorithm == HashAlgorithm::kSHA256) {
        std::tie(digest, total_size) =
                CalculateVbmetaDigest<SHA256Hasher>(avb_handle->vbmeta_images_);
    } else if (hash_algorithm == HashAlgorithm::kSHA512) {
        std::tie(digest, total_size) =
                CalculateVbmetaDigest<SHA512Hasher>(avb_handle->vbmeta_images_);
    } else {
        LERROR << "Invalid hash algorithm";
        return nullptr;
    }
    avb_handle->vbmeta_info_ = VBMetaInfo(digest, hash_algorithm, total_size);

    LINFO << "Returning avb_handle with status: " << avb_handle->status_;
    return avb_handle;
}

static bool IsAvbPermissive() {
    if (IsDeviceUnlocked()) {
        // Manually putting a file under metadata partition can enforce AVB verification.
        if (!access(DSU_METADATA_PREFIX "avb_enforce", F_OK)) {
            LINFO << "Enforcing AVB verification when the device is unlocked";
            return false;
        }
        return true;
    }
    return false;
}

AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta(const FstabEntry& fstab_entry,
                                            const std::vector<std::string>& preload_avb_key_blobs) {
    // At least one of the following should be provided for public key matching.
    if (preload_avb_key_blobs.empty() && fstab_entry.avb_keys.empty()) {
        LERROR << "avb_keys=/path/to/key(s) is missing for " << fstab_entry.mount_point;
        return nullptr;
    }

    // Binds allow_verification_error and rollback_protection to device unlock state.
    bool allow_verification_error = IsAvbPermissive();
    bool rollback_protection = !allow_verification_error;

    std::string public_key_data;
    bool verification_disabled = false;
    VBMetaVerifyResult verify_result = VBMetaVerifyResult::kError;
    std::unique_ptr<VBMetaData> vbmeta = LoadAndVerifyVbmetaByPath(
            fstab_entry.blk_device, "" /* partition_name, no need for a standalone path */,
            "" /* expected_public_key_blob, */, allow_verification_error, rollback_protection,
            false /* not is_chained_vbmeta */, &public_key_data, &verification_disabled,
            &verify_result);

    if (!vbmeta) {
        LERROR << "Failed to load vbmeta: " << fstab_entry.blk_device;
        return nullptr;
    }

    AvbUniquePtr avb_handle(new AvbHandle());
    if (!avb_handle) {
        LERROR << "Failed to allocate AvbHandle";
        return nullptr;
    }
    avb_handle->vbmeta_images_.emplace_back(std::move(*vbmeta));

    switch (verify_result) {
        case VBMetaVerifyResult::kSuccess:
            avb_handle->status_ = AvbHandleStatus::kSuccess;
            break;
        case VBMetaVerifyResult::kErrorVerification:
            avb_handle->status_ = AvbHandleStatus::kVerificationError;
            break;
        default:
            LERROR << "LoadAndVerifyVbmetaByPath failed, result: " << verify_result;
            return nullptr;
    }

    bool public_key_match = false;
    // Performs key matching for preload_avb_key_blobs first, if it is present.
    if (!public_key_data.empty() && !preload_avb_key_blobs.empty()) {
        if (std::find(preload_avb_key_blobs.begin(), preload_avb_key_blobs.end(),
                      public_key_data) != preload_avb_key_blobs.end()) {
            public_key_match = true;
        }
    }
    // Performs key matching for fstab_entry.avb_keys if necessary.
    // Note that it is intentional to match both preload_avb_key_blobs and fstab_entry.avb_keys.
    // Some keys might only be availble before init chroots into /system, e.g., /avb/key1
    // in the first-stage ramdisk, while other keys might only be available after the chroot,
    // e.g., /system/etc/avb/key2.
    if (!public_key_data.empty() && !public_key_match) {
        // fstab_entry.avb_keys might be either a directory containing multiple keys,
        // or a string indicating multiple keys separated by ':'.
        std::vector<std::string> allowed_avb_keys;
        auto list_avb_keys_in_dir = ListFiles(fstab_entry.avb_keys);
        if (list_avb_keys_in_dir.ok()) {
            std::sort(list_avb_keys_in_dir->begin(), list_avb_keys_in_dir->end());
            allowed_avb_keys = *list_avb_keys_in_dir;
        } else {
            allowed_avb_keys = Split(fstab_entry.avb_keys, ":");
        }
        if (ValidatePublicKeyBlob(public_key_data, allowed_avb_keys)) {
            public_key_match = true;
        }
    }

    if (!public_key_match) {
        avb_handle->status_ = AvbHandleStatus::kVerificationError;
        LWARNING << "Found unknown public key used to sign " << fstab_entry.mount_point;
        if (!allow_verification_error) {
            LERROR << "Unknown public key is not allowed";
            return nullptr;
        }
    }

    if (verification_disabled) {
        LINFO << "AVB verification disabled on: " << fstab_entry.mount_point;
        avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
    }

    LINFO << "Returning avb_handle for '" << fstab_entry.mount_point
          << "' with status: " << avb_handle->status_;
    return avb_handle;
}

AvbUniquePtr AvbHandle::LoadAndVerifyVbmeta() {
    // Loads inline vbmeta images, starting from /vbmeta.
    return LoadAndVerifyVbmeta("vbmeta", fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix(),
                               {} /* expected_public_key, already checked by bootloader */,
                               HashAlgorithm::kSHA256,
                               IsAvbPermissive(), /* allow_verification_error */
                               true,              /* load_chained_vbmeta */
                               false, /* rollback_protection, already checked by bootloader */
                               nullptr /* custom_device_path */);
}

// TODO(b/128807537): removes this function.
AvbUniquePtr AvbHandle::Open() {
    bool allow_verification_error = IsAvbPermissive();

    AvbUniquePtr avb_handle(new AvbHandle());
    if (!avb_handle) {
        LERROR << "Failed to allocate AvbHandle";
        return nullptr;
    }

    FsManagerAvbOps avb_ops;
    AvbSlotVerifyFlags flags = allow_verification_error
                                       ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
                                       : AVB_SLOT_VERIFY_FLAGS_NONE;
    AvbSlotVerifyResult verify_result =
            avb_ops.AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->vbmeta_images_);

    // Only allow the following verify results:
    //   - AVB_SLOT_VERIFY_RESULT_OK.
    //   - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (UNLOCKED only).
    //     Might occur in either the top-level vbmeta or a chained vbmeta.
    //   - AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED (UNLOCKED only).
    //     Could only occur in a chained vbmeta. Because we have *no-op* operations in
    //     FsManagerAvbOps such that avb_ops->validate_vbmeta_public_key() used to validate
    //     the public key of the top-level vbmeta always pass in userspace here.
    //
    // The following verify result won't happen, because the *no-op* operation
    // avb_ops->read_rollback_index() always returns the minimum value zero. So rollbacked
    // vbmeta images, which should be caught in the bootloader stage, won't be detected here.
    //   - AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
    switch (verify_result) {
        case AVB_SLOT_VERIFY_RESULT_OK:
            avb_handle->status_ = AvbHandleStatus::kSuccess;
            break;
        case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION:
        case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED:
            if (!allow_verification_error) {
                LERROR << "ERROR_VERIFICATION / PUBLIC_KEY_REJECTED isn't allowed ";
                return nullptr;
            }
            avb_handle->status_ = AvbHandleStatus::kVerificationError;
            break;
        default:
            LERROR << "avb_slot_verify failed, result: " << verify_result;
            return nullptr;
    }

    // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
    avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);

    // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
    std::unique_ptr<AvbVerifier> avb_verifier = AvbVerifier::Create();
    if (!avb_verifier || !avb_verifier->VerifyVbmetaImages(avb_handle->vbmeta_images_)) {
        LERROR << "Failed to verify vbmeta digest";
        if (!allow_verification_error) {
            LERROR << "vbmeta digest error isn't allowed ";
            return nullptr;
        }
    }

    // Checks whether FLAGS_VERIFICATION_DISABLED is set:
    //   - Only the top-level vbmeta struct is read.
    //   - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s)
    //     and AVB HASHTREE descriptor(s).
    AvbVBMetaImageHeader vbmeta_header;
    avb_vbmeta_image_header_to_host_byte_order(
            (AvbVBMetaImageHeader*)avb_handle->vbmeta_images_[0].data(), &vbmeta_header);
    bool verification_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags &
                                  AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);

    // Checks whether FLAGS_HASHTREE_DISABLED is set.
    //   - vbmeta struct in all partitions are still processed, just disable
    //     dm-verity in the user space.
    bool hashtree_disabled =
            ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);

    if (verification_disabled) {
        avb_handle->status_ = AvbHandleStatus::kVerificationDisabled;
    } else if (hashtree_disabled) {
        avb_handle->status_ = AvbHandleStatus::kHashtreeDisabled;
    }

    LINFO << "Returning avb_handle with status: " << avb_handle->status_;
    return avb_handle;
}

AvbHashtreeResult AvbHandle::SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry,
                                                        bool wait_for_verity_dev) {
    auto avb_handle = LoadAndVerifyVbmeta(*fstab_entry);
    if (!avb_handle) {
        return AvbHashtreeResult::kFail;
    }

    return avb_handle->SetUpAvbHashtree(fstab_entry, wait_for_verity_dev);
}

AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait_for_verity_dev) {
    if (!fstab_entry || status_ == AvbHandleStatus::kUninitialized || vbmeta_images_.size() < 1) {
        return AvbHashtreeResult::kFail;
    }

    if (status_ == AvbHandleStatus::kHashtreeDisabled ||
        status_ == AvbHandleStatus::kVerificationDisabled) {
        LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point;
        return AvbHashtreeResult::kDisabled;
    }

    if (!LoadAvbHashtreeToEnableVerity(fstab_entry, wait_for_verity_dev, vbmeta_images_,
                                       fs_mgr_get_slot_suffix(), fs_mgr_get_other_slot_suffix())) {
        return AvbHashtreeResult::kFail;
    }

    return AvbHashtreeResult::kSuccess;
}

bool AvbHandle::TearDownAvbHashtree(FstabEntry* fstab_entry, bool wait) {
    if (!fstab_entry) {
        return false;
    }

    const std::string device_name(GetVerityDeviceName(*fstab_entry));

    // TODO: remove duplicated code with UnmapDevice()
    android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
    std::string path;
    if (wait) {
        dm.GetDmDevicePathByName(device_name, &path);
    }
    if (!dm.DeleteDevice(device_name)) {
        return false;
    }
    if (!path.empty() && !WaitForFile(path, 1000ms, FileWaitMode::DoesNotExist)) {
        return false;
    }

    return true;
}

std::string AvbHandle::GetSecurityPatchLevel(const FstabEntry& fstab_entry) const {
    if (vbmeta_images_.size() < 1) {
        return "";
    }
    std::string avb_partition_name = DeriveAvbPartitionName(fstab_entry, fs_mgr_get_slot_suffix(),
                                                            fs_mgr_get_other_slot_suffix());
    auto avb_prop_name = "com.android.build." + avb_partition_name + ".security_patch";
    return GetAvbPropertyDescriptor(avb_prop_name, vbmeta_images_);
}

bool AvbHandle::IsDeviceUnlocked() {
    return android::fs_mgr::IsDeviceUnlocked();
}

}  // namespace fs_mgr
}  // namespace android
