Botan 3.6.0
Crypto and TLS for C&
ffi_tpm2.cpp
Go to the documentation of this file.
1/*
2* (C) 2024 Jack Lloyd
3* (C) 2024 René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity GmbH
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/ffi.h>
9
10#include <botan/internal/ffi_pkey.h>
11#include <botan/internal/ffi_rng.h>
12#include <botan/internal/ffi_util.h>
13
14#if defined(BOTAN_HAS_TPM2)
15 #include <botan/tpm2_context.h>
16 #include <botan/tpm2_key.h>
17 #include <botan/tpm2_rng.h>
18 #include <botan/tpm2_session.h>
19#endif
20
21extern "C" {
22
23using namespace Botan_FFI;
24
25#if defined(BOTAN_HAS_TPM2)
26
27// These wrappers are required since BOTAN_FFI_DECLARE_STRUCT internally
28// produces a unique pointer, but the TPM types are meant to be used as
29// shared pointers.
30
31struct botan_tpm2_ctx_wrapper {
32 std::shared_ptr<Botan::TPM2::Context> ctx;
33};
34
35struct botan_tpm2_session_wrapper {
36 std::shared_ptr<Botan::TPM2::Session> session;
37};
38
39BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_ctx_struct, botan_tpm2_ctx_wrapper, 0xD2B95E15);
40BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_session_struct, botan_tpm2_session_wrapper, 0x9ACCAB52);
41
42} // extern "C"
43
44namespace {
45
47 return Botan::TPM2::SessionBundle((s1 != nullptr) ? safe_get(s1).session : nullptr,
48 (s2 != nullptr) ? safe_get(s2).session : nullptr,
49 (s3 != nullptr) ? safe_get(s3).session : nullptr);
50}
51
52} // namespace
53
54extern "C" {
55
56#endif
57
59#if defined(BOTAN_HAS_TPM2)
61#else
62 return 0;
63#endif
64}
65
66int botan_tpm2_ctx_init(botan_tpm2_ctx_t* ctx_out, const char* tcti_nameconf) {
67#if defined(BOTAN_HAS_TPM2)
68 return ffi_guard_thunk(__func__, [=]() -> int {
69 if(ctx_out == nullptr) {
71 }
72 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
73
74 auto tcti = [=]() -> std::optional<std::string> {
75 if(tcti_nameconf == nullptr) {
76 return {};
77 } else {
78 return std::string(tcti_nameconf);
79 }
80 }();
81
82 ctx->ctx = Botan::TPM2::Context::create(std::move(tcti));
83 *ctx_out = new botan_tpm2_ctx_struct(std::move(ctx));
84 return BOTAN_FFI_SUCCESS;
85 });
86#else
87 BOTAN_UNUSED(ctx_out, tcti_nameconf);
89#endif
90}
91
92int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t* ctx_out, const char* tcti_name, const char* tcti_conf) {
93#if defined(BOTAN_HAS_TPM2)
94 return ffi_guard_thunk(__func__, [=]() -> int {
95 if(ctx_out == nullptr) {
97 }
98 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
99
100 auto tcti_name_str = [=]() -> std::optional<std::string> {
101 if(tcti_name == nullptr) {
102 return {};
103 } else {
104 return std::string(tcti_name);
105 }
106 }();
107
108 auto tcti_conf_str = [=]() -> std::optional<std::string> {
109 if(tcti_conf == nullptr) {
110 return {};
111 } else {
112 return std::string(tcti_conf);
113 }
114 }();
115
116 ctx->ctx = Botan::TPM2::Context::create(std::move(tcti_name_str), std::move(tcti_conf_str));
117 *ctx_out = new botan_tpm2_ctx_struct(std::move(ctx));
118 return BOTAN_FFI_SUCCESS;
119 });
120#else
121 BOTAN_UNUSED(ctx_out, tcti_name, tcti_conf);
123#endif
124}
125
127#if defined(BOTAN_HAS_TPM2)
128 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
130
131 // The lifetime of the RNG used for the crypto backend should be managed
132 // by the TPM2::Context. Here, we just need to trust the user that they
133 // keep the passed-in RNG instance intact for the lifetime of the context.
134 std::shared_ptr<Botan::RandomNumberGenerator> rng_ptr(&rng_ref, [](auto*) {});
135 ctx_wrapper.ctx->use_botan_crypto_backend(rng_ptr);
136 return BOTAN_FFI_SUCCESS;
137 });
138#else
139 BOTAN_UNUSED(ctx, rng);
141#endif
142}
143
144/**
145 * Frees all resouces of a TPM2 context
146 * @param ctx TPM2 context
147 * @return 0 on success
148 */
150#if defined(BOTAN_HAS_TPM2)
151 return BOTAN_FFI_CHECKED_DELETE(ctx);
152#else
153 BOTAN_UNUSED(ctx);
155#endif
156}
157
163#if defined(BOTAN_HAS_TPM2)
164 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
165 if(rng_out == nullptr) {
167 }
168
169 *rng_out = new botan_rng_struct(
170 std::make_unique<Botan::TPM2::RandomNumberGenerator>(ctx_wrapper.ctx, sessions(s1, s2, s3)));
171 return BOTAN_FFI_SUCCESS;
172 });
173#else
174 BOTAN_UNUSED(rng_out, ctx, s1, s2, s3);
176#endif
177}
178
180#if defined(BOTAN_HAS_TPM2)
181 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
182 if(session_out == nullptr) {
184 }
185
186 auto session = std::make_unique<botan_tpm2_session_wrapper>();
187 session->session = Botan::TPM2::Session::unauthenticated_session(ctx_wrapper.ctx);
188 *session_out = new botan_tpm2_session_struct(std::move(session));
189 return BOTAN_FFI_SUCCESS;
190 });
191#else
192 BOTAN_UNUSED(session_out, ctx);
194#endif
195}
196
198#if defined(BOTAN_HAS_TPM2)
199 return BOTAN_FFI_CHECKED_DELETE(session);
200#else
201 BOTAN_UNUSED(session);
203#endif
204}
205}
#define BOTAN_UNUSED
Definition assert.h:118
static bool supports_botan_crypto_backend() noexcept
static std::shared_ptr< Context > create(const std::string &tcti_nameconf)
static std::shared_ptr< Session > unauthenticated_session(const std::shared_ptr< Context > &ctx, std::string_view sym_algo="CFB(AES-256)", std::string_view hash_algo="SHA-256")
struct botan_tpm2_session_struct * botan_tpm2_session_t
Definition ffi.h:2266
struct botan_tpm2_ctx_struct * botan_tpm2_ctx_t
Definition ffi.h:2261
struct botan_rng_struct * botan_rng_t
Definition ffi.h:272
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:135
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:129
@ BOTAN_FFI_SUCCESS
Definition ffi.h:114
int botan_tpm2_ctx_enable_crypto_backend(botan_tpm2_ctx_t ctx, botan_rng_t rng)
Definition ffi_tpm2.cpp:126
int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t *ctx_out, const char *tcti_name, const char *tcti_conf)
Definition ffi_tpm2.cpp:92
int botan_tpm2_ctx_init(botan_tpm2_ctx_t *ctx_out, const char *tcti_nameconf)
Definition ffi_tpm2.cpp:66
int botan_tpm2_rng_init(botan_rng_t *rng_out, botan_tpm2_ctx_t ctx, botan_tpm2_session_t s1, botan_tpm2_session_t s2, botan_tpm2_session_t s3)
Definition ffi_tpm2.cpp:158
int botan_tpm2_ctx_destroy(botan_tpm2_ctx_t ctx)
Definition ffi_tpm2.cpp:149
int botan_tpm2_unauthenticated_session_init(botan_tpm2_session_t *session_out, botan_tpm2_ctx_t ctx)
Definition ffi_tpm2.cpp:179
int botan_tpm2_session_destroy(botan_tpm2_session_t session)
Definition ffi_tpm2.cpp:197
int botan_tpm2_supports_crypto_backend()
Definition ffi_tpm2.cpp:58
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:124
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:143
#define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC)
Definition ffi_util.h:51
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:63
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition ffi.cpp:118