// Copyright 2017 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 <arpa/inet.h>
#include <crypto/bytes.h>
#include <crypto/cipher.h>
#include <crypto/hkdf.h>
#include <crypto/secret.h>
#include <errno.h>
#include <fbl/algorithm.h>
#include <fs-management/mount.h>
#include <inttypes.h>
#include <lib/zircon-internal/debug.h>
#include <stddef.h>
#include <stdint.h>
#include <zircon/compiler.h>
#include <zircon/device/block.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <zxcrypt/volume.h>

#define ZXDEBUG 0

namespace zxcrypt {

// Several copies of the metadata for a zxcrypt volume is saved at the beginning and end of the
// devices.  The number of copies is given by |kMetadataBlocks * kReservedSlices|, and the locations
// of each block can be iterated through using |Begin| and |Next|.  The metadata block, or
// superblock, consists of a fixed type GUID, an instance GUID, a 32-bit version, a set of "key
// slots"  The key slots are data cipher key material encrypted with a wrapping crypto::AEAD key
// derived from the caller-provided root key and specific slot.

// Determines what algorithms are in use when creating new zxcrypt devices.
const Volume::Version Volume::kDefaultVersion = Volume::kAES256_XTS_SHA256;

// The amount of data that can "in-flight" to the underlying block device before the zxcrypt
// driver begins queuing transactions
//
// TODO(aarongreen): See ZX-1616.  Tune this value.  Possibly break into several smaller VMOs if we
// want to allow some to be recycled; support for this doesn't currently exist. Up to 64 MB may be
// in flight at once.  The device's max_transfer_size will be capped at 1/4 of this value.
const uint32_t Volume::kBufferSize = 1U << 24;
static_assert(Volume::kBufferSize % PAGE_SIZE == 0, "kBufferSize must be page aligned");

namespace {

// The number of metadata blocks in a reserved metadata slice, each holding a copy of the
// superblock.
const size_t kMetadataBlocks = 2;

// HKDF labels
const size_t kMaxLabelLen = 16;
const char* kWrapKeyLabel = "wrap key %" PRIu64;
const char* kWrapIvLabel = "wrap iv %" PRIu64;

// Header is type GUID | instance GUID | version.
const size_t kHeaderLen = sizeof(zxcrypt_magic) + GUID_LEN + sizeof(uint32_t);

}  // namespace

Volume::Volume() { Reset(); }

Volume::~Volume() {}

void Volume::Reset() {
  reserved_blocks_ = 0;
  reserved_slices_ = 0;
  block_.Resize(0);
  offset_ = UINT64_MAX;
  guid_.Resize(0);
  header_.Resize(0);
  aead_ = crypto::AEAD::kUninitialized;
  wrap_key_.Clear();
  wrap_iv_.Resize(0);
  cipher_ = crypto::Cipher::kUninitialized;
  data_key_.Clear();
  data_iv_.Resize(0);
  slot_len_ = 0;
  num_key_slots_ = 0;
  digest_ = crypto::digest::kUninitialized;
}

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

  for (rc = Begin(); rc == ZX_ERR_NEXT; rc = Next()) {
    if ((rc = Read()) != ZX_OK) {
      xprintf("failed to read block at %" PRIu64 ": %d\n", offset_, rc);
    } else if ((rc = UnsealBlock(key, slot)) != ZX_OK) {
      xprintf("failed to open block at %" PRIu64 ": %d\n", offset_, rc);
    } else {
      return ZX_OK;
    }
  }

  return ZX_ERR_ACCESS_DENIED;
}

zx_status_t Volume::Shred() {
  zx_status_t rc;

  if (!block_.get()) {
    xprintf("not initialized\n");
    return ZX_ERR_BAD_STATE;
  }
  if ((rc = block_.Randomize()) != ZX_OK) {
    return rc;
  }
  for (rc = Begin(); rc == ZX_ERR_NEXT; rc = Next()) {
    if ((rc = Write()) != ZX_OK) {
      return rc;
    }
  }
  Reset();

  return ZX_OK;
}

zx_status_t Volume::GetSlotOffset(key_slot_t slot, zx_off_t* out) const {
  if (!block_.get()) {
    xprintf("not initialized\n");
    return ZX_ERR_BAD_STATE;
  }

  zx_off_t off;
  if (mul_overflow(slot, slot_len_, &off) || add_overflow(kHeaderLen, off, &off) ||
      off > block_.len() - slot_len_) {
    xprintf("bad key slot: %" PRIu64 "\n", slot);
    return ZX_ERR_INVALID_ARGS;
  }

  if (out) {
    *out = off;
  }
  return ZX_OK;
}

zx_status_t Volume::Init() {
  zx_status_t rc;

  // Get block info; align our blocks to pages
  BlockInfo blk;
  if ((rc = GetBlockInfo(&blk)) != ZX_OK) {
    xprintf("failed to get block info: %s\n", zx_status_get_string(rc));
    return rc;
  }
  // Check that we meet the minimum size.
  if (blk.block_count < kMetadataBlocks) {
    xprintf("device is too small; have %" PRIu64 " blocks, need %" PRIu64 "\n", blk.block_count,
            kMetadataBlocks);
    return ZX_ERR_NOT_SUPPORTED;
  }
  reserved_blocks_ = kMetadataBlocks;
  // Allocate block buffer
  if ((rc = block_.Resize(blk.block_size)) != ZX_OK) {
    return rc;
  }
  // Get FVM info
  uint64_t fvm_slice_size;
  switch ((rc = GetFvmSliceSize(&fvm_slice_size))) {
    case ZX_OK: {
      // This *IS* an FVM partition.
      // Ensure first kReservedSlices + 1 slices are allocated
      size_t blocks_per_slice = fvm_slice_size / blk.block_size;
      reserved_blocks_ = fbl::round_up(reserved_blocks_, blocks_per_slice);
      reserved_slices_ = reserved_blocks_ / blocks_per_slice;
      size_t required = reserved_slices_ + 1;
      size_t range = 1;
      for (size_t i = 0; i < required; i += range) {
        // Ask about the next contiguous range
        SliceRegion ranges[MAX_SLICE_REGIONS];
        uint64_t slice_count;
        if ((rc = DoBlockFvmVsliceQuery(i + 1, ranges, &slice_count)) != ZX_OK ||
            slice_count == 0 || ((range = ranges[0].count) == 0)) {
          xprintf("FVM Vslice Query failed: %s\n", zx_status_get_string(rc));
          return rc;
        }
        // If already allocated, continue
        if (ranges[0].allocated) {
          continue;
        };
        // Otherwise, allocate it
        uint64_t extend_start_slice = i + 1;
        uint64_t extend_length = fbl::min(required - i, range);

        if ((rc = DoBlockFvmExtend(extend_start_slice, extend_length)) != ZX_OK) {
          xprintf("failed to extend FVM partition: %s\n", zx_status_get_string(rc));
          return rc;
        }
      }
      break;
    }
    case ZX_ERR_NOT_SUPPORTED:
      // This is *NOT* an FVM partition.
      xprintf("Not an FVM partition\n");
      break;
    default:
      xprintf("init failed: %s\n", zx_status_get_string(rc));
      // An error occurred
      return rc;
  }

  return ZX_OK;
}

zx_status_t Volume::Configure(Volume::Version version) {
  zx_status_t rc;

  switch (version) {
    case Volume::kAES256_XTS_SHA256:
      aead_ = crypto::AEAD::kAES128_GCM_SIV;
      cipher_ = crypto::Cipher::kAES256_XTS;
      digest_ = crypto::digest::kSHA256;
      break;

    default:
      xprintf("unknown version: %u\n", version);
      return ZX_ERR_NOT_SUPPORTED;
  }

  size_t key_len, iv_len, tag_len;
  if ((rc = crypto::Cipher::GetKeyLen(cipher_, &key_len)) != ZX_OK ||
      (rc = crypto::Cipher::GetIVLen(cipher_, &iv_len)) != ZX_OK ||
      (rc = crypto::AEAD::GetTagLen(aead_, &tag_len)) != ZX_OK) {
    return rc;
  }

  slot_len_ = key_len + iv_len + tag_len;
  num_key_slots_ = (block_.len() - kHeaderLen) / slot_len_;
  if (num_key_slots_ == 0) {
    xprintf("block size is too small; have %zu, need %zu\n", block_.len(), kHeaderLen + slot_len_);
    return ZX_ERR_NOT_SUPPORTED;
  }

  return ZX_OK;
}

zx_status_t Volume::DeriveSlotKeys(const crypto::Secret& key, key_slot_t slot) {
  zx_status_t rc;

  crypto::HKDF hkdf;
  char label[kMaxLabelLen];

  // We tolerate 128-bit keys here because some hardware we wish to operate on
  // only has 128-bits of random keys in hardware.  We believe that this
  // entropy is sufficient for our purposes.
  size_t key_len = key.len();
  if (key_len == 16) {
    rc = hkdf.Init(digest_, key, guid_, crypto::HKDF::ALLOW_WEAK_KEY);
  } else if (key_len == 32) {
    rc = hkdf.Init(digest_, key, guid_);
  } else {
    xprintf("invalid key length %lu (acceptable values are 16, 32)\n", key_len);
    return ZX_ERR_INVALID_ARGS;
  }
  if (rc != ZX_OK) {
    xprintf("hkdf.Init failed %s\n", zx_status_get_string(rc));
    return rc;
  }
  snprintf(label, kMaxLabelLen, kWrapKeyLabel, slot);
  size_t len;
  if ((rc = crypto::AEAD::GetKeyLen(aead_, &len)) != ZX_OK ||
      (rc = hkdf.Derive(label, len, &wrap_key_)) != ZX_OK) {
    xprintf("failed to derive wrap key: %s\n", zx_status_get_string(rc));
    return rc;
  }
  snprintf(label, kMaxLabelLen, kWrapIvLabel, slot);
  crypto::Secret wrap_iv;
  if ((rc = crypto::AEAD::GetIVLen(aead_, &len)) != ZX_OK ||
      (rc = hkdf.Derive(label, len, &wrap_iv_)) != ZX_OK) {
    xprintf("failed to derive wrap IV: %s\n", zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

// Block methods

zx_status_t Volume::Begin() {
  offset_ = 0;
  return ZX_ERR_NEXT;
}

zx_status_t Volume::Next() {
  offset_ += block_.len();
  return (offset_ / block_.len()) < kMetadataBlocks ? ZX_ERR_NEXT : ZX_ERR_STOP;
}

zx_status_t Volume::CreateBlock() {
  zx_status_t rc;

  // Create a "backdrop" of random data
  if ((rc = block_.Randomize()) != ZX_OK) {
    return rc;
  }

  // Write the variant 1/version 1 type GUID according to RFC 4122.
  // TODO(aarongreen): ZX-2106.  This and other magic numbers should be moved to a public/zircon
  // header, and the dependency removed.
  uint8_t* out = block_.get();
  memcpy(out, zxcrypt_magic, sizeof(zxcrypt_magic));
  out += sizeof(zxcrypt_magic);

  // Create a variant 1/version 4 instance GUID according to RFC 4122.
  if ((rc = guid_.Randomize(GUID_LEN)) != ZX_OK) {
    return rc;
  }
  guid_[6] = (guid_[6] & 0x0F) | 0x40;
  guid_[8] = (guid_[8] & 0x3F) | 0x80;
  memcpy(out, guid_.get(), GUID_LEN);
  out += GUID_LEN;

  // Write the 32-bit version.
  if ((rc = Configure(kDefaultVersion)) != ZX_OK) {
    return rc;
  }
  uint32_t version = htonl(kDefaultVersion);
  memcpy(out, &version, sizeof(version));

  // Generate the data key and IV, and save the AAD.
  size_t key_len, iv_len;
  if ((rc = crypto::Cipher::GetKeyLen(cipher_, &key_len)) != ZX_OK ||
      (rc = crypto::Cipher::GetIVLen(cipher_, &iv_len)) != ZX_OK ||
      (rc = data_key_.Generate(key_len)) != ZX_OK || (rc = data_iv_.Resize(iv_len)) != ZX_OK ||
      (rc = data_iv_.Randomize()) != ZX_OK ||
      (rc = header_.Copy(block_.get(), kHeaderLen)) != ZX_OK) {
    return rc;
  }

  return ZX_OK;
}

zx_status_t Volume::CommitBlock() {
  zx_status_t rc;

  // Make a copy to compare the read result to; this reduces the number of
  // writes we must do.
  crypto::Bytes block;
  if ((rc = block.Copy(block_)) != ZX_OK) {
    xprintf("zxcrypt: Cannot copy block: %s\n", zx_status_get_string(rc));
    return rc;
  }
  for (rc = Begin(); rc == ZX_ERR_NEXT; rc = Next()) {
    if ((rc = Read()) != ZX_OK) {
      xprintf("zxcrypt: CommitBlock Read failed: %s\n", zx_status_get_string(rc));
      return rc;
    }
    // Only write back blocks that don't match.
    if (block_ == block) {
      continue;
    }
    if ((rc = block_.Copy(block)) != ZX_OK || (rc = Write()) != ZX_OK) {
      xprintf("zxcrypt: CommitBlock Write failed for offset %" PRIu64 ": %s\n", offset_,
              zx_status_get_string(rc));
    }
  }
  return ZX_OK;
}

zx_status_t Volume::SealBlock(const crypto::Secret& key, key_slot_t slot) {
  zx_status_t rc;

  // Encrypt the data key
  zx_off_t nonce;
  crypto::AEAD aead;
  crypto::Bytes ptext, ctext;
  zx_off_t off;
  zx_off_t data_key_off = 0;
  zx_off_t data_iv_off = data_key_.len();
  if ((rc = GetSlotOffset(slot, &off)) != ZX_OK) {
    xprintf("GetSlotOffset for slot %" PRIu64 " failed: %s\n", slot, zx_status_get_string(rc));
    return rc;
  }
  if ((rc = ptext.Copy(data_key_.get(), data_key_.len(), data_key_off)) != ZX_OK) {
    xprintf("ptext.Copy (key) failed: %s", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = ptext.Copy(data_iv_.get(), data_iv_.len(), data_iv_off)) != ZX_OK) {
    xprintf("ptext.Copy (iv) failed: %s", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = DeriveSlotKeys(key, slot)) != ZX_OK) {
    xprintf("DeriveSlotKeys failed: %s", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = aead.InitSeal(aead_, wrap_key_, wrap_iv_)) != ZX_OK) {
    xprintf("aead.InitSeal failed: %s", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = aead.Seal(ptext, header_, &nonce, &ctext)) != ZX_OK) {
    xprintf("aead.Seal failed: %s", zx_status_get_string(rc));
    return rc;
  }
  // Check that we'll be able to unseal.
  if (memcmp(&nonce, wrap_iv_.get(), sizeof(nonce)) != 0) {
    xprintf("unexpected nonce: %" PRIu64 "\n", nonce);
    return ZX_ERR_INTERNAL;
  }

  memcpy(block_.get() + off, ctext.get(), ctext.len());
  return ZX_OK;
}

zx_status_t Volume::UnsealBlock(const crypto::Secret& key, key_slot_t slot) {
  zx_status_t rc;

  // Check the type GUID matches |kTypeGuid|.
  const uint8_t* in = block_.get();
  if (memcmp(in, zxcrypt_magic, sizeof(zxcrypt_magic)) != 0) {
    xprintf("not a zxcrypt device\n");
    return ZX_ERR_NOT_SUPPORTED;
  }
  in += sizeof(zxcrypt_magic);

  // Save the instance GUID
  if ((rc = guid_.Copy(in, GUID_LEN)) != ZX_OK) {
    return rc;
  }
  in += GUID_LEN;

  // Read the version
  uint32_t version;
  memcpy(&version, in, sizeof(version));
  in += sizeof(version);

  // Read in the data
  zx_off_t off;
  size_t key_len, iv_len;
  uint8_t* key_buf;
  crypto::AEAD aead;
  crypto::Bytes ctext, ptext;
  if ((rc = Configure(Version(ntohl(version)))) != ZX_OK) {
    xprintf("Configure failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = GetSlotOffset(slot, &off)) != ZX_OK) {
    xprintf("GetSlotOffset failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = DeriveSlotKeys(key, slot)) != ZX_OK) {
    xprintf("DeriveSlotKeys failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = crypto::Cipher::GetKeyLen(cipher_, &key_len)) != ZX_OK) {
    xprintf("Cipher::GetKeyLen failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = crypto::Cipher::GetIVLen(cipher_, &iv_len)) != ZX_OK) {
    xprintf("Cipher::GetIVLen failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = data_key_.Allocate(key_len, &key_buf)) != ZX_OK) {
    xprintf("Secret::Allocate failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = ctext.Copy(block_.get() + off, slot_len_)) != ZX_OK) {
    xprintf("ctext.Copy failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = aead.InitOpen(aead_, wrap_key_, wrap_iv_)) != ZX_OK) {
    xprintf("aead.InitOpen failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = header_.Copy(block_.get(), kHeaderLen)) != ZX_OK) {
    xprintf("header_.Copy failed: %s\n", zx_status_get_string(rc));
    return rc;
  }

  // Extract nonce from IV.
  zx_off_t nonce;
  memcpy(&nonce, wrap_iv_.get(), sizeof(nonce));
  if ((rc = aead.Open(nonce, ctext, header_, &ptext)) != ZX_OK) {
    xprintf("aead.Open failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = data_iv_.Copy(ptext.get() + key_len, iv_len)) != ZX_OK) {
    xprintf("data_iv_.Copy failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  memcpy(key_buf, ptext.get(), key_len);

  return ZX_OK;
}

}  // namespace zxcrypt
