Botan 3.9.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
20 #if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
21 #include <botan/tpm2_crypto_backend.h>
22 #endif
23#endif
24
25extern "C" {
26
27using namespace Botan_FFI;
28
29#if defined(BOTAN_HAS_TPM2)
30
31// These wrappers are required since BOTAN_FFI_DECLARE_STRUCT internally
32// produces a unique pointer, but the TPM types are meant to be used as
33// shared pointers.
34
35struct botan_tpm2_ctx_wrapper {
36 std::shared_ptr<Botan::TPM2::Context> ctx;
37};
38
39struct botan_tpm2_session_wrapper {
40 std::shared_ptr<Botan::TPM2::Session> session;
41};
42
43BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_ctx_struct, botan_tpm2_ctx_wrapper, 0xD2B95E15);
44BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_session_struct, botan_tpm2_session_wrapper, 0x9ACCAB52);
45
46 #if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
47BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_crypto_backend_state_struct, Botan::TPM2::CryptoCallbackState, 0x1AC84DE5);
48 #endif
49
50} // extern "C"
51
52namespace {
53
55 return Botan::TPM2::SessionBundle((s1 != nullptr) ? safe_get(s1).session : nullptr,
56 (s2 != nullptr) ? safe_get(s2).session : nullptr,
57 (s3 != nullptr) ? safe_get(s3).session : nullptr);
58}
59
60} // namespace
61
62extern "C" {
63
64#endif
65
67#if defined(BOTAN_HAS_TPM2)
69#else
70 return 0;
71#endif
72}
73
74int botan_tpm2_ctx_init(botan_tpm2_ctx_t* ctx_out, const char* tcti_nameconf) {
75#if defined(BOTAN_HAS_TPM2)
76 return ffi_guard_thunk(__func__, [=]() -> int {
77 if(ctx_out == nullptr) {
79 }
80 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
81
82 auto tcti = [=]() -> std::optional<std::string> {
83 if(tcti_nameconf == nullptr) {
84 return {};
85 } else {
86 return std::string(tcti_nameconf);
87 }
88 }();
89
90 ctx->ctx = Botan::TPM2::Context::create(std::move(tcti));
91 return ffi_new_object(ctx_out, std::move(ctx));
92 });
93#else
94 BOTAN_UNUSED(ctx_out, tcti_nameconf);
96#endif
97}
98
99int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t* ctx_out, const char* tcti_name, const char* tcti_conf) {
100#if defined(BOTAN_HAS_TPM2)
101 return ffi_guard_thunk(__func__, [=]() -> int {
102 if(ctx_out == nullptr) {
104 }
105 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
106
107 auto tcti_name_str = [=]() -> std::optional<std::string> {
108 if(tcti_name == nullptr) {
109 return {};
110 } else {
111 return std::string(tcti_name);
112 }
113 }();
114
115 auto tcti_conf_str = [=]() -> std::optional<std::string> {
116 if(tcti_conf == nullptr) {
117 return {};
118 } else {
119 return std::string(tcti_conf);
120 }
121 }();
122
123 ctx->ctx = Botan::TPM2::Context::create(std::move(tcti_name_str), std::move(tcti_conf_str));
124 return ffi_new_object(ctx_out, std::move(ctx));
125 });
126#else
127 BOTAN_UNUSED(ctx_out, tcti_name, tcti_conf);
129#endif
130}
131
132int botan_tpm2_ctx_from_esys(botan_tpm2_ctx_t* ctx_out, ESYS_CONTEXT* esys_ctx) {
133#if defined(BOTAN_HAS_TPM2)
134 return ffi_guard_thunk(__func__, [=]() -> int {
135 if(ctx_out == nullptr || esys_ctx == nullptr) {
137 }
138
139 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
140 ctx->ctx = Botan::TPM2::Context::create(esys_ctx);
141 return ffi_new_object(ctx_out, std::move(ctx));
142 });
143#else
144 BOTAN_UNUSED(ctx_out, esys_ctx);
146#endif
147}
148
150#if defined(BOTAN_HAS_TPM2)
151 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
153
154 // The lifetime of the RNG used for the crypto backend should be managed
155 // by the TPM2::Context. Here, we just need to trust the user that they
156 // keep the passed-in RNG instance intact for the lifetime of the context.
157 std::shared_ptr<Botan::RandomNumberGenerator> rng_ptr(&rng_ref, [](auto*) {});
158 ctx_wrapper.ctx->use_botan_crypto_backend(rng_ptr);
159 return BOTAN_FFI_SUCCESS;
160 });
161#else
162 BOTAN_UNUSED(ctx, rng);
164#endif
165}
166
167/**
168 * Frees all resouces of a TPM2 context
169 * @param ctx TPM2 context
170 * @return 0 on success
171 */
173#if defined(BOTAN_HAS_TPM2)
174 return BOTAN_FFI_CHECKED_DELETE(ctx);
175#else
176 BOTAN_UNUSED(ctx);
178#endif
179}
180
182 ESYS_CONTEXT* esys_ctx,
183 botan_rng_t rng) {
184#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
185 return ffi_guard_thunk(__func__, [=]() -> int {
186 if(cbs_out == nullptr || esys_ctx == nullptr) {
188 }
189
191
192 // Here, we just need to trust the user that they keep the passed-in RNG
193 // instance intact for the lifetime of the context.
194 std::shared_ptr<Botan::RandomNumberGenerator> rng_ptr(&rng_ref, [](auto*) {});
195 return ffi_new_object(cbs_out, Botan::TPM2::use_botan_crypto_backend(esys_ctx, rng_ptr));
196 });
197#else
198 BOTAN_UNUSED(cbs_out, esys_ctx, rng);
200#endif
201}
202
204#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
205 return BOTAN_FFI_CHECKED_DELETE(cbs);
206#else
207 BOTAN_UNUSED(cbs);
209#endif
210}
211
217#if defined(BOTAN_HAS_TPM2)
218 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
219 if(rng_out == nullptr) {
221 }
222
223 return ffi_new_object(
224 rng_out, std::make_unique<Botan::TPM2::RandomNumberGenerator>(ctx_wrapper.ctx, sessions(s1, s2, s3)));
225 });
226#else
227 BOTAN_UNUSED(rng_out, ctx, s1, s2, s3);
229#endif
230}
231
233#if defined(BOTAN_HAS_TPM2)
234 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
235 if(session_out == nullptr) {
237 }
238
239 auto session = std::make_unique<botan_tpm2_session_wrapper>();
240 session->session = Botan::TPM2::Session::unauthenticated_session(ctx_wrapper.ctx);
241 return ffi_new_object(session_out, std::move(session));
242 });
243#else
244 BOTAN_UNUSED(session_out, ctx);
246#endif
247}
248
250#if defined(BOTAN_HAS_TPM2)
251 return BOTAN_FFI_CHECKED_DELETE(session);
252#else
253 BOTAN_UNUSED(session);
255#endif
256}
257}
#define BOTAN_UNUSED
Definition assert.h:144
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:2543
struct botan_tpm2_ctx_struct * botan_tpm2_ctx_t
Definition ffi.h:2538
struct botan_rng_struct * botan_rng_t
Definition ffi.h:289
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:138
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:132
@ BOTAN_FFI_SUCCESS
Definition ffi.h:115
struct botan_tpm2_crypto_backend_state_struct * botan_tpm2_crypto_backend_state_t
Definition ffi.h:2548
int botan_tpm2_ctx_enable_crypto_backend(botan_tpm2_ctx_t ctx, botan_rng_t rng)
Definition ffi_tpm2.cpp:149
int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t *ctx_out, const char *tcti_name, const char *tcti_conf)
Definition ffi_tpm2.cpp:99
int botan_tpm2_ctx_init(botan_tpm2_ctx_t *ctx_out, const char *tcti_nameconf)
Definition ffi_tpm2.cpp:74
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:212
int botan_tpm2_ctx_from_esys(botan_tpm2_ctx_t *ctx_out, ESYS_CONTEXT *esys_ctx)
Definition ffi_tpm2.cpp:132
int botan_tpm2_ctx_destroy(botan_tpm2_ctx_t ctx)
Definition ffi_tpm2.cpp:172
int botan_tpm2_unauthenticated_session_init(botan_tpm2_session_t *session_out, botan_tpm2_ctx_t ctx)
Definition ffi_tpm2.cpp:232
int botan_tpm2_crypto_backend_state_destroy(botan_tpm2_crypto_backend_state_t cbs)
Definition ffi_tpm2.cpp:203
int botan_tpm2_session_destroy(botan_tpm2_session_t session)
Definition ffi_tpm2.cpp:249
int botan_tpm2_enable_crypto_backend(botan_tpm2_crypto_backend_state_t *cbs_out, ESYS_CONTEXT *esys_ctx, botan_rng_t rng)
Definition ffi_tpm2.cpp:181
int botan_tpm2_supports_crypto_backend()
Definition ffi_tpm2.cpp:66
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:158
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:185
#define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC)
Definition ffi_util.h:61
std::unique_ptr< CryptoCallbackState > use_botan_crypto_backend(ESYS_CONTEXT *context, const std::shared_ptr< Botan::RandomNumberGenerator > &rng)
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:79
BOTAN_FFI_ERROR ffi_new_object(T *obj, Args &&... args)
Definition ffi_util.h:178
int ffi_guard_thunk(const char *func_name, T thunk)
Definition ffi_util.h:95