blob: a7a4f7c37c0ec7fb1ea6cf366ded68366c8ec178 [file] [log] [blame]
// 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.
library fuchsia.hardware.block.verified;
using zx;
/// Hash function to use in the Merkle tree that verifies content. At present,
/// the only supported value for this field is SHA256.
type HashFunction = strict enum : uint8 {
SHA256 = 0x01;
};
/// The block size this device is expected to see in its backing storage, which
/// impacts hash tree layout and total available data size. At present, the only
/// supported block size is blocks of 4096 bytes.
type BlockSize = strict enum : uint8 {
/// Blocks of 4096 bytes each
SIZE_4096 = 0x01;
};
/// Properties of the device that must be decided upon in advance by the client.
/// A Config must be presented to the device whenver the user wants to open it
/// in any mode.
/// `block_size` affects how much or little data we authenticate as a unit, which
/// affects the number of hashes that fit into a block, which affects the
/// number of blocks needed to store integrity information, which affects overall
/// on-disk layout.
type Config = table {
/// Which hash function to use throughout the Merkle tree and when generating
/// a Seal over the superblock.
1: hash_function HashFunction;
/// Size of each block in the Merkle tree.
2: block_size BlockSize;
};
/// A cryptographic seal of the superblock generated with the SHA256 hash function
type Sha256Seal = struct {
/// SHA256 hash of superblock
superblock_hash array<uint8, 32>;
};
/// Data representing a cryptographic seal of the contents of the device.
/// This currently contains the hash of the superblock, and the superblock
/// contains the expected dimensions of the device and the root hash of the
/// integrity information Merkle tree
type Seal = strict union {
1: sha256 Sha256Seal;
};
/// An interface to the block-verified driver, as bound to a single block
/// device with a block-verified-formatted superblock. When bound, the device
/// starts out in `closed` mode. Before use, block-verified devices must first
/// be placed into either `authoring` mode, by calling `OpenForWrite`, or into
/// `verified-read` mode, by calling `OpenForVerifiedRead`.
///
/// This protocol allows the caller to make requests to open the device in
/// either mode, as well as a way to seal a device and receive a cryptographic
/// representation of the contents of the device which, if presented to
/// `OpenForVerifiedRead`, ensures any contents read from the `verified` child
/// device will match those last written while in `authoring` mode.
protocol DeviceManager {
/// Requests that the driver format the underlying block device as described
/// by the parameters in `config`, and enter `authoring` mode.
/// If `config` has any unpopulated fields, or those fields contain enum
/// values that are not known to this version of the driver, this method
/// will return `ZX_ERR_INVALID_ARGS`.
/// If the device was not in `closed` mode at the time of the call, this
/// method will return `ZX_ERR_BAD_STATE`.
/// If the underlying block device returns an error, this method will return
/// that same error code.
/// On success, the driver will enter `authoring` mode, expose a child
/// device named `mutable` which speaks the `fuchsia.hardware.block`
/// protocol in the device tree, then return.
OpenForWrite(struct {
config Config;
}) -> (struct {}) error zx.status;
/// Requests that the device in `authoring` mode:
/// * unbind the child device named `mutable`
/// * regenerate the integrity data necessary to provide the guarantees
/// expected by `OpenForVerifiedRead`
/// * flush all writes to the underlying block device
/// * switch to `closed` mode
/// * return a `Seal` that can be used to ensure that any data read in the
/// future from this device matches that which was written prior to this
/// particular call of `CloseAndGenerateSeal`.
///
/// If the device was not in "authoring" mode at the time of the call, this
/// function will return `ZX_ERR_BAD_STATE` and have no visible side effects.
///
/// If the underlying block device returns a failure while regenerating
/// integrity data or flushing writes, the device will enter the `failed` mode
/// and this call will propagate that error.
///
/// On success, the returned `seal` will contain a hash of the device
/// superblock that should be stored in tamper-proof storage, so it can be
/// retrieved and presented in a future `OpenForVerifiedRead` call.
CloseAndGenerateSeal() -> (struct {
seal Seal;
}) error zx.status;
/// Requests that the device verify that the provided `config` matches the
/// one on disk, and that the given `seal` covers the content of the
/// superblock. If all match as expected, then the device will bind a child
/// device named `verified` which speaks the `fuchsia.hardware.block`
/// protocol and enter the `verified-read` mode. Reads issued to the
/// `verified` block device will either successfully return the same content
/// as the `mutable` block device would have returned at the time the volume
/// was authored, or return a failure. That is to say: modifying the
/// underlying storage will cause the `verified` device to return read
/// failures for any modified blocks as `ZX_ERR_IO_DATA_INTEGRITY` rather
/// than data other than what was present at the time `CloseAndGenerateSeal`
/// was called.
///
/// * Returns `ZX_ERR_BAD_STATE` if the device was not in the `closed`
/// state at the time of the call
/// * Returns `ZX_ERR_INVALID_ARGS` if `config` lacks either `hash_function` or `block_size`
/// * Returns `ZX_ERR_INVALID_ARGS` if `seal` is of an unrecognized variant
/// * Returns `ZX_ERR_IO_DATA_INTEGRITY` if the `seal` provided is inconsistent with
/// the superblock, or if the properties in `config` are inconsistent with the
/// configuration data stored in the superblock on the underlying block device.
/// * Returns the underlying I/O error code if the underlying block device
/// returns an error.
///
/// On success, the device binds a child device `verified`, enters
/// `verified-read` mode, and returns from this call.
OpenForVerifiedRead(struct {
config Config;
seal Seal;
}) -> (struct {}) error zx.status;
/// Requests that the device in either `authoring` mode or `verified-read` mode
/// unbind any child devices and return to `closed` mode.
/// Returns `ZX_ERR_BAD_STATE` if the device is not in `authoring` or
/// `verified-read` mode at the time of the call.
/// On success, the device does the following:
/// * If the device was in `authoring` mode, removes the child `mutable` device
/// * If the device was in `verified-read` mode, removes the child `verified` device
/// * Enters `closed` mode.
/// * Returns from this call
Close() -> (struct {}) error zx.status;
};