Botan 3.7.1
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 *ctx_out = new botan_tpm2_ctx_struct(std::move(ctx));
92 return BOTAN_FFI_SUCCESS;
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 *ctx_out = new botan_tpm2_ctx_struct(std::move(ctx));
126 return BOTAN_FFI_SUCCESS;
127 });
128#else
129 BOTAN_UNUSED(ctx_out, tcti_name, tcti_conf);
131#endif
132}
133
134int botan_tpm2_ctx_from_esys(botan_tpm2_ctx_t* ctx_out, ESYS_CONTEXT* esys_ctx) {
135#if defined(BOTAN_HAS_TPM2)
136 return ffi_guard_thunk(__func__, [=]() -> int {
137 if(ctx_out == nullptr || esys_ctx == nullptr) {
139 }
140
141 auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
142 ctx->ctx = Botan::TPM2::Context::create(esys_ctx);
143 *ctx_out = new botan_tpm2_ctx_struct(std::move(ctx));
144 return BOTAN_FFI_SUCCESS;
145 });
146#else
147 BOTAN_UNUSED(ctx_out, esys_ctx);
149#endif
150}
151
153#if defined(BOTAN_HAS_TPM2)
154 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
156
157 // The lifetime of the RNG used for the crypto backend should be managed
158 // by the TPM2::Context. Here, we just need to trust the user that they
159 // keep the passed-in RNG instance intact for the lifetime of the context.
160 std::shared_ptr<Botan::RandomNumberGenerator> rng_ptr(&rng_ref, [](auto*) {});
161 ctx_wrapper.ctx->use_botan_crypto_backend(rng_ptr);
162 return BOTAN_FFI_SUCCESS;
163 });
164#else
165 BOTAN_UNUSED(ctx, rng);
167#endif
168}
169
170/**
171 * Frees all resouces of a TPM2 context
172 * @param ctx TPM2 context
173 * @return 0 on success
174 */
176#if defined(BOTAN_HAS_TPM2)
177 return BOTAN_FFI_CHECKED_DELETE(ctx);
178#else
179 BOTAN_UNUSED(ctx);
181#endif
182}
183
185 ESYS_CONTEXT* esys_ctx,
186 botan_rng_t rng) {
187#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
188 return ffi_guard_thunk(__func__, [=]() -> int {
189 if(cbs_out == nullptr || esys_ctx == nullptr) {
191 }
192
194
195 // Here, we just need to trust the user that they keep the passed-in RNG
196 // instance intact for the lifetime of the context.
197 std::shared_ptr<Botan::RandomNumberGenerator> rng_ptr(&rng_ref, [](auto*) {});
198 *cbs_out = new botan_tpm2_crypto_backend_state_struct(Botan::TPM2::use_botan_crypto_backend(esys_ctx, rng_ptr));
199 return BOTAN_FFI_SUCCESS;
200 });
201#else
202 BOTAN_UNUSED(cbs_out, esys_ctx, rng);
204#endif
205}
206
208#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
209 return BOTAN_FFI_CHECKED_DELETE(cbs);
210#else
211 BOTAN_UNUSED(cbs);
213#endif
214}
215
221#if defined(BOTAN_HAS_TPM2)
222 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
223 if(rng_out == nullptr) {
225 }
226
227 *rng_out = new botan_rng_struct(
228 std::make_unique<Botan::TPM2::RandomNumberGenerator>(ctx_wrapper.ctx, sessions(s1, s2, s3)));
229 return BOTAN_FFI_SUCCESS;
230 });
231#else
232 BOTAN_UNUSED(rng_out, ctx, s1, s2, s3);
234#endif
235}
236
238#if defined(BOTAN_HAS_TPM2)
239 return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
240 if(session_out == nullptr) {
242 }
243
244 auto session = std::make_unique<botan_tpm2_session_wrapper>();
245 session->session = Botan::TPM2::Session::unauthenticated_session(ctx_wrapper.ctx);
246 *session_out = new botan_tpm2_session_struct(std::move(session));
247 return BOTAN_FFI_SUCCESS;
248 });
249#else
250 BOTAN_UNUSED(session_out, ctx);
252#endif
253}
254
256#if defined(BOTAN_HAS_TPM2)
257 return BOTAN_FFI_CHECKED_DELETE(session);
258#else
259 BOTAN_UNUSED(session);
261#endif
262}
263}
#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:2284
struct botan_tpm2_ctx_struct * botan_tpm2_ctx_t
Definition ffi.h:2279
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
struct botan_tpm2_crypto_backend_state_struct * botan_tpm2_crypto_backend_state_t
Definition ffi.h:2289
int botan_tpm2_ctx_enable_crypto_backend(botan_tpm2_ctx_t ctx, botan_rng_t rng)
Definition ffi_tpm2.cpp:152
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: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:216
int botan_tpm2_ctx_from_esys(botan_tpm2_ctx_t *ctx_out, ESYS_CONTEXT *esys_ctx)
Definition ffi_tpm2.cpp:134
int botan_tpm2_ctx_destroy(botan_tpm2_ctx_t ctx)
Definition ffi_tpm2.cpp:175
int botan_tpm2_unauthenticated_session_init(botan_tpm2_session_t *session_out, botan_tpm2_ctx_t ctx)
Definition ffi_tpm2.cpp:237
int botan_tpm2_crypto_backend_state_destroy(botan_tpm2_crypto_backend_state_t cbs)
Definition ffi_tpm2.cpp:207
int botan_tpm2_session_destroy(botan_tpm2_session_t session)
Definition ffi_tpm2.cpp:255
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:184
int botan_tpm2_supports_crypto_backend()
Definition ffi_tpm2.cpp:66
#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
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:63
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition ffi.cpp:128