/*
 * 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) {
  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) {
  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) {
  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) {
  // 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) {
  base::FilePath path =
      partition_dir_.Append(std::string(partition)).AddExtension("img");

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