// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/security/lib/zxcrypt/fdio-volume.h"

#include <errno.h>
#include <fidl/fuchsia.hardware.block.encrypted/cpp/wire.h>
#include <fidl/fuchsia.hardware.block.volume/cpp/wire.h>
#include <fidl/fuchsia.hardware.block/cpp/wire.h>
#include <inttypes.h>
#include <lib/component/incoming/cpp/clone.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/zircon-internal/debug.h>
#include <lib/zx/channel.h>
#include <unistd.h>
#include <zircon/status.h>

#include <memory>
#include <utility>

#include <fbl/string_buffer.h>
#include <fbl/vector.h>

#include "src/security/lib/zxcrypt/volume.h"
#include "src/storage/lib/block_client/cpp/remote_block_device.h"

#define ZXDEBUG 0

namespace zxcrypt {

FdioVolume::FdioVolume(fidl::ClientEnd<fuchsia_hardware_block_volume::Volume> channel)
    : device_(std::move(channel)) {}

zx::result<std::unique_ptr<FdioVolume>> FdioVolume::Init(
    fidl::ClientEnd<fuchsia_hardware_block_volume::Volume> channel) {
  if (!channel) {
    xprintf("bad parameter(s): block=%d\n", channel.channel().get());
    return zx::error(ZX_ERR_INVALID_ARGS);
  }

  fbl::AllocChecker ac;
  std::unique_ptr<FdioVolume> volume(new (&ac) FdioVolume(std::move(channel)));
  if (!ac.check()) {
    xprintf("allocation failed: %zu bytes\n", sizeof(FdioVolume));
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  if (zx_status_t status = volume->Init(); status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(std::move(volume));
}

zx::result<std::unique_ptr<FdioVolume>> FdioVolume::Create(
    fidl::ClientEnd<fuchsia_hardware_block_volume::Volume> channel, const crypto::Secret& key) {
  zx::result volume = Init(std::move(channel));
  if (volume.is_error()) {
    xprintf("Init failed: %s\n", volume.status_string());
    return volume.take_error();
  }

  uint8_t slot = 0;
  if (zx_status_t status = volume.value()->Format(key, slot); status != ZX_OK) {
    xprintf("Format failed: %s\n", zx_status_get_string(status));
    return zx::error(status);
  }
  return volume;
}

zx::result<std::unique_ptr<FdioVolume>> FdioVolume::Unlock(
    fidl::ClientEnd<fuchsia_hardware_block_volume::Volume> channel, const crypto::Secret& key,
    key_slot_t slot) {
  zx::result volume = Init(std::move(channel));
  if (volume.is_error()) {
    xprintf("Init failed: %s\n", volume.status_string());
    return volume.take_error();
  }
  if (zx_status_t status = volume.value()->Unlock(key, slot); status != ZX_OK) {
    xprintf("Unlock failed: %s\n", zx_status_get_string(status));
    return zx::error(status);
  }
  return volume;
}

zx_status_t FdioVolume::Unlock(const crypto::Secret& key, key_slot_t slot) {
  return Volume::Unlock(key, slot);
}

// Configuration methods
zx_status_t FdioVolume::Enroll(const crypto::Secret& key, key_slot_t slot) {
  if (zx_status_t status = SealBlock(key, slot); status != ZX_OK) {
    xprintf("SealBlock failed: %s\n", zx_status_get_string(status));
    return status;
  }
  if (zx_status_t status = CommitBlock(); status != ZX_OK) {
    xprintf("CommitBlock failed: %s\n", zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}

zx_status_t FdioVolume::Revoke(key_slot_t slot) {
  zx_off_t off;
  crypto::Bytes invalid;
  if (zx_status_t status = GetSlotOffset(slot, &off); status != ZX_OK) {
    xprintf("GetSlotOffset failed: %s\n", zx_status_get_string(status));
    return status;
  }
  if (zx_status_t status = invalid.Randomize(slot_len_); status != ZX_OK) {
    xprintf("Randomize failed: %s\n", zx_status_get_string(status));
    return status;
  }
  if (zx_status_t status = block_.Copy(invalid, off); status != ZX_OK) {
    xprintf("Copy failed: %s\n", zx_status_get_string(status));
    return status;
  }
  if (zx_status_t status = CommitBlock(); status != ZX_OK) {
    xprintf("CommitBlock failed: %s\n", zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}

zx_status_t FdioVolume::Init() { return Volume::Init(); }

zx_status_t FdioVolume::GetBlockInfo(BlockInfo* out) {
  const fidl::WireResult result = fidl::WireCall(device_)->GetInfo();
  if (!result.ok()) {
    return result.status();
  }
  const fit::result response = result.value();
  if (response.is_error()) {
    return response.error_value();
  }

  out->block_count = response.value()->info.block_count;
  out->block_size = response.value()->info.block_size;
  return ZX_OK;
}

zx_status_t FdioVolume::GetFvmSliceSize(uint64_t* out) {
  const fidl::WireResult result = fidl::WireCall(device_)->GetVolumeInfo();
  if (!result.ok()) {
    return result.status();
  }
  const fidl::WireResponse response = result.value();
  if (response.status != ZX_OK) {
    return response.status;
  }

  *out = response.manager->slice_size;
  return ZX_OK;
}

zx_status_t FdioVolume::DoBlockFvmVsliceQuery(uint64_t vslice_start,
                                              SliceRegion ranges[Volume::MAX_SLICE_REGIONS],
                                              uint64_t* slice_count) {
  static_assert(fuchsia_hardware_block_volume::wire::kMaxSliceRequests == Volume::MAX_SLICE_REGIONS,
                "block volume slice response count must match");

  const fidl::WireResult result = fidl::WireCall(device_)->QuerySlices(
      fidl::VectorView<uint64_t>::FromExternal(&vslice_start, 1));
  if (!result.ok()) {
    return result.status();
  }
  const fidl::WireResponse response = result.value();
  if (response.status != ZX_OK) {
    return response.status;
  }

  if (response.response_count > Volume::MAX_SLICE_REGIONS) {
    // Should be impossible.  Trust nothing.
    return ZX_ERR_BAD_STATE;
  }

  *slice_count = response.response_count;
  for (size_t i = 0; i < response.response_count; i++) {
    ranges[i].allocated = response.response[i].allocated;
    ranges[i].count = response.response[i].count;
  }

  return ZX_OK;
}

zx_status_t FdioVolume::DoBlockFvmExtend(uint64_t start_slice, uint64_t slice_count) {
  const fidl::WireResult result = fidl::WireCall(device_)->Extend(start_slice, slice_count);
  if (!result.ok()) {
    return result.status();
  }
  const fidl::WireResponse response = result.value();
  if (response.status != ZX_OK) {
    return response.status;
  }

  return ZX_OK;
}

zx_status_t FdioVolume::Read() {
  // TODO(https://fxbug.dev/42080299): Update this API to take a volume channel instead.
  return block_client::SingleReadBytes(
      fidl::UnownedClientEnd<fuchsia_hardware_block::Block>(device_.channel().borrow()),
      block_.get(), block_.len(), offset_);
}

zx_status_t FdioVolume::Write() {
  // TODO(https://fxbug.dev/42080299): Update this API to take a volume channel instead.
  return block_client::SingleWriteBytes(
      fidl::UnownedClientEnd<fuchsia_hardware_block::Block>(device_.channel().borrow()),
      block_.get(), block_.len(), offset_);
}

zx_status_t FdioVolume::Flush() {
  // On Fuchsia, an FD produced by opening a block device out of the device tree doesn't implement
  // fsync(), so we stub this out.  FdioVolume is only used for tests anyway, which don't need to
  // worry too much about durability.
  return ZX_OK;
}

}  // namespace zxcrypt
