Skip to content

Commit

Permalink
Restructure tpm2.h to avoid external includes in public headers
Browse files Browse the repository at this point in the history
  • Loading branch information
atreiber94 committed Jun 14, 2024
1 parent ed26467 commit 2ab6008
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 29 deletions.
4 changes: 4 additions & 0 deletions src/lib/prov/tpm2/info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ all -> tss2-esys,tss2-rc,tss2-tctildr
rng
</requires>

<header:internal>
tpm2_util.h
</header:internal>

<header:public>
tpm2.h
tpm2_rng.h
Expand Down
40 changes: 30 additions & 10 deletions src/lib/prov/tpm2/tpm2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,27 @@
#include <botan/tpm2.h>

#include <botan/internal/fmt.h>
#include <botan/internal/tpm2_util.h>

#include <tss2/tss2_esys.h>
#include <tss2/tss2_tcti.h>
#include <tss2/tss2_tctildr.h>

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> TPM2_Context::create(std::optional<std::string> tcti_nameconf) {
const auto tcti_nameconf_ptr = [&]() -> const char* {
if(tcti_nameconf.has_value()) {
Expand All @@ -30,30 +38,42 @@ std::shared_ptr<TPM2_Context> TPM2_Context::create(std::optional<std::string> tc
return nullptr;
}
}();
// We cannot std::make_shared as the constructor is private
return std::shared_ptr<TPM2_Context>(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<Impl>()) {
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
24 changes: 7 additions & 17 deletions src/lib/prov/tpm2/tpm2.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,16 @@

#include <botan/exceptn.h>

#include <memory>
#include <optional>

#include <tss2/tss2_esys.h>
#include <tss2/tss2_rc.h>
#include <tss2/tss2_tctildr.h>

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
Expand All @@ -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:
/**
Expand All @@ -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<Impl> m_impl;
};

} // namespace Botan
Expand Down
12 changes: 10 additions & 2 deletions src/lib/prov/tpm2/tpm2_rng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <botan/tpm2_rng.h>

#include <botan/internal/stl_util.h>
#include <botan/internal/tpm2_util.h>

#include <source_location>
#include <tss2/tss2_esys.h>
Expand All @@ -25,15 +26,22 @@ void TPM2_RNG::fill_bytes_with_input(std::span<uint8_t> output, std::span<const
data.size = std::min(in.remaining(), MAX_STIR_RANDOM_SIZE);
in.copy_into({data.buffer, data.size});

check_tss2_rc("StirRandom", Esys_StirRandom(m_ctx->get(), ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &data));
check_tss2_rc(
"StirRandom",
Esys_StirRandom(static_cast<ESYS_CONTEXT*>(m_ctx->get()), ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &data));
}

BufferStuffer out(output);
while(!out.full()) {
TPM2B_DIGEST* digest = nullptr;
const auto requested_bytes = std::min(sizeof(digest->buffer), 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<ESYS_CONTEXT*>(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); });
Expand Down
25 changes: 25 additions & 0 deletions src/lib/prov/tpm2/tpm2_util.h
Original file line number Diff line number Diff line change
@@ -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 <botan/tpm2.h>

#include <tss2/tss2_rc.h>

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

0 comments on commit 2ab6008

Please sign in to comment.