Botan 3.11.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/assert.h>
11#include <botan/internal/ffi_pkey.h>
12#include <botan/internal/ffi_rng.h>
13#include <botan/internal/ffi_util.h>
14
15#if defined(BOTAN_HAS_TPM2)
16 #include <botan/tpm2_context.h>
17 #include <botan/tpm2_key.h>
18 #include <botan/tpm2_rng.h>
19 #include <botan/tpm2_session.h>
20
21 #if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
22 #include <botan/tpm2_crypto_backend.h>
23 #endif
24#endif
25
26extern "C" {
27
28using namespace Botan_FFI;
29
30#if defined(BOTAN_HAS_TPM2)
31
32// These wrappers are required since BOTAN_FFI_DECLARE_STRUCT internally
33// produces a unique pointer, but the TPM types are meant to be used as
34// shared pointers.
35
36struct botan_tpm2_ctx_wrapper {
37 std::shared_ptr<Botan::TPM2::Context> ctx;
38};
39
40struct botan_tpm2_session_wrapper {
41 std::shared_ptr<Botan::TPM2::Session> session;
42};
43
44BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_ctx_struct, botan_tpm2_ctx_wrapper, 0xD2B95E15);
45BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_session_struct, botan_tpm2_session_wrapper, 0x9ACCAB52);
46
47 #if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
48BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_crypto_backend_state_struct, Botan::TPM2::CryptoCallbackState, 0x1AC84DE5);
49 #endif
50
51} // extern "C"
52
53namespace {
54
56 return Botan::TPM2::SessionBundle((s1 != nullptr) ? safe_get(s1).session : nullptr,
57 (s2 != nullptr) ? safe_get(s2).session : nullptr,
58 (s3 != nullptr) ? safe_get(s3).session : nullptr);
59}
60
61} // namespace
62
63extern "C" {
64
65#endif
66
68#if defined(BOTAN_HAS_TPM2)
70#else
71 return 0;
72#endif
73}
74
75int botan_tpm2_ctx_init(botan_tpm2_ctx_t* ctx_out, const char* tcti_nameconf) {
76#if defined(BOTAN_HAS_TPM2)
77 return ffi_guard_thunk(__func__, [=]() -> int {
78 if(ctx_out == nullptr) {
80 }
81 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
82
83 auto tcti = [=]() -> std::optional<std::string> {
84 if(tcti_nameconf == nullptr) {
85 return {};
86 } else {
87 return std::string(tcti_nameconf);
88 }
89 }();
90
91 ctx->ctx = Botan::TPM2::Context::create(std::move(tcti));
92 return ffi_new_object(ctx_out, std::move(ctx));
93 });
94#else
95 BOTAN_UNUSED(ctx_out, tcti_nameconf);
97#endif
98}
99
100int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t* ctx_out, const char* tcti_name, const char* tcti_conf) {
101#if defined(BOTAN_HAS_TPM2)
102 return ffi_guard_thunk(__func__, [=]() -> int {
103 if(ctx_out == nullptr) {
105 }
106 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
107
108 auto tcti_name_str = [=]() -> std::optional<std::string> {
109 if(tcti_name == nullptr) {
110 return {};
111 } else {
112 return std::string(tcti_name);
113 }
114 }();
115
116 auto tcti_conf_str = [=]() -> std::optional<std::string> {
117 if(tcti_conf == nullptr) {
118 return {};
119 } else {
120 return std::string(tcti_conf);
121 }
122 }();
123
124 ctx->ctx = Botan::TPM2::Context::create(std::move(tcti_name_str), std::move(tcti_conf_str));
125 return ffi_new_object(ctx_out, std::move(ctx));
126 });
127#else
128 BOTAN_UNUSED(ctx_out, tcti_name, tcti_conf);
130#endif
131}
132
133int botan_tpm2_ctx_from_esys(botan_tpm2_ctx_t* ctx_out, ESYS_CONTEXT* esys_ctx) {
134#if defined(BOTAN_HAS_TPM2)
135 return ffi_guard_thunk(__func__, [=]() -> int {
136 if(ctx_out == nullptr || esys_ctx == nullptr) {
138 }
139
140 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
141 ctx->ctx = Botan::TPM2::Context::create(esys_ctx);
142 return ffi_new_object(ctx_out, std::move(ctx));
143 });
144#else
145 BOTAN_UNUSED(ctx_out, esys_ctx);
147#endif
148}
149
151#if defined(BOTAN_HAS_TPM2)
152 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
154
155 // The lifetime of the RNG used for the crypto backend should be managed
156 // by the TPM2::Context. Here, we just need to trust the user that they
157 // keep the passed-in RNG instance intact for the lifetime of the context.
158 ctx_wrapper.ctx->use_botan_crypto_backend(std::shared_ptr<Botan::RandomNumberGenerator>(&rng_ref, [](auto*) {}));
159 return BOTAN_FFI_SUCCESS;
160 });
161#else
162 BOTAN_UNUSED(ctx, rng);
164#endif
165}
166
167/**
168 * Frees all resources 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 const 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:3036
struct botan_tpm2_ctx_struct * botan_tpm2_ctx_t
Definition ffi.h:3031
struct botan_rng_struct * botan_rng_t
Definition ffi.h:291
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:140
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:133
@ BOTAN_FFI_SUCCESS
Definition ffi.h:116
struct botan_tpm2_crypto_backend_state_struct * botan_tpm2_crypto_backend_state_t
Definition ffi.h:3041
int botan_tpm2_ctx_enable_crypto_backend(botan_tpm2_ctx_t ctx, botan_rng_t rng)
Definition ffi_tpm2.cpp:150
int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t *ctx_out, const char *tcti_name, const char *tcti_conf)
Definition ffi_tpm2.cpp:100
int botan_tpm2_ctx_init(botan_tpm2_ctx_t *ctx_out, const char *tcti_nameconf)
Definition ffi_tpm2.cpp:75
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:133
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:67
#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