/*
 * Copyright (C) 2019 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.
 */
#define LOG_TAG "apexd"

#include "apexd_verity.h"

#include <filesystem>
#include <vector>

#include <android-base/file.h>
#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <verity/hash_tree_builder.h>

#include "apex_file.h"
#include "apexd_loop.h"
#include "apexd_utils.h"
#include "string_log.h"

namespace fs = std::filesystem;
using android::base::ErrnoError;
using android::base::Error;
using android::base::ReadFully;
using android::base::Result;
using android::base::unique_fd;

namespace android {
namespace apex {

namespace {

const fs::path kHashTreeDir{"/data/apex/hashtree"};

uint8_t HexToBin(char h) {
  if (h >= 'A' && h <= 'H') return h - 'A' + 10;
  if (h >= 'a' && h <= 'h') return h - 'a' + 10;
  return h - '0';
}

std::vector<uint8_t> HexToBin(const std::string& hex) {
  std::vector<uint8_t> bin;
  bin.reserve(hex.size() / 2);
  for (size_t i = 0; i + 1 < hex.size(); i += 2) {
    uint8_t c = (HexToBin(hex[i]) << 4) + HexToBin(hex[i + 1]);
    bin.push_back(c);
  }
  return bin;
}

Result<void> GenerateHashTree(const ApexFile& apex,
                              const ApexVerityData& verity_data,
                              const std::string& hashtree_file) {
  unique_fd fd(TEMP_FAILURE_RETRY(open(apex.GetPath().c_str(), O_RDONLY)));
  if (fd.get() == -1) {
    return ErrnoError() << "Failed to open " << apex.GetPath();
  }

  auto block_size = verity_data.desc->hash_block_size;
  auto image_size = verity_data.desc->image_size;

  auto hash_fn = HashTreeBuilder::HashFunction(verity_data.hash_algorithm);
  if (hash_fn == nullptr) {
    return Error() << "Unsupported hash algorithm "
                   << verity_data.hash_algorithm;
  }

  auto builder = std::make_unique<HashTreeBuilder>(block_size, hash_fn);
  if (!builder->Initialize(image_size, HexToBin(verity_data.salt))) {
    return Error() << "Invalid image size " << image_size;
  }

  if (lseek(fd, apex.GetImageOffset(), SEEK_SET) == -1) {
    return ErrnoError() << "Failed to seek";
  }

  auto block_count = image_size / block_size;
  auto buf = std::vector<uint8_t>(block_size);
  while (block_count-- > 0) {
    if (!ReadFully(fd, buf.data(), block_size)) {
      return Error() << "Failed to read";
    }
    if (!builder->Update(buf.data(), block_size)) {
      return Error() << "Failed to build hashtree: Update";
    }
  }
  if (!builder->BuildHashTree()) {
    return Error() << "Failed to build hashtree: incomplete data";
  }

  auto golden_digest = HexToBin(verity_data.root_digest);
  auto digest = builder->root_hash();
  // This returns zero-padded digest.
  // resize() it to compare with golden digest,
  digest.resize(golden_digest.size());
  if (digest != golden_digest) {
    return Error() << "Failed to build hashtree: root digest mismatch";
  }

  unique_fd out_fd(TEMP_FAILURE_RETRY(
      open(hashtree_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0600)));
  if (!builder->WriteHashTreeToFd(out_fd, 0)) {
    return Error() << "Failed to write hashtree to " << hashtree_file;
  }
  return {};
}

}  // namespace

// Returns loop device of hashtree.
// If image payload has an embedded hash tree, then returns <empty> loop device
Result<loop::LoopbackDeviceUniqueFd> GetHashTree(
    const ApexFile& apex, const ApexVerityData& verity_data) {
  if (auto st = createDirIfNeeded(kHashTreeDir, 0700); !st) {
    return st.error();
  }

  // TODO(b/120058143): proper hashtree filename for an apex file
  // what if different apex files have same packageId(name@ver)
  // TODO(b/120058143): check if existing hastree is tampered by comparing
  // root digests. If they don't match, need to regenerate.
  auto hash_path = kHashTreeDir / GetPackageId(apex.GetManifest());
  auto exists = PathExists(hash_path);
  if (!exists) {
    return exists.error();
  }
  if (!*exists ||
      fs::last_write_time(apex.GetPath()) > fs::last_write_time(hash_path)) {
    if (auto st = GenerateHashTree(apex, verity_data, hash_path); !st) {
      return st.error();
    }
    LOG(INFO) << "hashtree: generated to " << hash_path;
  } else {
    LOG(INFO) << "hashtree: reuse " << hash_path;
  }

  return loop::createLoopDevice(hash_path, 0, 0);
}

void RemoveObsoleteHashTrees() {
  // TODO(b/120058143): on boot complete, remove unused hashtree files
}

}  // namespace apex
}  // namespace android