// 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 <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

#include <crypto/bytes.h>
#include <crypto/cipher.h>
#include <crypto/hkdf.h>
#include <crypto/secret.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/block.h>
#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/macros.h>
#include <fbl/string_buffer.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <fs-management/mount.h>
#include <fs-management/ramdisk.h>
#include <lib/fdio/debug.h>
#include <lib/zx/vmo.h>
#include <lib/sync/completion.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 zxcrypt driver
const char* kDriverLib = "/boot/driver/zxcrypt.so";

// 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);

void SyncComplete(block_op_t* block, zx_status_t status) {
    // Use the 32bit command field to shuttle the response back to the callsite that's waiting on
    // the completion
    block->command = status;
    sync_completion_signal(static_cast<sync_completion_t*>(block->cookie));
}

// Performs synchronous I/O
zx_status_t SyncIO(zx_device_t* dev, uint32_t cmd, void* buf, size_t off, size_t len) {
    zx_status_t rc;

    if (!dev || !buf || len == 0) {
        xprintf("bad parameter(s): dev=%p, buf=%p, len=%zu\n", dev, buf, len);
        return ZX_ERR_INVALID_ARGS;
    }

    block_protocol_t proto;
    if ((rc = device_get_protocol(dev, ZX_PROTOCOL_BLOCK, &proto)) != ZX_OK) {
        xprintf("block protocol not support\n");
        return ZX_ERR_NOT_SUPPORTED;
    }

    zx::vmo vmo;
    if ((rc = zx::vmo::create(len, 0, &vmo)) != ZX_OK) {
        xprintf("zx::vmo::create failed: %s\n", zx_status_get_string(rc));
        return rc;
    }

    block_info_t info;
    size_t op_size;
    proto.ops->query(proto.ctx, &info, &op_size);

    size_t bsz = info.block_size;
    ZX_DEBUG_ASSERT(off / bsz <= UINT32_MAX);
    ZX_DEBUG_ASSERT(len / bsz <= UINT32_MAX);

    char raw[op_size];
    block_op_t* block = reinterpret_cast<block_op_t*>(raw);

    sync_completion_t completion;
    sync_completion_reset(&completion);

    block->command = cmd;
    block->rw.vmo = vmo.get();
    block->rw.length = static_cast<uint32_t>(len / bsz);
    block->rw.offset_dev = static_cast<uint32_t>(off / bsz);
    block->rw.offset_vmo = 0;
    block->rw.pages = nullptr;
    block->completion_cb = SyncComplete;
    block->cookie = &completion;

    if (cmd == BLOCK_OP_WRITE && (rc = vmo.write(buf, 0, len)) != ZX_OK) {
        xprintf("zx::vmo::write failed: %s\n", zx_status_get_string(rc));
        return rc;
    }

    proto.ops->queue(proto.ctx, block);
    sync_completion_wait(&completion, ZX_TIME_INFINITE);

    rc = block->command;
    if (rc != ZX_OK) {
        xprintf("Block I/O failed: %s\n", zx_status_get_string(rc));
        return rc;
    }

    if (cmd == BLOCK_OP_READ && (rc = vmo.read(buf, 0, len)) != ZX_OK) {
        xprintf("zx::vmo::read failed: %s\n", zx_status_get_string(rc));
        return rc;
    }

    return ZX_OK;
}

} // namespace

Volume::~Volume() {}

// Library methods

zx_status_t Volume::Init(fbl::unique_fd fd, fbl::unique_ptr<Volume>* out) {
    zx_status_t rc;

    if (!fd || !out) {
        xprintf("bad parameter(s): fd=%d, out=%p\n", fd.get(), out);
        return ZX_ERR_INVALID_ARGS;
    }

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

    if ((rc = volume->Init()) != ZX_OK) {
        return rc;
    }

    *out = fbl::move(volume);
    return ZX_OK;
}

zx_status_t Volume::Create(fbl::unique_fd fd, const crypto::Secret& key,
                           fbl::unique_ptr<Volume>* out) {
    zx_status_t rc;

    fbl::unique_ptr<Volume> volume;
    if ((rc = Volume::Init(fbl::move(fd), &volume)) != ZX_OK ||
        (rc = volume->CreateBlock()) != ZX_OK ||
        (rc = volume->SealBlock(key, 0)) != ZX_OK || (rc = volume->CommitBlock()) != ZX_OK) {
        return rc;
    }

    if (out) {
        *out = fbl::move(volume);
    }
    return ZX_OK;
}

zx_status_t Volume::Unlock(fbl::unique_fd fd, const crypto::Secret& key, key_slot_t slot,
                           fbl::unique_ptr<Volume>* out) {
    zx_status_t rc;

    fbl::unique_ptr<Volume> volume;
    if ((rc = Volume::Init(fbl::move(fd), &volume)) != ZX_OK ||
        (rc = volume->Unseal(key, slot)) != ZX_OK) {
        return rc;
    }

    *out = fbl::move(volume);
    return ZX_OK;
}

zx_status_t Volume::Open(const zx::duration& timeout, fbl::unique_fd* out) {
    zx_status_t rc;
    ssize_t res;

    // Get the full device path
    fbl::StringBuffer<PATH_MAX> path;
    path.Resize(path.capacity());
    if ((res = ioctl_device_get_topo_path(fd_.get(), path.data(), path.capacity())) < 0) {
        rc = static_cast<zx_status_t>(res);
        xprintf("could not find parent device: %s\n", zx_status_get_string(rc));
        return rc;
    }
    path.Resize(strlen(path.c_str()));
    path.Append("/zxcrypt/block");

    // Early return if already bound
    fbl::unique_fd fd(open(path.c_str(), O_RDWR));
    if (fd) {
        out->reset(fd.release());
        return ZX_OK;
    }

    // Bind the device
    if ((res = ioctl_device_bind(fd_.get(), kDriverLib, strlen(kDriverLib))) < 0) {
        rc = static_cast<zx_status_t>(res);
        xprintf("could not bind zxcrypt driver: %s\n", zx_status_get_string(rc));
        return rc;
    }
    if ((rc = wait_for_device(path.c_str(), timeout.get())) != ZX_OK) {
        xprintf("zxcrypt driver failed to bind: %s\n", zx_status_get_string(rc));
        return rc;
    }
    fd.reset(open(path.c_str(), O_RDWR));
    if (!fd) {
        xprintf("failed to open zxcrypt volume\n");
        return ZX_ERR_NOT_FOUND;
    }

    out->reset(fd.release());
    return ZX_OK;
}

zx_status_t Volume::Enroll(const crypto::Secret& key, key_slot_t slot) {
    zx_status_t rc;
    ZX_DEBUG_ASSERT(!dev_); // Cannot enroll from driver

    if (!block_.get()) {
        xprintf("not initialized\n");
        return ZX_ERR_BAD_STATE;
    }
    if (slot >= num_key_slots_) {
        xprintf("bad parameter(s): slot=%" PRIu64 "\n", slot);
        return ZX_ERR_INVALID_ARGS;
    }
    if ((rc = SealBlock(key, slot)) != ZX_OK || (rc = CommitBlock()) != ZX_OK) {
        return rc;
    }

    return ZX_OK;
}

zx_status_t Volume::Revoke(key_slot_t slot) {
    zx_status_t rc;
    ZX_DEBUG_ASSERT(!dev_); // Cannot revoke from driver

    if (!block_.get()) {
        xprintf("not initialized\n");
        return ZX_ERR_BAD_STATE;
    }
    if (slot >= num_key_slots_) {
        xprintf("bad parameter(s): slot=%" PRIu64 "\n", slot);
        return ZX_ERR_INVALID_ARGS;
    }
    zx_off_t off = kHeaderLen + (slot_len_ * slot);
    crypto::Bytes invalid;
    if ((rc = invalid.Randomize(slot_len_)) != ZX_OK || (rc = block_.Copy(invalid, off)) != ZX_OK ||
        (rc = CommitBlock()) != ZX_OK) {
        return rc;
    }

    return ZX_OK;
}

zx_status_t Volume::Shred() {
    zx_status_t rc;
    ZX_DEBUG_ASSERT(!dev_); // Cannot shred from driver

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

// Driver methods

zx_status_t Volume::Unlock(zx_device_t* dev, const crypto::Secret& key, key_slot_t slot,
                           fbl::unique_ptr<Volume>* out) {
    zx_status_t rc;

    if (!dev || !out) {
        xprintf("bad parameter(s): dev=%p, out=%p\n", dev, out);
        return ZX_ERR_INVALID_ARGS;
    }
    fbl::AllocChecker ac;
    fbl::unique_ptr<Volume> volume(new (&ac) Volume(dev));
    if (!ac.check()) {
        xprintf("allocation failed: %zu bytes\n", sizeof(Volume));
        return ZX_ERR_NO_MEMORY;
    }
    if ((rc = volume->Init()) != ZX_OK || (rc = volume->Unseal(key, slot)) != ZX_OK) {
        return rc;
    }

    *out = fbl::move(volume);
    return ZX_OK;
}

zx_status_t Volume::Bind(crypto::Cipher::Direction direction, crypto::Cipher* cipher) const {
    zx_status_t rc;
    ZX_DEBUG_ASSERT(dev_); // Cannot bind from library

    if (!cipher) {
        xprintf("bad parameter(s): cipher=%p\n", cipher);
        return ZX_ERR_INVALID_ARGS;
    }
    if (!block_.get()) {
        xprintf("not initialized\n");
        return ZX_ERR_BAD_STATE;
    }
    if ((rc = cipher->Init(cipher_, direction, data_key_, data_iv_, block_.len())) != ZX_OK) {
        return rc;
    }

    return ZX_OK;
}

// Private methods

Volume::Volume(fbl::unique_fd&& fd) {
    Reset();
    fd_ = fbl::move(fd);
}

Volume::Volume(zx_device_t* dev) {
    Reset();
    dev_ = dev;
}

// Configuration methods

zx_status_t Volume::Init() {
    zx_status_t rc;

    // Get block info; align our blocks to pages
    block_info_t blk;
    if ((rc = Ioctl(IOCTL_BLOCK_GET_INFO, nullptr, 0, &blk, sizeof(blk))) < 0) {
        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
    fvm_info_t fvm;
    switch ((rc = Ioctl(IOCTL_BLOCK_FVM_QUERY, nullptr, 0, &fvm, sizeof(fvm)))) {
    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;
        query_request_t request;
        query_response_t response;
        extend_request_t extend;
        for (size_t i = 0; i < required; i += range) {
            // Ask about the next contiguous range
            request.count = 1;
            request.vslice_start[0] = i + 1;
            if ((rc = Ioctl(IOCTL_BLOCK_FVM_VSLICE_QUERY, &request, sizeof(request), &response,
                            sizeof(response))) < 0 ||
                response.count == 0 || (range = response.vslice_range[0].count) == 0) {
                xprintf("ioctl_block_fvm_vslice_query failed: %s\n", zx_status_get_string(rc));
                return rc;
            }
            // If already allocated, continue
            if (response.vslice_range[0].allocated) {
                continue;
            };
            // Otherwise, allocate it
            extend.offset = i + 1;
            extend.length = fbl::min(required - i, range);
            if ((rc = Ioctl(IOCTL_BLOCK_FVM_EXTEND, &extend, sizeof(extend), nullptr, 0)) < 0) {
                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.
        break;
    default:
        // 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 ||
        (rc = crypto::digest::GetDigestLen(digest_, &digest_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];
    if ((rc = hkdf.Init(digest_, key, guid_)) != ZX_OK) {
        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;
}

void Volume::Reset() {
    dev_ = nullptr;
    fd_.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;
    digest_len_ = 0;
}

// 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) {
        return rc;
    }
    for (rc = Begin(); rc == ZX_ERR_NEXT; rc = Next()) {
        // Only write back blocks that don't match
        if (Read() == ZX_OK && block_ == block) {
            continue;
        }
        if ((rc = block_.Copy(block)) != ZX_OK || (rc = Write()) != ZX_OK) {
            xprintf("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;

    if (slot >= num_key_slots_) {
        xprintf("bad key slot: %" PRIu64 "\n", slot);
        return ZX_ERR_OUT_OF_RANGE;
    }

    // Encrypt the data key
    zx_off_t nonce;
    crypto::AEAD aead;
    crypto::Bytes ptext, ctext;
    zx_off_t off = kHeaderLen + (slot_len_ * slot);
    zx_off_t data_key_off = 0;
    zx_off_t data_iv_off = data_key_.len();
    if ((rc = ptext.Copy(data_key_.get(), data_key_.len(), data_key_off)) != ZX_OK ||
        (rc = ptext.Copy(data_iv_.get(), data_iv_.len(), data_iv_off)) != ZX_OK ||
        (rc = DeriveSlotKeys(key, slot)) != ZX_OK ||
        (rc = aead.InitSeal(aead_, wrap_key_, wrap_iv_)) != ZX_OK ||
        (rc = aead.Seal(ptext, header_, &nonce, &ctext)) != ZX_OK) {
        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::Unseal(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 ": %s\n", offset_, zx_status_get_string(rc));
        } else if ((rc = UnsealBlock(key, slot)) != ZX_OK) {
            xprintf("failed to open block at %" PRIu64 ": %s\n", offset_, zx_status_get_string(rc));
        } else {
            return CommitBlock();
        }
    }

    xprintf("unable to unseal with the given %zu-byte key\n", key.len());
    return ZX_ERR_ACCESS_DENIED;
}

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

    // Check the type GUID matches |kTypeGuid|.
    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);
    if ((rc != Configure(Version(ntohl(version)))) != ZX_OK) {
        return rc;
    }
    if (slot >= num_key_slots_) {
        xprintf("bad key slot: %" PRIu64 "\n", slot);
        return ZX_ERR_OUT_OF_RANGE;
    }
    if ((rc != DeriveSlotKeys(key, slot)) != ZX_OK) {
        return rc;
    }

    // Extract nonce from IV.
    zx_off_t nonce;
    memcpy(&nonce, wrap_iv_.get(), sizeof(nonce));

    // Read in the data
    crypto::AEAD aead;
    crypto::Bytes ptext, ctext, data_key;
    zx_off_t off = kHeaderLen + (slot_len_ * slot);

    size_t key_off, key_len, iv_off, iv_len;
    uint8_t* key_buf;
    if ((rc = crypto::Cipher::GetKeyLen(cipher_, &key_len)) != ZX_OK ||
        (rc = crypto::Cipher::GetIVLen(cipher_, &iv_len)) != ZX_OK ||
        (rc = data_key_.Allocate(key_len, &key_buf)) != ZX_OK) {
        return rc;
    }

    key_off = 0;
    iv_off = data_key_.len();
    if ((rc = ctext.Copy(block_.get() + off, slot_len_)) != ZX_OK ||
        (rc = aead.InitOpen(aead_, wrap_key_, wrap_iv_)) != ZX_OK ||
        (rc = header_.Copy(block_.get(), kHeaderLen)) != ZX_OK ||
        (rc = aead.Open(nonce, ctext, header_, &ptext)) != ZX_OK ||
        (rc = data_iv_.Copy(ptext.get() + iv_off, iv_len)) != ZX_OK) {
        return rc;
    }
    memcpy(key_buf, ptext.get() + key_off, key_len);

    return ZX_OK;
}

// Device methods

zx_status_t Volume::Ioctl(int op, const void* in, size_t in_len, void* out, size_t out_len) {
    zx_status_t rc;
    // Don't include debug messages here; some errors (e.g. ZX_ERR_NOT_SUPPORTED)
    // are expected under certain conditions (e.g. calling FVM ioctls on a non-FVM
    // device).  Handle error reporting at the call sites instead.
    if (dev_) {
        size_t actual;
        if ((rc = device_ioctl(dev_, op, in, in_len, out, out_len, &actual)) < 0) {
            return rc;
        }
    } else {
        ssize_t res;
        if ((res = fdio_ioctl(fd_.get(), op, in, in_len, out, out_len)) < 0) {
            return static_cast<zx_status_t>(res);
        }
    }
    return ZX_OK;
}

zx_status_t Volume::Read() {
    zx_status_t rc;

    if (dev_) {
        if ((rc = SyncIO(dev_, BLOCK_OP_READ, block_.get(), offset_, block_.len())) != ZX_OK) {
            return rc;
        }
    } else {
        if (lseek(fd_.get(), offset_, SEEK_SET) < 0) {
            xprintf("lseek(%d, %" PRIu64 ", SEEK_SET) failed: %s\n", fd_.get(), offset_,
                    strerror(errno));
            return ZX_ERR_IO;
        }
        ssize_t res;
        if ((res = read(fd_.get(), block_.get(), block_.len())) < 0) {
            xprintf("read(%d, %p, %zu) failed: %s\n", fd_.get(), block_.get(), block_.len(),
                    strerror(errno));
            return ZX_ERR_IO;
        }
        if (static_cast<size_t>(res) != block_.len()) {
            xprintf("short read: have %zd, need %zu\n", res, block_.len());
            return ZX_ERR_IO;
        }
    }

    return ZX_OK;
}

zx_status_t Volume::Write() {
    zx_status_t rc;

    if (dev_) {
        if ((rc = SyncIO(dev_, BLOCK_OP_WRITE, block_.get(), offset_, block_.len())) != ZX_OK) {
            return rc;
        }
    } else {
        if (lseek(fd_.get(), offset_, SEEK_SET) < 0) {
            xprintf("lseek(%d, %" PRIu64 ", SEEK_SET) failed: %s\n", fd_.get(), offset_,
                    strerror(errno));
            return ZX_ERR_IO;
        }
        ssize_t res;
        if ((res = write(fd_.get(), block_.get(), block_.len())) < 0) {
            xprintf("write(%d, %p, %zu) failed: %s\n", fd_.get(), block_.get(), block_.len(),
                    strerror(errno));
            return ZX_ERR_IO;
        }
        if (static_cast<size_t>(res) != block_.len()) {
            xprintf("short read: have %zd, need %zu\n", res, block_.len());
            return ZX_ERR_IO;
        }
    }
    return ZX_OK;
}

} // namespace zxcrypt
