// Copyright 2018 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/devices/block/drivers/zxcrypt/worker.h"

#include <inttypes.h>
#include <lib/ddk/debug.h>
#include <lib/fit/defer.h>
#include <lib/trace/event.h>
#include <lib/zircon-internal/align.h>
#include <lib/zx/port.h>
#include <stddef.h>
#include <stdint.h>
#include <threads.h>
#include <zircon/listnode.h>
#include <zircon/status.h>
#include <zircon/syscalls/port.h>
#include <zircon/types.h>

#include <utility>

#include "src/devices/block/drivers/zxcrypt/debug.h"
#include "src/devices/block/drivers/zxcrypt/device.h"
#include "src/devices/block/drivers/zxcrypt/extra.h"
#include "src/devices/block/drivers/zxcrypt/queue.h"
#include "src/security/lib/fcrypto/cipher.h"
#include "src/security/lib/zxcrypt/ddk-volume.h"
#include "src/security/lib/zxcrypt/volume.h"

namespace zxcrypt {

Worker::Worker() : device_(nullptr), started_(false) { LOG_ENTRY(); }

Worker::~Worker() {
  LOG_ENTRY();
  ZX_DEBUG_ASSERT(!started_.load());
}

zx_status_t Worker::Start(Device* device, const DdkVolume& volume, Queue<block_op_t*>& queue) {
  LOG_ENTRY_ARGS("device=%p, volume=%p, queue=%p", device, &volume, &queue);
  zx_status_t rc;

  if (!device) {
    zxlogf(ERROR, "bad parameters: device=%p", device);
    return ZX_ERR_INVALID_ARGS;
  }
  device_ = device;

  if ((rc = volume.Bind(crypto::Cipher::kEncrypt, &encrypt_)) != ZX_OK ||
      (rc = volume.Bind(crypto::Cipher::kDecrypt, &decrypt_)) != ZX_OK) {
    zxlogf(ERROR, "failed to bind ciphers: %s", zx_status_get_string(rc));
    return rc;
  }

  queue_ = &queue;

  if (thrd_create_with_name(&thrd_, WorkerRun, this, "zxcrypt_worker") != thrd_success) {
    zxlogf(ERROR, "failed to start thread");
    return ZX_ERR_INTERNAL;
  }

  started_.store(true);
  return ZX_OK;
}

zx_status_t Worker::Run() {
  LOG_ENTRY();
  ZX_DEBUG_ASSERT(device_);

  for (;;) {
    block_op_t* block;
    if (auto block_or = queue_->Pop()) {
      block = *block_or;
    } else {
      zxlogf(DEBUG, "worker %p stopping.", this);
      return ZX_OK;
    }

    TRACE_DURATION("zxcrypt", "zxcrypt::Worker::Dispatch");

    // Dispatch block request
    switch (block->command.opcode) {
      case BLOCK_OPCODE_WRITE:
        device_->BlockForward(block, EncryptWrite(block));
        break;

      case BLOCK_OPCODE_READ:
        device_->BlockComplete(block, DecryptRead(block));
        break;

      default:
        device_->BlockComplete(block, ZX_ERR_NOT_SUPPORTED);
    }
  }
}

zx_status_t Worker::EncryptWrite(block_op_t* block) {
  LOG_ENTRY_ARGS("block=%p", block);
  zx_status_t rc;

  // Convert blocks to bytes
  extra_op_t* extra = BlockToExtra(block, device_->op_size());
  uint32_t length;
  uint64_t offset_dev, offset_vmo;
  if (mul_overflow(block->rw.length, device_->block_size(), &length) ||
      mul_overflow(block->rw.offset_dev, device_->block_size(), &offset_dev) ||
      mul_overflow(extra->offset_vmo, device_->block_size(), &offset_vmo)) {
    zxlogf(ERROR, "overflow; length=%" PRIu32 "; offset_dev=%" PRIu64 "; offset_vmo=%" PRIu64 "",
           block->rw.length, block->rw.offset_dev, extra->offset_vmo);
    return ZX_ERR_OUT_OF_RANGE;
  }

  TRACE_DURATION("zxcrypt", "zxcrypt::Worker::EncryptWrite", "len", length);

  // Copy and encrypt the plaintext
  if ((rc = zx_vmo_read(extra->vmo, extra->data, offset_vmo, length)) != ZX_OK) {
    zxlogf(ERROR, "zx_vmo_read() failed: %s", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = encrypt_.Encrypt(extra->data, offset_dev, length, extra->data) != ZX_OK)) {
    zxlogf(ERROR, "failed to encrypt: %s", zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

zx_status_t Worker::DecryptRead(block_op_t* block) {
  LOG_ENTRY_ARGS("block=%p", block);
  zx_status_t rc;

  // Convert blocks to bytes
  uint32_t length;
  uint64_t offset_dev, offset_vmo;
  uint64_t mapping_offset = 0;
  if (mul_overflow(block->rw.length, device_->block_size(), &length) ||
      mul_overflow(block->rw.offset_dev, device_->block_size(), &offset_dev) ||
      mul_overflow(block->rw.offset_vmo, device_->block_size(), &offset_vmo)) {
    zxlogf(ERROR, "overflow; length=%" PRIu32 "; offset_dev=%" PRIu64 "; offset_vmo=%" PRIu64 "",
           block->rw.length, block->rw.offset_dev, block->rw.offset_vmo);
    return ZX_ERR_OUT_OF_RANGE;
  }
  uint32_t aligned_length = length;

  TRACE_DURATION("zxcrypt", "zxcrypt::Worker::DecryptRead", "len", length);

  const size_t kPageSize = zx_system_get_page_size();

  if (ZX_ROUNDDOWN(offset_vmo, kPageSize) != offset_vmo) {
    // Ensure the range inside the VMO we map is page aligned so that requests smaller than a page
    // still work.
    mapping_offset = offset_vmo - ZX_ROUNDDOWN(offset_vmo, kPageSize);
    offset_vmo = ZX_ROUNDDOWN(offset_vmo, kPageSize);
    aligned_length += mapping_offset;
  }

  // Map the ciphertext
  zx_handle_t root = zx_vmar_root_self();
  uintptr_t address;
  constexpr uint32_t flags = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE;
  if ((rc = zx_vmar_map(root, flags, 0, block->rw.vmo, offset_vmo, aligned_length, &address)) !=
      ZX_OK) {
    zxlogf(ERROR, "zx::vmar::root_self()->map() failed: %s", zx_status_get_string(rc));
    return rc;
  }
  auto cleanup = fit::defer(
      [root, address, aligned_length]() { zx_vmar_unmap(root, address, aligned_length); });

  // Decrypt in place
  uint8_t* data = reinterpret_cast<uint8_t*>(address + mapping_offset);
  if ((rc = decrypt_.Decrypt(data, offset_dev, length, data)) != ZX_OK) {
    zxlogf(ERROR, "failed to decrypt: %s", zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

zx_status_t Worker::Stop() {
  LOG_ENTRY();
  zx_status_t rc;

  // Only join once per call to |Start|.
  if (!started_.exchange(false)) {
    return ZX_OK;
  }
  thrd_join(thrd_, &rc);

  if (rc != ZX_OK) {
    zxlogf(WARNING, "worker exited with error: %s", zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

}  // namespace zxcrypt
