// 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.

#ifndef SRC_SECURITY_ZXCRYPT_INCLUDE_ZXCRYPT_VOLUME_H_
#define SRC_SECURITY_ZXCRYPT_INCLUDE_ZXCRYPT_VOLUME_H_

#include <lib/zx/time.h>
#include <stddef.h>
#include <stdint.h>
#include <zircon/types.h>

#include "src/security/fcrypto/aead.h"
#include "src/security/fcrypto/bytes.h"
#include "src/security/fcrypto/cipher.h"
#include "src/security/fcrypto/digest.h"
#include "src/security/fcrypto/secret.h"

// |zxcrypt::Volume| manages the interactions of both driver and library code with the metadata
// used to format and operate zxcrypt devices.  The superblock is saved multiple times on disk to
// provide redundancy.
//
// It manages three types of key material:
//  - Root: Provided by the consumers of this class.
//  - Data: Randomly generated at volume creation and used to encrypt and decrypt the volumes data.
//  - Wrap: Derived from the root keys and used to encrypt and decrypt the data key material.
//
// This is an abstract class, with concrete children for FD-backed and
// zx_device_t-backed implementations.
namespace zxcrypt {

// Forward declaration of unit test framework.
namespace testing {
class TestDevice;
}

const uint8_t zxcrypt_magic[16] = {
    0x5f, 0xe8, 0xf8, 0x00, 0xb3, 0x6d, 0x11, 0xe7, 0x80, 0x7a, 0x78, 0x63, 0x72, 0x79, 0x70, 0x74,
};

using key_slot_t = zx_off_t;

// Unifying types used for a couple of calls that will call either FIDL or Banjo
// interfaces under the hood.
typedef struct {
  uint64_t block_count;
  uint32_t block_size;
} BlockInfo;

typedef struct {
  bool allocated;
  size_t count;
} SliceRegion;

class __EXPORT Volume {
 public:
  // The supported version, named by the algorithms they use.  New version should increment the
  // version number and update the default version.  Zero indicates an error state.
  enum Version : uint32_t {
    kUninitialized = 0,
    kAES256_XTS_SHA256,
  };

  // The default version, used when sealing a new volume.
  static const Version kDefaultVersion;

  // The amount of data that can "in-flight" to the underlying block device before the zxcrypt
  // driver begins queuing transactions
  static const uint32_t kBufferSize;

  explicit Volume();
  virtual ~Volume();
  DISALLOW_COPY_ASSIGN_AND_MOVE(Volume);

  // Returns space reserved for metadata and keys
  size_t reserved_blocks() const { return reserved_blocks_; }
  size_t reserved_slices() const { return reserved_slices_; }
  size_t num_slots() const { return num_key_slots_; }

  // Opens a zxcrypt volume on the block device described by |fd| using the |key| corresponding to
  // given key |slot|.
  zx_status_t Unlock(const crypto::Secret& key, key_slot_t slot);

  // Removes ALL keys, rendering any data in the zxcrypt device inaccessible.  It is an error to
  // call any method except the destructor on this instance after this methods returns.
  zx_status_t Shred();

 protected:
  friend class testing::TestDevice;

  ////////////////
  // Configuration methods

  // Retrieves the block and FVM information and adjusts it.
  zx_status_t Init();

  // Maps the volume version to crypto algorithms.
  zx_status_t Configure(Version version);

  // Returns via |out| the offset in bytes for the given key |slot|.  Returns an error if the
  // volume hasn't been initialized, or if |slot| is out of range.
  zx_status_t GetSlotOffset(key_slot_t slot, zx_off_t* out) const;

  // Derives intermediate keys for the given key |slot| from the given |key|.
  zx_status_t DeriveSlotKeys(const crypto::Secret& key, key_slot_t slot);

  // Resets all fields in this object to initial values
  void Reset();

  ////////////////
  // Block methods

  // Resets the superblock offset to the first location (block 0).
  zx_status_t Begin();

  // Advances the superblock offset to the next volume location.  Returns ZX_ERR_STOP if no more
  // offsets available; ZX_ERR_NEXT otherwise.
  zx_status_t Next();

  // Creates a new volume, with a new instance GUID and data key and IV, and seals it with the
  // given |key|
  zx_status_t CreateBlock();

  // Writes |block| out to each of the superblock locations.
  zx_status_t CommitBlock();

  // Encrypts the current data key and IV to the given |slot| using the given |key|.
  zx_status_t SealBlock(const crypto::Secret& key, key_slot_t slot);

  // Reads the block and parses and checks various fields before attempting to open it with the
  // given |key| corresponding to the given |slot|.
  zx_status_t UnsealBlock(const crypto::Secret& key, key_slot_t slot);

  ////////////////
  // Device methods

  virtual zx_status_t GetBlockInfo(BlockInfo* out) = 0;
  virtual zx_status_t GetFvmSliceSize(uint64_t* out) = 0;
  static const size_t MAX_SLICE_REGIONS = 16;
  virtual zx_status_t DoBlockFvmVsliceQuery(uint64_t vslice_start,
                                            SliceRegion ranges[MAX_SLICE_REGIONS],
                                            uint64_t* slice_count) = 0;
  virtual zx_status_t DoBlockFvmExtend(uint64_t start_slice, uint64_t slice_count) = 0;

  // Reads a block from the current offset on the underlying device.
  virtual zx_status_t Read() = 0;

  // Writes a block to the current offset on the underlying device.
  virtual zx_status_t Write() = 0;

  ////////////////
  // Fields

  // The underlying block device as accessed via DDK or FDIO.

  // The space reserved for metadata.
  uint64_t reserved_blocks_;
  uint64_t reserved_slices_;

  // Buffer holding the current block being examined, and its offset on the underlying device.
  crypto::Bytes block_;
  zx_off_t offset_;

  // The instance GUID for this device.
  crypto::Bytes guid_;
  // A copy of the entire header, used as AAD for the AEAD.
  crypto::Bytes header_;

  // The algorithm, lengths, and buffers for the key-wrapping AEAD.
  crypto::AEAD::Algorithm aead_;
  crypto::Secret wrap_key_;
  crypto::Bytes wrap_iv_;

  // The algorithm for data processing Cipher and length of wrapped key material.
  crypto::Cipher::Algorithm cipher_;
  crypto::Secret data_key_;
  crypto::Bytes data_iv_;
  size_t slot_len_;
  size_t num_key_slots_;

  // The digest used by the HKDF.
  crypto::digest::Algorithm digest_;
};

}  // namespace zxcrypt

#endif  // SRC_SECURITY_ZXCRYPT_INCLUDE_ZXCRYPT_VOLUME_H_
