diff --git a/src/lib/prov/tpm2/info.txt b/src/lib/prov/tpm2/info.txt index a1487d75fb..63409938ec 100644 --- a/src/lib/prov/tpm2/info.txt +++ b/src/lib/prov/tpm2/info.txt @@ -17,6 +17,10 @@ all -> tss2-esys,tss2-rc,tss2-tctildr rng + +tpm2_util.h + + tpm2.h tpm2_rng.h diff --git a/src/lib/prov/tpm2/tpm2.cpp b/src/lib/prov/tpm2/tpm2.cpp index f1ce599491..74ca2efb9a 100644 --- a/src/lib/prov/tpm2/tpm2.cpp +++ b/src/lib/prov/tpm2/tpm2.cpp @@ -9,19 +9,27 @@ #include #include +#include #include +#include #include namespace Botan { -TPM2_Error::TPM2_Error(std::string_view location, TSS2_RC rc) : +TPM2_Error::TPM2_Error(std::string_view location, uint32_t rc) : Exception(fmt("TPM2 Exception in {}: Code {} ({})", location, rc, Tss2_RC_Decode(rc))), m_rc(rc) {} std::string TPM2_Error::error_message() const { return Tss2_RC_Decode(m_rc); } +class TPM2_Context::Impl { + public: + TSS2_TCTI_CONTEXT* m_tcti_ctx; + ESYS_CONTEXT* m_ctx; +}; + std::shared_ptr TPM2_Context::create(std::optional tcti_nameconf) { const auto tcti_nameconf_ptr = [&]() -> const char* { if(tcti_nameconf.has_value()) { @@ -30,30 +38,42 @@ std::shared_ptr TPM2_Context::create(std::optional tc return nullptr; } }(); + // We cannot std::make_shared as the constructor is private return std::shared_ptr(new TPM2_Context(tcti_nameconf_ptr)); } -TPM2_Context::TPM2_Context(const char* tcti_nameconf) { - check_tss2_rc("TCTI Initialization", Tss2_TctiLdr_Initialize(tcti_nameconf, &m_tcti_ctx)); - check_tss2_rc("TPM2 Initialization", Esys_Initialize(&m_ctx, m_tcti_ctx, nullptr /* ABI version */)); +TPM2_Context::TPM2_Context(const char* tcti_nameconf) : m_impl(std::make_unique()) { + check_tss2_rc("TCTI Initialization", Tss2_TctiLdr_Initialize(tcti_nameconf, &m_impl->m_tcti_ctx)); + check_tss2_rc("TPM2 Initialization", Esys_Initialize(&m_impl->m_ctx, m_impl->m_tcti_ctx, nullptr /* ABI version */)); } -TPM2_Context::TPM2_Context(TPM2_Context&& ctx) noexcept : m_ctx(ctx.m_ctx) { - ctx.m_ctx = nullptr; +TPM2_Context::TPM2_Context(TPM2_Context&& ctx) noexcept { + m_impl->m_ctx = ctx.m_impl->m_ctx; + m_impl->m_tcti_ctx = ctx.m_impl->m_tcti_ctx; + + ctx.m_impl->m_ctx = nullptr; + ctx.m_impl->m_tcti_ctx = nullptr; } TPM2_Context& TPM2_Context::operator=(TPM2_Context&& ctx) noexcept { if(this != &ctx) { - m_ctx = ctx.m_ctx; - ctx.m_ctx = nullptr; + m_impl->m_ctx = ctx.m_impl->m_ctx; + m_impl->m_tcti_ctx = ctx.m_impl->m_tcti_ctx; + + ctx.m_impl->m_ctx = nullptr; + ctx.m_impl->m_tcti_ctx = nullptr; } return *this; } +void* TPM2_Context::get() { + return m_impl->m_ctx; +} + TPM2_Context::~TPM2_Context() { - Esys_Finalize(&m_ctx); - Tss2_TctiLdr_Finalize(&m_tcti_ctx); + Esys_Finalize(&m_impl->m_ctx); + Tss2_TctiLdr_Finalize(&m_impl->m_tcti_ctx); } } // namespace Botan diff --git a/src/lib/prov/tpm2/tpm2.h b/src/lib/prov/tpm2/tpm2.h index 32cdee131c..fe45c8b345 100644 --- a/src/lib/prov/tpm2/tpm2.h +++ b/src/lib/prov/tpm2/tpm2.h @@ -11,21 +11,16 @@ #include -#include #include -#include -#include -#include - namespace Botan { class BOTAN_PUBLIC_API(3, 6) TPM2_Error final : public Exception { public: - TPM2_Error(std::string_view location, TSS2_RC rc); + TPM2_Error(std::string_view location, uint32_t rc); ErrorType error_type() const noexcept override { return ErrorType::TPMError; } - TSS2_RC code() const { return m_rc; } + uint32_t code() const { return m_rc; } int error_code() const noexcept override { // RC is uint32 but the maximum value is within int32 range as per tss2_common.h @@ -35,15 +30,9 @@ class BOTAN_PUBLIC_API(3, 6) TPM2_Error final : public Exception { std::string error_message() const; private: - TSS2_RC m_rc; + uint32_t m_rc; }; -inline void check_tss2_rc(std::string_view location, TSS2_RC rc) { - if(rc != TSS2_RC_SUCCESS) { - throw TPM2_Error(location, rc); - } -} - class BOTAN_PUBLIC_API(3, 6) TPM2_Context final { public: /** @@ -59,14 +48,15 @@ class BOTAN_PUBLIC_API(3, 6) TPM2_Context final { TPM2_Context& operator=(const TPM2_Context&) = delete; TPM2_Context& operator=(TPM2_Context&& ctx) noexcept; - ESYS_CONTEXT* get() { return m_ctx; } + // Return an ESYS_CONTEXT* for use in other TPM2 functions. + void* get(); private: TPM2_Context(const char* tcti_nameconf); private: - TSS2_TCTI_CONTEXT* m_tcti_ctx; - ESYS_CONTEXT* m_ctx; + class Impl; // PImpl to avoid TPM2-TSS includes in this header + std::unique_ptr m_impl; }; } // namespace Botan diff --git a/src/lib/prov/tpm2/tpm2_rng.cpp b/src/lib/prov/tpm2/tpm2_rng.cpp index 2a90e1a50a..77e4219951 100644 --- a/src/lib/prov/tpm2/tpm2_rng.cpp +++ b/src/lib/prov/tpm2/tpm2_rng.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -25,7 +26,9 @@ void TPM2_RNG::fill_bytes_with_input(std::span output, std::spanget(), ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &data)); + check_tss2_rc( + "StirRandom", + Esys_StirRandom(static_cast(m_ctx->get()), ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &data)); } BufferStuffer out(output); @@ -33,7 +36,12 @@ void TPM2_RNG::fill_bytes_with_input(std::span output, std::spanbuffer), out.remaining_capacity()); check_tss2_rc("GetRandom", - Esys_GetRandom(m_ctx->get(), ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, requested_bytes, &digest)); + Esys_GetRandom(static_cast(m_ctx->get()), + ESYS_TR_NONE, + ESYS_TR_NONE, + ESYS_TR_NONE, + requested_bytes, + &digest)); // Ensure Esys_Free(digest) is called even if assertions fail and we leave this block auto clean_buffer = scoped_cleanup([&digest] { Esys_Free(digest); }); diff --git a/src/lib/prov/tpm2/tpm2_util.h b/src/lib/prov/tpm2/tpm2_util.h new file mode 100644 index 0000000000..812c83ac1c --- /dev/null +++ b/src/lib/prov/tpm2/tpm2_util.h @@ -0,0 +1,25 @@ +/* +* TPM 2 internal utilities +* (C) 2024 Jack Lloyd +* (C) 2024 René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity GmbH +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_TPM2_UTIL_H_ +#define BOTAN_TPM2_UTIL_H_ + +#include + +#include + +namespace Botan { + +inline void check_tss2_rc(std::string_view location, TSS2_RC rc) { + if(rc != TSS2_RC_SUCCESS) { + throw TPM2_Error(location, rc); + } +} +} // namespace Botan + +#endif