-
Notifications
You must be signed in to change notification settings - Fork 578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add TPM2 RNG #4117
Closed
Closed
Add TPM2 RNG #4117
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
6109b2b
Add TPM2 Context and tpm2_rng
atreiber94 5250131
Add FFI support for TPM2 RNG
atreiber94 e613f07
Add TPM2 RNG support for Python
atreiber94 c205858
Include TCTI configuration into TPM2_Context
atreiber94 bda3913
Fix CI
atreiber94 78f1bee
Fix Python linting issues
atreiber94 1cd900b
Add CI support for TPM2/swtpm
atreiber94 c6a3a02
Fix TPM2_Context vs TPm2Context in botan3.py
atreiber94 d1244e3
Extend CI for TPM2
atreiber94 9890bfa
Fix Memory Leak in C FFI Test
atreiber94 ed26467
Apply review suggestions except tpm2.h restructuring
atreiber94 2ab6008
Restructure tpm2.h to avoid external includes in public headers
atreiber94 70be246
Address comments regarding tpm2.h restructuring
atreiber94 6e2af38
Review comments: Rename TPM2_Context::get() to TPM2_Context::inner_co…
atreiber94 34c7d9a
Review comment: Move TPM2 FFI Declarations to end of file
atreiber94 f09eb9f
Review comment: Remove Botan_Tests::
atreiber94 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* (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) | ||
*/ | ||
|
||
#include <botan/ffi.h> | ||
|
||
#include <botan/internal/ffi_rng.h> | ||
#include <botan/internal/ffi_util.h> | ||
|
||
#if defined(BOTAN_HAS_TPM2) | ||
#include <botan/tpm2.h> | ||
#include <botan/tpm2_rng.h> | ||
#endif | ||
|
||
extern "C" { | ||
|
||
using namespace Botan_FFI; | ||
|
||
#if defined(BOTAN_HAS_TPM2) | ||
/** | ||
* This wrapper is required since BOTAN_FFI_DECLARE_STRUCT internally produces a unique pointer, | ||
* but the TPM2_Context is meant to be used as a shared pointer. | ||
*/ | ||
struct botan_tpm2_ctx_wrapper { | ||
std::shared_ptr<Botan::TPM2_Context> ctx; | ||
}; | ||
|
||
BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_ctx_struct, botan_tpm2_ctx_wrapper, 0xD2B95E15); | ||
#endif | ||
|
||
int botan_tpm2_ctx_init(botan_tpm2_ctx_t* ctx_out, const char* tcti_nameconf) { | ||
#if defined(BOTAN_HAS_TPM2) | ||
return ffi_guard_thunk(__func__, [=]() -> int { | ||
if(ctx_out == nullptr) { | ||
return BOTAN_FFI_ERROR_NULL_POINTER; | ||
} | ||
auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>(); | ||
|
||
auto tcti = [=]() -> std::optional<std::string> { | ||
randombit marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if(tcti_nameconf == nullptr) { | ||
return {}; | ||
} else { | ||
return std::string(tcti_nameconf); | ||
} | ||
}(); | ||
|
||
ctx->ctx = Botan::TPM2_Context::create(std::move(tcti)); | ||
randombit marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*ctx_out = new botan_tpm2_ctx_struct(std::move(ctx)); | ||
return BOTAN_FFI_SUCCESS; | ||
}); | ||
#else | ||
BOTAN_UNUSED(ctx_out, tcti_nameconf); | ||
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; | ||
#endif | ||
} | ||
|
||
/** | ||
* Frees all resouces of a TPM2 context | ||
* @param ctx TPM2 context | ||
* @return 0 on success | ||
*/ | ||
int botan_tpm2_ctx_destroy(botan_tpm2_ctx_t ctx) { | ||
#if defined(BOTAN_HAS_TPM2) | ||
return BOTAN_FFI_CHECKED_DELETE(ctx); | ||
#else | ||
BOTAN_UNUSED(ctx); | ||
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; | ||
#endif | ||
} | ||
|
||
int botan_tpm2_rng_init(botan_rng_t* rng_out, botan_tpm2_ctx_t ctx) { | ||
#if defined(BOTAN_HAS_TPM2) | ||
return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int { | ||
if(rng_out == nullptr) { | ||
return BOTAN_FFI_ERROR_NULL_POINTER; | ||
} | ||
|
||
*rng_out = new botan_rng_struct(std::make_unique<Botan::TPM2_RNG>(ctx_wrapper.ctx)); | ||
return BOTAN_FFI_SUCCESS; | ||
}); | ||
#else | ||
BOTAN_UNUSED(rng_out, ctx); | ||
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; | ||
#endif | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<defines> | ||
TPM2 -> 20240610 | ||
</defines> | ||
|
||
<module_info> | ||
name -> "TPM2" | ||
brief -> "Wrappers and Utilites to interact with TPM2" | ||
</module_info> | ||
|
||
load_on vendor | ||
|
||
<libs> | ||
all -> tss2-esys,tss2-rc,tss2-tctildr | ||
</libs> | ||
|
||
<requires> | ||
rng | ||
</requires> | ||
|
||
<header:internal> | ||
tpm2_util.h | ||
</header:internal> | ||
|
||
<header:public> | ||
tpm2.h | ||
tpm2_rng.h | ||
</header:public> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* TPM 2 interface | ||
* (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) | ||
*/ | ||
|
||
#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, 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); | ||
} | ||
|
||
struct TPM2_Context::Impl { | ||
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()) { | ||
return tcti_nameconf->c_str(); | ||
} else { | ||
return nullptr; | ||
} | ||
}(); | ||
// We cannot std::make_shared as the constructor is private | ||
return std::shared_ptr<TPM2_Context>(new TPM2_Context(tcti_nameconf_ptr)); | ||
atreiber94 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
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 */)); | ||
} | ||
|
||
void* TPM2_Context::inner_context_object() { | ||
return m_impl->m_ctx; | ||
} | ||
|
||
TPM2_Context::~TPM2_Context() { | ||
Esys_Finalize(&m_impl->m_ctx); | ||
Tss2_TctiLdr_Finalize(&m_impl->m_tcti_ctx); | ||
} | ||
|
||
} // namespace Botan |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
* TPM 2 interface | ||
* (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_H_ | ||
#define BOTAN_TPM2_H_ | ||
|
||
#include <botan/exceptn.h> | ||
|
||
#include <memory> | ||
#include <optional> | ||
atreiber94 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
namespace Botan { | ||
class BOTAN_PUBLIC_API(3, 6) TPM2_Error final : public Exception { | ||
public: | ||
TPM2_Error(std::string_view location, uint32_t rc); | ||
|
||
ErrorType error_type() const noexcept override { return ErrorType::TPMError; } | ||
|
||
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 | ||
return static_cast<int>(m_rc); | ||
} | ||
|
||
std::string error_message() const; | ||
|
||
private: | ||
uint32_t m_rc; | ||
}; | ||
|
||
class BOTAN_PUBLIC_API(3, 6) TPM2_Context final { | ||
public: | ||
/** | ||
* @param tcti_nameconf if set this is passed to Tss2_TctiLdr_Initialize verbatim | ||
* otherwise a nullptr is passed. | ||
*/ | ||
static std::shared_ptr<TPM2_Context> create(std::optional<std::string> tcti_nameconf = {}); | ||
|
||
TPM2_Context(const TPM2_Context&) = delete; | ||
TPM2_Context(TPM2_Context&& ctx) noexcept = default; | ||
~TPM2_Context(); | ||
|
||
TPM2_Context& operator=(const TPM2_Context&) = delete; | ||
TPM2_Context& operator=(TPM2_Context&& ctx) noexcept = default; | ||
|
||
/// @return an ESYS_CONTEXT* for use in other TPM2 functions. | ||
void* inner_context_object(); | ||
|
||
private: | ||
TPM2_Context(const char* tcti_nameconf); | ||
|
||
private: | ||
struct Impl; // PImpl to avoid TPM2-TSS includes in this header | ||
std::unique_ptr<Impl> m_impl; | ||
}; | ||
|
||
} // namespace Botan | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* TPM 2 RNG interface | ||
* (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) | ||
*/ | ||
|
||
#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> | ||
|
||
namespace Botan { | ||
|
||
void TPM2_RNG::fill_bytes_with_input(std::span<uint8_t> output, std::span<const uint8_t> input) { | ||
constexpr size_t MAX_STIR_RANDOM_SIZE = 128; // From specification of tpm2-tool's tpm2_stirrandom | ||
|
||
BufferSlicer in(input); | ||
|
||
while(!in.empty()) { | ||
TPM2B_SENSITIVE_DATA data; | ||
data.size = std::min(in.remaining(), MAX_STIR_RANDOM_SIZE); | ||
in.copy_into({data.buffer, data.size}); | ||
|
||
check_tss2_rc("StirRandom", Esys_StirRandom(inner(m_ctx), 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(inner(m_ctx), 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); }); | ||
|
||
BOTAN_ASSERT_NOMSG(digest->size == requested_bytes); | ||
out.append({digest->buffer, digest->size}); | ||
} | ||
} | ||
|
||
} // namespace Botan |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... we've been specific basically everywhere. I think we should always state TPM2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #4117 (comment) - this FFI error translates the
ErrorType::TPMError
, which is also the error type forTPM2_Error
. Or should we just introduce a new TPM2ErrorType
and keep them separated entirely?