/*
 * 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 <iostream>

#include <endian.h>
#include <errno.h>
#include <inttypes.h>
#include <string.h>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <openssl/rand.h>
#include <openssl/sha.h>

#include "fake_avb_ops.h"

namespace avb {

std::set<std::string> FakeAvbOps::get_partition_names_read_from() {
  return partition_names_read_from_;
}

bool FakeAvbOps::preload_partition(const std::string& partition,
                                   const base::FilePath& path) {
  if (preloaded_partitions_.count(partition) > 0) {
    fprintf(stderr, "Partition '%s' already preloaded\n", partition.c_str());
    return false;
  }

  int64_t file_size;
  if (!base::GetFileSize(path, &file_size)) {
    fprintf(stderr, "Error getting size of file '%s'\n", path.value().c_str());
    return false;
  }

  int fd = open(path.value().c_str(), O_RDONLY);
  if (fd < 0) {
    fprintf(stderr,
            "Error opening file '%s': %s\n",
            path.value().c_str(),
            strerror(errno));
    return false;
  }

  uint8_t* buffer = static_cast<uint8_t*>(malloc(file_size));
  ssize_t num_read = read(fd, buffer, file_size);
  if (num_read != file_size) {
    fprintf(stderr,
            "Error reading %zd bytes from file '%s': %s\n",
            file_size,
            path.value().c_str(),
            strerror(errno));
    free(buffer);
    return false;
  }
  close(fd);

  preloaded_partitions_[partition] = buffer;
  return true;
}

AvbIOResult FakeAvbOps::read_from_partition(const char* partition,
                                            int64_t offset,
                                            size_t num_bytes,
                                            void* buffer,
                                            size_t* out_num_read) {
  if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  }

  base::FilePath path =
      partition_dir_.Append(std::string(partition)).AddExtension("img");

  partition_names_read_from_.insert(partition);

  if (offset < 0) {
    int64_t file_size;
    if (!base::GetFileSize(path, &file_size)) {
      fprintf(
          stderr, "Error getting size of file '%s'\n", path.value().c_str());
      return AVB_IO_RESULT_ERROR_IO;
    }
    offset = file_size - (-offset);
  }

  int fd = open(path.value().c_str(), O_RDONLY);
  if (fd < 0) {
    fprintf(stderr,
            "Error opening file '%s': %s\n",
            path.value().c_str(),
            strerror(errno));
    if (errno == ENOENT) {
      return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
    } else {
      return AVB_IO_RESULT_ERROR_IO;
    }
  }
  if (lseek(fd, offset, SEEK_SET) != offset) {
    fprintf(stderr,
            "Error seeking to pos %zd in file %s: %s\n",
            offset,
            path.value().c_str(),
            strerror(errno));
    close(fd);
    return AVB_IO_RESULT_ERROR_IO;
  }
  ssize_t num_read = read(fd, buffer, num_bytes);
  if (num_read < 0) {
    fprintf(stderr,
            "Error reading %zd bytes from pos %" PRId64 " in file %s: %s\n",
            num_bytes,
            offset,
            path.value().c_str(),
            strerror(errno));
    close(fd);
    return AVB_IO_RESULT_ERROR_IO;
  }
  close(fd);

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

  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::get_preloaded_partition(
    const char* partition,
    size_t num_bytes,
    uint8_t** out_pointer,
    size_t* out_num_bytes_preloaded) {
  if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  }
  std::map<std::string, uint8_t*>::iterator it =
      preloaded_partitions_.find(std::string(partition));
  if (it == preloaded_partitions_.end()) {
    *out_pointer = NULL;
    *out_num_bytes_preloaded = 0;
    return AVB_IO_RESULT_OK;
  }

  uint64_t size;
  AvbIOResult result = get_size_of_partition(avb_ops(), partition, &size);
  if (result != AVB_IO_RESULT_OK) {
    return result;
  }
  if (size != num_bytes) {
    return AVB_IO_RESULT_ERROR_IO;
  }

  *out_num_bytes_preloaded = num_bytes;
  *out_pointer = it->second;
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::write_to_partition(const char* partition,
                                           int64_t offset,
                                           size_t num_bytes,
                                           const void* buffer) {
  if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  }

  base::FilePath path =
      partition_dir_.Append(std::string(partition)).AddExtension("img");

  if (offset < 0) {
    int64_t file_size;
    if (!base::GetFileSize(path, &file_size)) {
      fprintf(
          stderr, "Error getting size of file '%s'\n", path.value().c_str());
      return AVB_IO_RESULT_ERROR_IO;
    }
    offset = file_size - (-offset);
  }

  int fd = open(path.value().c_str(), O_WRONLY);
  if (fd < 0) {
    fprintf(stderr,
            "Error opening file '%s': %s\n",
            path.value().c_str(),
            strerror(errno));
    if (errno == ENOENT) {
      return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
    } else {
      return AVB_IO_RESULT_ERROR_IO;
    }
  }
  if (lseek(fd, offset, SEEK_SET) != offset) {
    fprintf(stderr,
            "Error seeking to pos %zd in file %s: %s\n",
            offset,
            path.value().c_str(),
            strerror(errno));
    close(fd);
    return AVB_IO_RESULT_ERROR_IO;
  }
  ssize_t num_written = write(fd, buffer, num_bytes);
  if (num_written < 0) {
    fprintf(stderr,
            "Error writing %zd bytes at pos %" PRId64 " in file %s: %s\n",
            num_bytes,
            offset,
            path.value().c_str(),
            strerror(errno));
    close(fd);
    return AVB_IO_RESULT_ERROR_IO;
  }
  close(fd);

  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::validate_vbmeta_public_key(
    AvbOps* ops,
    const uint8_t* public_key_data,
    size_t public_key_length,
    const uint8_t* public_key_metadata,
    size_t public_key_metadata_length,
    bool* out_key_is_trusted) {
  if (out_key_is_trusted != NULL) {
    bool pk_matches = (public_key_length == expected_public_key_.size() &&
                       (memcmp(expected_public_key_.c_str(),
                               public_key_data,
                               public_key_length) == 0));
    bool pkmd_matches =
        (public_key_metadata_length == expected_public_key_metadata_.size() &&
         (memcmp(expected_public_key_metadata_.c_str(),
                 public_key_metadata,
                 public_key_metadata_length) == 0));
    *out_key_is_trusted = pk_matches && pkmd_matches;
  }
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops,
                                            size_t rollback_index_location,
                                            uint64_t* out_rollback_index) {
  if (stored_rollback_indexes_.count(rollback_index_location) == 0) {
    fprintf(stderr,
            "No rollback index for location %zd (has %zd locations).\n",
            rollback_index_location,
            stored_rollback_indexes_.size());
    return AVB_IO_RESULT_ERROR_IO;
  }
  *out_rollback_index = stored_rollback_indexes_[rollback_index_location];
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::write_rollback_index(AvbOps* ops,
                                             size_t rollback_index_location,
                                             uint64_t rollback_index) {
  if (stored_rollback_indexes_.count(rollback_index_location) == 0) {
    fprintf(stderr,
            "No rollback index for location %zd (has %zd locations).\n",
            rollback_index_location,
            stored_rollback_indexes_.size());
    return AVB_IO_RESULT_ERROR_IO;
  }
  stored_rollback_indexes_[rollback_index_location] = rollback_index;
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::read_is_device_unlocked(AvbOps* ops,
                                                bool* out_is_device_unlocked) {
  *out_is_device_unlocked = stored_is_device_unlocked_ ? 1 : 0;
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::get_unique_guid_for_partition(AvbOps* ops,
                                                      const char* partition,
                                                      char* guid_buf,
                                                      size_t guid_buf_size) {
  if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  }
  // This is faking it a bit but makes testing easy. It works
  // because avb_slot_verify.c doesn't check that the returned GUID
  // is wellformed.
  snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::get_size_of_partition(AvbOps* ops,
                                              const char* partition,
                                              uint64_t* out_size) {
  if (hidden_partitions_.find(partition) != hidden_partitions_.end()) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  }

  base::FilePath path =
      partition_dir_.Append(std::string(partition)).AddExtension("img");

  int64_t file_size;
  if (!base::GetFileSize(path, &file_size)) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
  }
  *out_size = file_size;
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::read_persistent_value(const char* name,
                                              size_t buffer_size,
                                              uint8_t* out_buffer,
                                              size_t* out_num_bytes_read) {
  if (out_buffer == NULL && buffer_size > 0) {
    return AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE;
  }
  if (stored_values_.count(name) == 0) {
    return AVB_IO_RESULT_ERROR_NO_SUCH_VALUE;
  }
  if (stored_values_[name].size() > buffer_size) {
    *out_num_bytes_read = stored_values_[name].size();
    return AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE;
  }
  memcpy(out_buffer, stored_values_[name].data(), stored_values_[name].size());
  *out_num_bytes_read = stored_values_[name].size();
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::write_persistent_value(const char* name,
                                               size_t value_size,
                                               const uint8_t* value) {
  stored_values_[name] =
      std::string(reinterpret_cast<const char*>(value), value_size);
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::read_permanent_attributes(
    AvbAtxPermanentAttributes* attributes) {
  *attributes = permanent_attributes_;
  return AVB_IO_RESULT_OK;
}

AvbIOResult FakeAvbOps::read_permanent_attributes_hash(
    uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
  if (permanent_attributes_hash_.empty()) {
    SHA256(reinterpret_cast<const unsigned char*>(&permanent_attributes_),
           sizeof(AvbAtxPermanentAttributes),
           hash);
    return AVB_IO_RESULT_OK;
  }
  memset(hash, 0, AVB_SHA256_DIGEST_SIZE);
  permanent_attributes_hash_.copy(reinterpret_cast<char*>(hash),
                                  AVB_SHA256_DIGEST_SIZE);
  return AVB_IO_RESULT_OK;
}

void FakeAvbOps::set_key_version(size_t rollback_index_location,
                                 uint64_t key_version) {
  verified_rollback_indexes_[rollback_index_location] = key_version;
}

AvbIOResult FakeAvbOps::get_random(size_t num_bytes, uint8_t* output) {
  if (!RAND_bytes(output, num_bytes)) {
    return AVB_IO_RESULT_ERROR_IO;
  }
  return AVB_IO_RESULT_OK;
}

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

static AvbIOResult my_ops_get_preloaded_partition(
    AvbOps* ops,
    const char* partition,
    size_t num_bytes,
    uint8_t** out_pointer,
    size_t* out_num_bytes_preloaded) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->get_preloaded_partition(
          partition, num_bytes, out_pointer, out_num_bytes_preloaded);
}

static AvbIOResult my_ops_write_to_partition(AvbOps* ops,
                                             const char* partition,
                                             int64_t offset,
                                             size_t num_bytes,
                                             const void* buffer) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)->delegate()->write_to_partition(
      partition, offset, num_bytes, buffer);
}

static AvbIOResult my_ops_validate_vbmeta_public_key(
    AvbOps* ops,
    const uint8_t* public_key_data,
    size_t public_key_length,
    const uint8_t* public_key_metadata,
    size_t public_key_metadata_length,
    bool* out_key_is_trusted) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->validate_vbmeta_public_key(ops,
                                   public_key_data,
                                   public_key_length,
                                   public_key_metadata,
                                   public_key_metadata_length,
                                   out_key_is_trusted);
}

static AvbIOResult my_ops_read_rollback_index(AvbOps* ops,
                                              size_t rollback_index_location,
                                              uint64_t* out_rollback_index) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->read_rollback_index(ops, rollback_index_location, out_rollback_index);
}

static AvbIOResult my_ops_write_rollback_index(AvbOps* ops,
                                               size_t rollback_index_location,
                                               uint64_t rollback_index) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->write_rollback_index(ops, rollback_index_location, rollback_index);
}

static AvbIOResult my_ops_read_is_device_unlocked(
    AvbOps* ops, bool* out_is_device_unlocked) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->read_is_device_unlocked(ops, out_is_device_unlocked);
}

static AvbIOResult my_ops_get_unique_guid_for_partition(AvbOps* ops,
                                                        const char* partition,
                                                        char* guid_buf,
                                                        size_t guid_buf_size) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->get_unique_guid_for_partition(ops, partition, guid_buf, guid_buf_size);
}

static AvbIOResult my_ops_get_size_of_partition(AvbOps* ops,
                                                const char* partition,
                                                uint64_t* out_size) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->get_size_of_partition(ops, partition, out_size);
}

static AvbIOResult my_ops_read_persistent_value(AvbOps* ops,
                                                const char* name,
                                                size_t buffer_size,
                                                uint8_t* out_buffer,
                                                size_t* out_num_bytes_read) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->read_persistent_value(
          name, buffer_size, out_buffer, out_num_bytes_read);
}

static AvbIOResult my_ops_write_persistent_value(AvbOps* ops,
                                                 const char* name,
                                                 size_t value_size,
                                                 const uint8_t* value) {
  return FakeAvbOps::GetInstanceFromAvbOps(ops)
      ->delegate()
      ->write_persistent_value(name, value_size, value);
}

static AvbIOResult my_ops_read_permanent_attributes(
    AvbAtxOps* atx_ops, AvbAtxPermanentAttributes* attributes) {
  return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
      ->delegate()
      ->read_permanent_attributes(attributes);
}

static AvbIOResult my_ops_read_permanent_attributes_hash(
    AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]) {
  return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
      ->delegate()
      ->read_permanent_attributes_hash(hash);
}

static void my_ops_set_key_version(AvbAtxOps* atx_ops,
                                   size_t rollback_index_location,
                                   uint64_t key_version) {
  return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
      ->delegate()
      ->set_key_version(rollback_index_location, key_version);
}

static AvbIOResult my_ops_get_random(AvbAtxOps* atx_ops,
                                     size_t num_bytes,
                                     uint8_t* output) {
  return FakeAvbOps::GetInstanceFromAvbOps(atx_ops->ops)
      ->delegate()
      ->get_random(num_bytes, output);
}

FakeAvbOps::FakeAvbOps() {
  memset(&avb_ops_, 0, sizeof(avb_ops_));
  avb_ops_.ab_ops = &avb_ab_ops_;
  avb_ops_.atx_ops = &avb_atx_ops_;
  avb_ops_.user_data = this;
  avb_ops_.read_from_partition = my_ops_read_from_partition;
  avb_ops_.write_to_partition = my_ops_write_to_partition;
  avb_ops_.validate_vbmeta_public_key = my_ops_validate_vbmeta_public_key;
  avb_ops_.read_rollback_index = my_ops_read_rollback_index;
  avb_ops_.write_rollback_index = my_ops_write_rollback_index;
  avb_ops_.read_is_device_unlocked = my_ops_read_is_device_unlocked;
  avb_ops_.get_unique_guid_for_partition = my_ops_get_unique_guid_for_partition;
  avb_ops_.get_size_of_partition = my_ops_get_size_of_partition;
  avb_ops_.read_persistent_value = my_ops_read_persistent_value;
  avb_ops_.write_persistent_value = my_ops_write_persistent_value;

  // Just use the built-in A/B metadata read/write routines.
  avb_ab_ops_.ops = &avb_ops_;
  avb_ab_ops_.read_ab_metadata = avb_ab_data_read;
  avb_ab_ops_.write_ab_metadata = avb_ab_data_write;

  avb_atx_ops_.ops = &avb_ops_;
  avb_atx_ops_.read_permanent_attributes = my_ops_read_permanent_attributes;
  avb_atx_ops_.read_permanent_attributes_hash =
      my_ops_read_permanent_attributes_hash;
  avb_atx_ops_.set_key_version = my_ops_set_key_version;
  avb_atx_ops_.get_random = my_ops_get_random;

  delegate_ = this;
}

FakeAvbOps::~FakeAvbOps() {
  std::map<std::string, uint8_t*>::iterator it;
  for (it = preloaded_partitions_.begin(); it != preloaded_partitions_.end();
       it++) {
    free(it->second);
  }
}

void FakeAvbOps::enable_get_preloaded_partition() {
  avb_ops_.get_preloaded_partition = my_ops_get_preloaded_partition;
}

}  // namespace avb
