blob: e2c7e4c1873194d9ebdc05f1a0441a4d329ba098 [file] [log] [blame]
// Copyright 2021 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_CLIENT_H_
#define SRC_SECURITY_ZXCRYPT_CLIENT_H_
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/fdio.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <memory>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>
namespace zxcrypt {
// Describes what activity we are performing: creating a new volume from
// scratch, or unsealing an existing volume. Different activities may prefer
// different key sources for migration reasons.
enum Activity {
Create,
Unseal,
};
enum KeySourcePolicy {
// Always uses a key of all zeroes.
NullSource,
// Always uses a key from the TEE; fail if not available
TeeRequiredSource,
// Always uses a key from the TEE for new volumes;
// allows fallback to null key for unsealing volumes
TeeTransitionalSource,
// Attempts to use a key from the TEE for new volumes and unlocking, but
// falls back to null key if TEE key fails
TeeOpportunisticSource,
// someday: TpmSource variants?
};
enum KeySource {
kNullSource,
kTeeSource,
};
fbl::Vector<KeySource> ComputeEffectiveCreatePolicy(KeySourcePolicy ksp);
fbl::Vector<KeySource> ComputeEffectiveUnsealPolicy(KeySourcePolicy ksp);
// Computes the ordered list of key sources that should be used in the context
// of |activity| under the key source policy |ksp|.
fbl::Vector<KeySource> ComputeEffectivePolicy(KeySourcePolicy ksp, Activity activity);
// Calls |callback| on a key provided by each key source appropriate for
// |activity| until either the callback returns ZX_OK or the callback has
// returned some error on all candidate key sources. The caller must have
// access to /boot/config/zxcrypt in its namespace to use this function.
zx_status_t TryWithImplicitKeys(
Activity activity, fit::function<zx_status_t(std::unique_ptr<uint8_t[]>, size_t)> callback);
// |zxcrypt::EncryptedVolumeClient| represents a channel to an instance of a bound
// zxcrypt device (named "zxcrypt" in the device tree).
class __EXPORT EncryptedVolumeClient {
public:
explicit EncryptedVolumeClient(zx::channel&& chan);
// Request that the volume provided by the manager represented by |chan| be
// formatted with the given key material/slot, destroying all previous data
// and key slots. This function will only succeed on a sealed volume.
zx_status_t Format(const uint8_t* key, size_t key_len, uint8_t slot);
// Request that the volume provided by the manager represented by |chan| be
// formatted with a product-defined device key associated with the specified
// slot, destroying any previous superblock. The caller must have access to
// /boot/config/zxcrypt in its namespace to use this function. This function
// will only succeed on a sealed volume.
zx_status_t FormatWithImplicitKey(uint8_t slot);
// Request that the volume provided by the manager represented by |chan| be
// unsealed with the given key material/slot. If successful, the driver
// will create a child device named |unsealed| which exposes a block interface.
zx_status_t Unseal(const uint8_t* key, size_t key_len, uint8_t slot);
// Request that the volume provided by the manager represented by |chan| be
// unsealed with an product-defined device key associated with the specified
// slot. The caller must have access to /boot/config/zxcrypt in its
// namespace to use this function. If successful, the driver will create a
// child device named |unsealed| which exposes a block interface.
zx_status_t UnsealWithImplicitKey(uint8_t slot);
// Request that the volume provided by the manager represented by |chan| be
// sealed. After calling this method, it is an error to make any further
// calls with this EncryptedVolumeClient.
zx_status_t Seal();
// Request that the volume provided by the manager represented by |chan| be
// shredded, permanently rendering the device unable to be |Unseal|ed again in
// the future. This renders all data on the volume permanently inaccessible
// once it is sealed.
zx_status_t Shred();
private:
// The underlying zxcrypt device, accessed over FDIO
zx::channel chan_;
};
// |zxcrypt::VolumeManager| manages access to a zxcrypt volume device. In
// particular, it ensures that the driver is bound before returning a handle to
// the EncryptedVolumeClient.
//
// Due to the limitations of actions that involve multiple device drivers,
// VolumeManager requires access to both the block device we wish to run zxcrypt
// atop and the root of the device tree that contains said block device, so that
// we can discover child driver nodes in that tree via topological paths, which
// are currently the only way to obtain a handle to a newly-bound child.
class __EXPORT VolumeManager {
public:
explicit VolumeManager(fbl::unique_fd&& block_dev_fd, fbl::unique_fd&& devfs_root_fd);
// Attempts to open the zxcrypt driver device associated with the underlying
// block device described by |fd|, binding the driver if necessary,
// and returning a channel to the zxcrypt device node.
zx_status_t OpenClient(const zx::duration& timeout, zx::channel& out);
// Attempts to open the block device representing the inner, unsealed block
// device, at a device path of |/zxcrypt/unsealed/block| below the block device
// represented by |block_dev_fd_|. This will only work once you have called
// |OpenClient| and used that handle to call |EncryptedVolumeClient::Unseal|
// or |EncryptedVolumeClient::UnsealWithImplicitKey|.
zx_status_t OpenInnerBlockDevice(const zx::duration& timeout, fbl::unique_fd* out);
private:
// OpenManager, but using a pre-created fdio_t.
zx_status_t OpenClientWithCaller(fdio_cpp::UnownedFdioCaller& caller, const zx::duration& timeout,
zx::channel& out);
// Returns the topological path of the underlying block device, relative to
// |devfs_root_fd|
zx_status_t RelativeTopologicalPath(fdio_cpp::UnownedFdioCaller& caller, fbl::String* out);
// The underlying block device, accessed over FDIO
fbl::unique_fd block_dev_fd_;
// The root of the device tree, needed to openat() related devices via
// constructing relative topological paths.
fbl::unique_fd devfs_root_fd_;
};
} // namespace zxcrypt
#endif // SRC_SECURITY_ZXCRYPT_CLIENT_H_