Skip to content

Commit

Permalink
Allow using Botan for the TPM2 TSS' crypto needs
Browse files Browse the repository at this point in the history
This adds an implementation of the tpm2-tss crypto callbacks. If
enabled, Botan will be used for the client-side crypto functions to
communicate with the TPM. This lets applications shed a transitive
dependency on another crypto library (like OpenSSL or mbedTLS).

The crypto callbacks are available in tpm2-tss 4.0 and later. Before
that, calling TPM2::Context::use_botan_crypto_backend() will result in
an exception.

Co-Authored-By: René Meusel <[email protected]>
  • Loading branch information
atreiber94 and reneme committed Sep 6, 2024
1 parent 403f899 commit 6f1d96b
Show file tree
Hide file tree
Showing 6 changed files with 968 additions and 1 deletion.
42 changes: 42 additions & 0 deletions src/lib/prov/tpm2/tpm2_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <tss2/tss2_tcti.h>
#include <tss2/tss2_tctildr.h>

#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
#include <botan/internal/tpm2_crypto_backend.h>
#endif

namespace Botan::TPM2 {

namespace {
Expand All @@ -32,8 +36,20 @@ constexpr TPM2_HANDLE storage_root_key_handle = TPM2_HR_PERSISTENT + 1;
struct Context::Impl {
TSS2_TCTI_CONTEXT* m_tcti_ctx;
ESYS_CONTEXT* m_ctx;

#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
std::unique_ptr<CryptoCallbackState> m_crypto_callback_state;
#endif
};

bool Context::supports_botan_crypto_backend() noexcept {
#if defined(BOTAN_TSS2_SUPPORTS_CRYPTO_CALLBACKS) and defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
return true;
#else
return false;
#endif
}

std::shared_ptr<Context> Context::create(const std::string& tcti_nameconf) {
// We cannot std::make_shared as the constructor is private
return std::shared_ptr<Context>(new Context(tcti_nameconf.c_str()));
Expand Down Expand Up @@ -61,6 +77,32 @@ Context::Context(const char* tcti_name, const char* tcti_conf) : m_impl(std::mak
BOTAN_ASSERT_NONNULL(m_impl->m_ctx);
}

void Context::use_botan_crypto_backend(const std::shared_ptr<Botan::RandomNumberGenerator>& rng) {
#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
BOTAN_STATE_CHECK(!uses_botan_crypto_backend());
m_impl->m_crypto_callback_state = std::make_unique<CryptoCallbackState>(rng);
enable_crypto_callbacks(shared_from_this());
#else
BOTAN_UNUSED(rng);
throw Not_Implemented("This build of botan does not provide the TPM2 crypto backend");
#endif
}

bool Context::uses_botan_crypto_backend() const noexcept {
#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
return m_impl->m_crypto_callback_state != nullptr;
#else
return false;
#endif
}

#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
CryptoCallbackState& Context::crypto_callback_state() {
BOTAN_ASSERT_NONNULL(m_impl->m_crypto_callback_state);
return *m_impl->m_crypto_callback_state;
}
#endif

ESYS_CONTEXT* Context::esys_context() noexcept {
return m_impl->m_ctx;
}
Expand Down
33 changes: 33 additions & 0 deletions src/lib/prov/tpm2/tpm2_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ struct ESYS_CONTEXT;

namespace Botan::TPM2 {

struct CryptoCallbackState;

class PrivateKey;
class SessionBundle;

Expand Down Expand Up @@ -57,6 +59,32 @@ class BOTAN_PUBLIC_API(3, 6) Context final : public std::enable_shared_from_this
Context& operator=(const Context&) = delete;
Context& operator=(Context&& ctx) noexcept = default;

/**
* 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;

Expand Down Expand Up @@ -105,6 +133,11 @@ class BOTAN_PUBLIC_API(3, 6) Context final : public std::enable_shared_from_this
Context(const char* tcti_nameconf);
Context(const char* tcti_name, const char* tcti_conf);

#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;
Expand Down
20 changes: 20 additions & 0 deletions src/lib/prov/tpm2/tpm2_crypto_backend/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<defines>
TPM2_CRYPTO_BACKEND -> 20240806
</defines>

<module_info>
name -> "TPM2 Crypto Backend"
brief -> "Implementation of the TPM2-TSS crypto callbacks"
</module_info>

<requires>
hash
hmac
modes
pk_pad
eme_raw
</requires>

<header:internal>
tpm2_crypto_backend.h
</header:internal>
Loading

0 comments on commit 6f1d96b

Please sign in to comment.