Source code
Revision control
Copy as Markdown
Other Tools
/*
* TPM 2 interface
* (C) 2024 Jack Lloyd
* (C) 2024 René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity GmbH, financed by LANCOM Systems GmbH
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#ifndef BOTAN_TPM2_CONTEXT_H_
#define BOTAN_TPM2_CONTEXT_H_
#include <botan/exceptn.h>
#include <botan/rng.h>
#include <memory>
#include <optional>
#include <vector>
/// Forward declaration of TSS2 type for convenience
using TPM2_HANDLE = uint32_t;
/// Forward declaration of TSS2 type for convenience
using ESYS_TR = uint32_t;
struct ESYS_CONTEXT;
namespace Botan::TPM2 {
struct CryptoCallbackState;
class PrivateKey;
class SessionBundle;
/**
* Central class for interacting with a TPM2. Additional to managing the
* connection to the TPM, this provides authorative information about the TPM's
* capabilities. Also, it allows to persist and evict keys generated by the TPM.
*/
class BOTAN_PUBLIC_API(3, 6) Context final : public std::enable_shared_from_this<Context> {
public:
/**
* @param tcti_nameconf this is passed to Tss2_TctiLdr_Initialize verbatim
*/
static std::shared_ptr<Context> create(const std::string& tcti_nameconf);
/**
* @param tcti if set this is passed to Tss2_TctiLdr_Initialize_Ex verbatim
* otherwise a nullptr is passed.
* @param conf if set this is passed to Tss2_TctiLdr_Initialize_Ex verbatim
* otherwise a nullptr is passed.
*/
static std::shared_ptr<Context> create(std::optional<std::string> tcti = {},
std::optional<std::string> conf = {});
/**
* Create a TPM2::Context from an externally sourced TPM2-TSS ESYS
* Context. Note that the input contexts need to remain alive for the
* lifetime of the entire TPM2::Context! This allows to use Botan's TPM2
* functionality within an exising ESAPI application.
*
* Note that Botan won't finalize an externally provided ESYS context,
* this responsibility remains with the caller in this case.
*
* @param ctx the already set up ESYS_CONTEXT*
*/
static std::shared_ptr<Context> create(ESYS_CONTEXT* ctx);
Context(const Context&) = delete;
Context(Context&&) noexcept;
~Context();
Context& operator=(const Context&) = delete;
Context& operator=(Context&&) noexcept;
/**
* Overrides the TSS2's crypto callbacks with Botan's functionality.
*
* This replaces all cryptographic functionality required for the
* communication with the TPM by botan's implementations. The TSS2
* would otherwise use OpenSSL or mbedTLS.
*
* Note that the provided @p rng should not be dependent on the TPM.
*
* @param rng the RNG to use for the crypto operations
* @throws Not_Implemented if the TPM2-TSS does not support crypto callbacks
* @sa supports_botan_crypto_backend()
*/
void use_botan_crypto_backend(const std::shared_ptr<Botan::RandomNumberGenerator>& rng);
/**
* Checks if the TSS2 supports registering Botan's crypto backend at runtime.
* Older versions of the TSS2 do not support this feature ( 4.0.0), also
* Botan may be compiled without support for TSS' crypto backend.
* @return true if the TSS2 supports Botan's crypto backend
*/
static bool supports_botan_crypto_backend() noexcept;
/// @returns true if botan is used for the TSS' crypto functions
bool uses_botan_crypto_backend() const noexcept;
/// @return an ESYS_CONTEXT* for use in other TPM2 functions.
ESYS_CONTEXT* esys_context() noexcept;
operator ESYS_CONTEXT*() noexcept { return esys_context(); }
/// @return the Vendor of the TPM2
std::string vendor() const;
/// @returns the Manufacturer of the TPM2
std::string manufacturer() const;
/**
* The @p algo_name can be any of the string algorithm specifiers used
* elsewhere. For example, "RSA", "AES-128", "SHA-1", "CTR(3DES)", etc.
*
* @returns true if the specified algorithm is supported by the TPM
*/
bool supports_algorithm(std::string_view algo_name) const;
/// @returns the maximum number of random bytes to be requested at once
size_t max_random_bytes_per_request() const;
std::vector<ESYS_TR> transient_handles() const;
/// @returns a persistent handle that is currently not in use
/// or std::nullopt if no such handle is available
std::optional<TPM2_HANDLE> find_free_persistent_handle() const;
std::vector<TPM2_HANDLE> persistent_handles() const;
/// Makes @p key persistent at location @p persistent_handle or any free
TPM2_HANDLE persist(TPM2::PrivateKey& key,
const SessionBundle& sessions,
std::span<const uint8_t> auth_value = {},
std::optional<TPM2_HANDLE> persistent_handle = std::nullopt);
/// Evicts a persistent @p key from the TPM. The key cannot be used after.
void evict(std::unique_ptr<TPM2::PrivateKey> key, const SessionBundle& sessions);
// TODO: Currently this assumes that the SRK is a persistent object,
// this assumption may not hold forever.
std::unique_ptr<TPM2::PrivateKey> storage_root_key(std::span<const uint8_t> auth_value,
const SessionBundle& sessions);
private:
Context(ESYS_CONTEXT* ctx, bool external);
#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
friend void enable_crypto_callbacks(const std::shared_ptr<Context>&);
CryptoCallbackState& crypto_callback_state();
#endif
private:
struct Impl; // PImpl to avoid TPM2-TSS includes in this header
std::unique_ptr<Impl> m_impl;
};
} // namespace Botan::TPM2
#endif