blob: 33562c5f8528267084286a3fba23fac7059899f1 [file] [log] [blame]
// Copyright 2022 The Chromium OS 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 LIBHWSEC_BACKEND_BACKEND_H_
#define LIBHWSEC_BACKEND_BACKEND_H_
#include <cstdint>
#include <optional>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
#include <absl/container/flat_hash_set.h>
#include <base/notreached.h>
#include <brillo/secure_blob.h>
#include "libhwsec/status.h"
#include "libhwsec/structures/device_config.h"
#include "libhwsec/structures/key.h"
#include "libhwsec/structures/operation_policy.h"
#include "libhwsec/structures/permission.h"
#include "libhwsec/structures/session.h"
#include "libhwsec/structures/space.h"
namespace hwsec {
// Backend is the layer to abstract the difference between different security
// module(e.g. TPM1.2, TPM2.0, GSC...). And provide a unified interface. Note:
// This class is NOT thread safe.
class Backend {
public:
// State provide the basic state of the security module.
class State {
public:
// Is the security module enabled or not.
virtual StatusOr<bool> IsEnabled() = 0;
// Is the security module ready to use or not.
virtual StatusOr<bool> IsReady() = 0;
// Tries to make the security module become ready.
virtual Status Prepare() = 0;
protected:
State() = default;
~State() = default;
};
// DAMitigation provide the functions related to the DA counter mitigation.
class DAMitigation {
public:
struct DAMitigationStatus {
bool lockout;
uint32_t seconds_remaining;
};
// Is DA counter can be mitigated or not.
virtual StatusOr<bool> IsReady() = 0;
// Is DA mitigation status.
virtual StatusOr<DAMitigationStatus> GetStatus() = 0;
// Tries to mitigate the DA counter.
virtual Status Mitigate() = 0;
protected:
DAMitigation() = default;
~DAMitigation() = default;
};
// Storage provide the functions for writeable space.
class Storage {
public:
enum class ReadyState {
// Ready to use.
kReady,
// Not available on this device.
kNotAvailable,
// Can be prepared.
kPreparable,
};
struct LockOptions {
bool read_lock = false;
bool write_lock = false;
};
// Is the |space| ready to use (defined correctly) or not.
virtual StatusOr<ReadyState> IsReady(Space space) = 0;
// Tries to make the |space| become ready and have enough |size| to write.
virtual Status Prepare(Space space, uint32_t size) = 0;
// Reads the data from the |space|.
virtual StatusOr<brillo::Blob> Load(Space space) = 0;
// Writes the |blob| into the |space|.
virtual Status Store(Space space, const brillo::Blob& blob) = 0;
// Locks the |space| with some optional |options|.
virtual Status Lock(Space space, LockOptions options) = 0;
protected:
Storage() = default;
~Storage() = default;
};
// Storage provide the functions for read-only space.
class RoData {
public:
// Is the |space| ready to use (defined correctly) or not.
virtual StatusOr<bool> IsReady(RoSpace space) = 0;
// Reads the data from the |space|.
virtual StatusOr<brillo::Blob> Read(RoSpace space) = 0;
// Certifies data the |space| with a |key|.
virtual StatusOr<brillo::Blob> Certify(RoSpace space, Key key) = 0;
protected:
RoData() = default;
~RoData() = default;
};
// Sealing provide the functions to sealing and unsealing with policy.
class Sealing {
public:
struct UnsealOptions {
// The preload_data returned from |PreloadSealedData|.
std::optional<Key> preload_data;
};
// Seals the |unsealed_data| with |policy|.
virtual StatusOr<brillo::Blob> Seal(
const OperationPolicySetting& policy,
const brillo::SecureBlob& unsealed_data) = 0;
// Preloads the |sealed_data| with |policy|.
virtual StatusOr<std::optional<ScopedKey>> PreloadSealedData(
const OperationPolicy& policy, const brillo::Blob& sealed_data) = 0;
// Unseals the |sealed_data| with |policy| and optional |options|.
virtual StatusOr<brillo::SecureBlob> Unseal(const OperationPolicy& policy,
const brillo::Blob& sealed_data,
UnsealOptions options) = 0;
protected:
Sealing() = default;
~Sealing() = default;
};
// SignatureSealing provide the functions to sealing and unsealing with policy
// and signature challenge.
class SignatureSealing {
public:
struct SealedData {
struct Tpm1Data {
brillo::Blob public_key_spki_der;
brillo::Blob srk_wrapped_secret;
int32_t scheme;
int32_t hash_alg;
std::vector<brillo::Blob> policy_digests;
};
struct Tpm2Data {
brillo::Blob public_key_spki_der;
brillo::Blob srk_wrapped_cmk;
brillo::Blob cmk_pubkey;
brillo::Blob cmk_wrapped_auth_data;
std::vector<brillo::Blob> pcr_bound_secrets;
};
std::variant<Tpm1Data, Tpm2Data> sealed_data;
};
enum class Algorithm {
kRsassaPkcs1V15Sha1,
kRsassaPkcs1V15Sha256,
kRsassaPkcs1V15Sha384,
kRsassaPkcs1V15Sha512,
};
enum class ChallengeID : uint32_t;
struct ChallengeResult {
NoDefault<ChallengeID> challenge_id;
brillo::Blob challenge;
};
// Seals the |unsealed_data| with |policy| and |public_key_spki_der|.
//
// |key_algorithms| is the list of signature algorithms supported by the
// key. Listed in the order of preference (starting from the most
// preferred); however, the implementation is permitted to ignore this
// order.
virtual StatusOr<SealedData> Seal(
const OperationPolicySetting& policy,
const brillo::SecureBlob& unsealed_data,
const brillo::Blob& public_key_spki_der,
const std::vector<Algorithm>& key_algorithms) = 0;
// Creates a challenge from the |sealed_data| with |policy|,
// |public_key_spki_der|, |key_algorithms|.
virtual StatusOr<ChallengeResult> Challenge(
const OperationPolicy& policy,
const SealedData& sealed_data,
const brillo::Blob& public_key_spki_der,
const std::vector<Algorithm>& key_algorithms) = 0;
// Unseals the sealed_data from previous |challenge| with the
// |challenge_response|.
virtual StatusOr<brillo::SecureBlob> Unseal(
ChallengeID challenge, const brillo::Blob challenge_response) = 0;
protected:
SignatureSealing() = default;
~SignatureSealing() = default;
};
// Deriving provide the functions to derive blob.
class Deriving {
public:
// Derives the |blob| with |key|.
// Note: The function may return same |blob| on some platform(e.g. TPM1.2)
// for backward compatibility.
virtual StatusOr<brillo::Blob> Derive(Key key,
const brillo::Blob& blob) = 0;
// Derives the secure |blob| with |key|.
// Note: The function may return same |blob| on some platform(e.g. TPM1.2)
// for backward compatibility.
virtual StatusOr<brillo::SecureBlob> SecureDerive(
Key key, const brillo::SecureBlob& blob) = 0;
protected:
Deriving() = default;
~Deriving() = default;
};
// Encryption provide the functions to encrypt and decrypt blob.
class Encryption {
public:
struct EncryptionOptions {
enum class Schema {
kDefault,
kNull,
};
Schema schema = Schema::kDefault;
};
// Encrypts the |plaintext| with |key| and optional |options|.
virtual StatusOr<brillo::Blob> Encrypt(Key key,
const brillo::SecureBlob& plaintext,
EncryptionOptions options) = 0;
// Decrypts the |ciphertext| with |key| and optional |options|.
virtual StatusOr<brillo::SecureBlob> Decrypt(Key key,
const brillo::Blob& ciphertext,
EncryptionOptions options) = 0;
protected:
Encryption() = default;
~Encryption() = default;
};
// Signing provide the functions to sign and verify.
class Signing {
public:
// Signs the |data| with |policy| and |key|.
virtual StatusOr<brillo::Blob> Sign(const OperationPolicy& policy,
Key key,
const brillo::Blob& data) = 0;
// Verifies the |signed_data| with |policy| and |key|.
virtual Status Verify(const OperationPolicy& policy,
Key key,
const brillo::Blob& signed_data) = 0;
protected:
Signing() = default;
~Signing() = default;
};
// KeyManagerment provide the functions to manager key.
class KeyManagerment {
public:
enum class PersistentKeyType {
kStorageRootKey,
};
struct CreateKeyOptions {
bool allow_software_gen = false;
bool allow_decrypt = false;
bool allow_sign = false;
};
struct CreateKeyResult {
ScopedKey key;
brillo::Blob key_blob;
};
// Gets the supported algorithm.
virtual StatusOr<absl::flat_hash_set<KeyAlgoType>> GetSupportedAlgo() = 0;
// Creates a key with |key_algo| algorithm, |policy| and optional |options|.
virtual StatusOr<CreateKeyResult> CreateKey(
const OperationPolicySetting& policy,
KeyAlgoType key_algo,
CreateKeyOptions options) = 0;
// Loads a key from |key_blob| with |policy|.
virtual StatusOr<ScopedKey> LoadKey(const OperationPolicy& policy,
const brillo::Blob& key_blob) = 0;
// Creates an auto-reload key with |key_algo| algorithm, |policy| and
// optional |options|.
virtual StatusOr<CreateKeyResult> CreateAutoReloadKey(
const OperationPolicySetting& policy,
KeyAlgoType key_algo,
CreateKeyOptions options) = 0;
// Loads an auto-reload key from |key_blob| with |policy|.
virtual StatusOr<ScopedKey> LoadAutoReloadKey(
const OperationPolicy& policy, const brillo::Blob& key_blob) = 0;
// Loads the persistent key with specific |key_type|.
virtual StatusOr<ScopedKey> GetPersistentKey(
PersistentKeyType key_type) = 0;
// Loads the hash of public part of the |key|.
virtual StatusOr<brillo::Blob> GetPubkeyHash(Key key) = 0;
// Flushes the |key| to reclaim the resource.
virtual Status Flush(Key key) = 0;
// Reloads the |key| if possible.
virtual Status ReloadIfPossible(Key key) = 0;
// Loads the key with raw |key_handle|.
// TODO(174816474): deprecated legacy APIs.
virtual StatusOr<ScopedKey> SideLoadKey(uint32_t key_handle) = 0;
// Loads the raw |key_handle| from key.
// TODO(174816474): deprecated legacy APIs.
virtual StatusOr<uint32_t> GetKeyHandle(Key key) = 0;
protected:
KeyManagerment() = default;
~KeyManagerment() = default;
};
// KeyManagerment provide the functions to manager session.
class SessionManagerment {
public:
struct CreateSessionOptions {};
// Creates a session with |policy| and optional |options|.
virtual StatusOr<ScopedSession> CreateSession(
const OperationPolicy& policy, CreateSessionOptions options) = 0;
// Flushes the |session| to reclaim the resource.
virtual Status Flush(Session session) = 0;
// Loads the session with raw |session_handle|.
// TODO(174816474): deprecated legacy APIs.
virtual StatusOr<ScopedSession> SideLoadSession(
uint32_t session_handle) = 0;
protected:
SessionManagerment() = default;
~SessionManagerment() = default;
};
// Config provide the functions to change settings and policies.
class Config {
public:
struct QuoteResult {
brillo::Blob unquoted_device_config;
brillo::Blob quoted_data;
brillo::Blob signature;
};
// Converts the operation |policy| setting to operation policy.
virtual StatusOr<OperationPolicy> ToOperationPolicy(
const OperationPolicySetting& policy) = 0;
// Sets the |current_user| config.
virtual Status SetCurrentUser(const std::string& current_user) = 0;
// Quotes the |device_config| with |key|.
virtual StatusOr<QuoteResult> Quote(DeviceConfigs device_config,
Key key) = 0;
protected:
Config() = default;
~Config() = default;
};
// Random provide the functions to generate random.
class Random {
public:
// Generates random blob with |size|.
virtual StatusOr<brillo::Blob> RandomBlob(size_t size) = 0;
// Generates random secure blob with |size|.
virtual StatusOr<brillo::SecureBlob> RandomSecureBlob(size_t size) = 0;
protected:
Random() = default;
~Random() = default;
};
// Random provide the functions related to pinweaver.
class PinWeaver {
public:
// Is the pinweaver enabled or not.
virtual StatusOr<bool> IsEnabled() = 0;
// Gets the version of pinweaver.
virtual StatusOr<uint8_t> GetVersion() = 0;
// Sends pinweaver |command|.
virtual StatusOr<brillo::Blob> SendCommand(const brillo::Blob& command) = 0;
protected:
PinWeaver() = default;
~PinWeaver() = default;
};
// Vendor provide the vendor specific commands.
class Vendor {
public:
// Gets the family.
virtual StatusOr<uint32_t> GetFamily() = 0;
// Gets the spec level.
virtual StatusOr<uint64_t> GetSpecLevel() = 0;
// Gets the manufacturer.
virtual StatusOr<uint32_t> GetManufacturer() = 0;
// Gets the TPM model.
virtual StatusOr<uint32_t> GetTpmModel() = 0;
// Gets the TPM firmware version.
virtual StatusOr<uint64_t> GetFirmwareVersion() = 0;
// Gets the vendor specific string.
virtual StatusOr<std::string> GetVendorSpecific() = 0;
// Gets the TPM fingerprint.
virtual StatusOr<int32_t> GetFingerprint() = 0;
// Is the SRK ROCA vulnerable or not.
virtual StatusOr<bool> IsSrkRocaVulnerable() = 0;
// Gets the IFX upgrade information.
virtual StatusOr<brillo::Blob> GetIFXFieldUpgradeInfo() = 0;
// Declares the TPM firmware is stable.
virtual Status DeclareTpmFirmwareStable() = 0;
// Sends the raw |command|.
virtual StatusOr<brillo::Blob> SendRawCommand(
const brillo::Blob& command) = 0;
protected:
Vendor() = default;
~Vendor() = default;
};
virtual ~Backend() = default;
// A helper to get the subclass pointer with subclass type.
template <class SubClass>
SubClass* Get() {
if constexpr (std::is_same_v<SubClass, State>)
return GetState();
else if constexpr (std::is_same_v<SubClass, DAMitigation>)
return GetDAMitigation();
else if constexpr (std::is_same_v<SubClass, Storage>)
return GetStorage();
else if constexpr (std::is_same_v<SubClass, RoData>)
return GetRoData();
else if constexpr (std::is_same_v<SubClass, Sealing>)
return GetSealing();
else if constexpr (std::is_same_v<SubClass, SignatureSealing>)
return GetSignatureSealing();
else if constexpr (std::is_same_v<SubClass, Deriving>)
return GetDeriving();
else if constexpr (std::is_same_v<SubClass, Encryption>)
return GetEncryption();
else if constexpr (std::is_same_v<SubClass, Signing>)
return GetSigning();
else if constexpr (std::is_same_v<SubClass, KeyManagerment>)
return GetKeyManagerment();
else if constexpr (std::is_same_v<SubClass, SessionManagerment>)
return GetSessionManagerment();
else if constexpr (std::is_same_v<SubClass, Config>)
return GetConfig();
else if constexpr (std::is_same_v<SubClass, Random>)
return GetRandom();
else if constexpr (std::is_same_v<SubClass, PinWeaver>)
return GetPinWeaver();
else if constexpr (std::is_same_v<SubClass, Vendor>)
return GetVendor();
NOTREACHED() << "Should not reach here.";
}
protected:
// A helper to give subclasses the ability to access the backend.
template <typename BackendType>
class SubClassHelper {
public:
explicit SubClassHelper(BackendType& backend) : backend_(backend) {}
protected:
~SubClassHelper() = default;
BackendType& backend_;
};
private:
virtual State* GetState() = 0;
virtual DAMitigation* GetDAMitigation() = 0;
virtual Storage* GetStorage() = 0;
virtual RoData* GetRoData() = 0;
virtual Sealing* GetSealing() = 0;
virtual SignatureSealing* GetSignatureSealing() = 0;
virtual Deriving* GetDeriving() = 0;
virtual Encryption* GetEncryption() = 0;
virtual Signing* GetSigning() = 0;
virtual KeyManagerment* GetKeyManagerment() = 0;
virtual SessionManagerment* GetSessionManagerment() = 0;
virtual Config* GetConfig() = 0;
virtual Random* GetRandom() = 0;
virtual PinWeaver* GetPinWeaver() = 0;
virtual Vendor* GetVendor() = 0;
};
} // namespace hwsec
#endif // LIBHWSEC_BACKEND_BACKEND_H_