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