// Copyright 2020 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/block-verity/block-verifier.h"

#include <lib/fit/defer.h>
#include <lib/zx/vmar.h>
#include <zircon/assert.h>
#include <zircon/status.h>

#include <fbl/auto_lock.h>

#include "src/devices/block/drivers/block-verity/block-loader-interface.h"
#include "src/devices/block/drivers/block-verity/constants.h"
#include "src/devices/block/drivers/block-verity/geometry.h"
#include "src/lib/digest/digest.h"

namespace block_verity {
namespace {

static void IntegrityBlockCallback(void* cookie, zx_status_t status) {
  BlockVerifier* verifier = static_cast<BlockVerifier*>(cookie);
  verifier->OnIntegrityDataLoaded(status);
}

}  // namespace

BlockVerifier::BlockVerifier(const Geometry& geometry,
                             const std::array<uint8_t, kHashOutputSize>& integrity_root_hash,
                             BlockLoaderInterface* block_loader)
    : block_loader_(block_loader),
      geometry_(geometry),
      state_(kInitial),
      root_hash_(integrity_root_hash) {}

BlockVerifier::~BlockVerifier() {
  // Unmap the vmo from the vmar.
  if (integrity_block_base_ == nullptr) {
    return;
  }
  uintptr_t address = reinterpret_cast<uintptr_t>(integrity_block_base_);
  integrity_block_base_ = nullptr;
  // Ignore unmap failures; we're destructing anyway
  zx::vmar::root_self()->unmap(address, GetIntegritySectionSizeInBytes());
}

zx_status_t BlockVerifier::PrepareAsync(void* cookie, BlockVerifierCallback callback) {
  {
    // Scoped so we don't hold mtx_ while calling LoadIntegrityBlocks.
    fbl::AutoLock lock(&mtx_);

    ZX_ASSERT(state_ == kInitial);

    // Allocate and map a VMO for block operations
    zx_status_t rc;
    if ((rc = zx::vmo::create(GetIntegritySectionSizeInBytes(), 0, &integrity_block_vmo_)) !=
        ZX_OK) {
      return rc;
    }
    auto cleanup = fit::defer([this]() { integrity_block_vmo_.reset(); });
    constexpr uint32_t flags = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE;
    uintptr_t address;
    if ((rc = zx::vmar::root_self()->map(flags, 0, integrity_block_vmo_, 0,
                                         GetIntegritySectionSizeInBytes(), &address)) != ZX_OK) {
      return rc;
    }
    integrity_block_base_ = reinterpret_cast<const uint8_t*>(address);
    cleanup.cancel();

    cookie_ = cookie;
    callback_ = callback;
    state_ = kLoading;
  }
  LoadIntegrityBlocks();

  return ZX_OK;
}

void BlockVerifier::LoadIntegrityBlocks() {
  uint64_t integrity_start_block = geometry_.AbsoluteLocationForIntegrity(0);
  uint64_t integrity_block_count = geometry_.allocation_.integrity_shape.integrity_block_count;
  block_loader_->RequestBlocks(integrity_start_block, integrity_block_count, integrity_block_vmo_,
                               this, IntegrityBlockCallback);
}

void BlockVerifier::OnIntegrityDataLoaded(zx_status_t status) {
  {
    fbl::AutoLock lock(&mtx_);
    ZX_ASSERT(state_ == kLoading);
    if (status == ZX_OK) {
      state_ = kReady;
    } else {
      state_ = kFailed;
    }
  }

  callback_(cookie_, status);
}

uint64_t BlockVerifier::GetIntegritySectionSizeInBytes() const {
  return geometry_.allocation_.integrity_shape.integrity_block_count * kBlockSize;
}

const uint8_t* BlockVerifier::MemoryLocationForHash(HashLocation h) const {
  uint64_t offset = (h.integrity_block * kBlockSize) + (h.hash_in_block * kHashOutputSize);
  return integrity_block_base_ + offset;
}

const uint8_t* BlockVerifier::MemoryLocationForBlock(IntegrityBlockIndex i) const {
  uint64_t offset = i * kBlockSize;
  return integrity_block_base_ + offset;
}

zx_status_t BlockVerifier::VerifyDataBlockSync(uint64_t data_block_index,
                                               const uint8_t* block_data) {
  {
    // Since `kReady` is a terminal state, we can release the lock as soon as
    // we're done checking state.
    fbl::AutoLock lock(&mtx_);
    if (state_ != kReady) {
      return ZX_ERR_BAD_STATE;
    }
  }

  digest::Digest hasher;
  hasher.Hash(block_data, kBlockSize);

  // Check that the data block matches the hash in the leaf integrity block.
  HashLocation leaf_hash_location = geometry_.IntegrityDataLocationForDataBlock(data_block_index);
  const uint8_t* leaf_integrity_range = MemoryLocationForHash(leaf_hash_location);
  if (!hasher.Equals(leaf_integrity_range, kHashOutputSize)) {
    return ZX_ERR_IO_DATA_INTEGRITY;
  }

  // Future performance improvement: make this cache successfully-hashed
  // indirect integrity blocks rather than rehashing to the root every time.
  uint32_t distance_from_leaf = 0;
  HashLocation previous = leaf_hash_location;
  while (distance_from_leaf < geometry_.allocation_.integrity_shape.tree_depth - 1) {
    // Get address of containing block.  Hash it.
    const uint8_t* containing_block = MemoryLocationForBlock(previous.integrity_block);
    hasher.Hash(containing_block, kBlockSize);

    HashLocation up_one =
        geometry_.NextIntegrityBlockUp(distance_from_leaf, previous.integrity_block);
    if (!hasher.Equals(MemoryLocationForHash(up_one), kHashOutputSize)) {
      return ZX_ERR_IO_DATA_INTEGRITY;
    }

    previous = up_one;
    distance_from_leaf++;
  }

  // Validate the root hash.  By now the last integrity range we checked
  // should have been in the final integrity block, which is the root integrity
  // block.
  ZX_ASSERT(previous.integrity_block ==
            geometry_.allocation_.integrity_shape.integrity_block_count - 1);

  const uint8_t* root_integrity_block = MemoryLocationForBlock(previous.integrity_block);
  hasher.Hash(root_integrity_block, kBlockSize);
  if (!hasher.Equals(root_hash_.data(), kHashOutputSize)) {
    return ZX_ERR_IO_DATA_INTEGRITY;
  }

  return ZX_OK;
}

}  // namespace block_verity
