• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 21850311256

10 Feb 2026 03:17AM UTC coverage: 91.635% (+0.001%) from 91.634%
21850311256

Pull #5302

github

web-flow
Merge 26bacb252 into 1d119e57a
Pull Request #5302: Cleanup various header inclusions

104007 of 113502 relevant lines covered (91.63%)

11071649.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.76
/src/lib/ffi/ffi_tpm2.cpp
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

26
extern "C" {
27

28
using 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

36
struct botan_tpm2_ctx_wrapper {
7✔
37
      std::shared_ptr<Botan::TPM2::Context> ctx;
38
};
39

40
struct botan_tpm2_session_wrapper {
7✔
41
      std::shared_ptr<Botan::TPM2::Session> session;
42
};
43

44
BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_ctx_struct, botan_tpm2_ctx_wrapper, 0xD2B95E15);
3✔
45
BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_session_struct, botan_tpm2_session_wrapper, 0x9ACCAB52);
3✔
46

47
   #if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
48
BOTAN_FFI_DECLARE_STRUCT(botan_tpm2_crypto_backend_state_struct, Botan::TPM2::CryptoCallbackState, 0x1AC84DE5);
1✔
49
   #endif
50

51
}  // extern "C"
52

53
namespace {
54

55
Botan::TPM2::SessionBundle sessions(botan_tpm2_session_t s1, botan_tpm2_session_t s2, botan_tpm2_session_t s3) {
6✔
56
   return Botan::TPM2::SessionBundle((s1 != nullptr) ? safe_get(s1).session : nullptr,
6✔
57
                                     (s2 != nullptr) ? safe_get(s2).session : nullptr,
12✔
58
                                     (s3 != nullptr) ? safe_get(s3).session : nullptr);
12✔
59
}
60

61
}  // namespace
62

63
extern "C" {
64

65
#endif
66

67
int botan_tpm2_supports_crypto_backend() {
3✔
68
#if defined(BOTAN_HAS_TPM2)
69
   return Botan::TPM2::Context::supports_botan_crypto_backend() ? 1 : 0;
3✔
70
#else
71
   return 0;
72
#endif
73
}
74

75
int 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) {
×
79
         return BOTAN_FFI_ERROR_NULL_POINTER;
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);
96
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
97
#endif
98
}
99

100
int botan_tpm2_ctx_init_ex(botan_tpm2_ctx_t* ctx_out, const char* tcti_name, const char* tcti_conf) {
2✔
101
#if defined(BOTAN_HAS_TPM2)
102
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
103
      if(ctx_out == nullptr) {
2✔
104
         return BOTAN_FFI_ERROR_NULL_POINTER;
105
      }
106
      auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
2✔
107

108
      auto tcti_name_str = [=]() -> std::optional<std::string> {
×
109
         if(tcti_name == nullptr) {
2✔
110
            return {};
×
111
         } else {
112
            return std::string(tcti_name);
4✔
113
         }
114
      }();
2✔
115

116
      auto tcti_conf_str = [=]() -> std::optional<std::string> {
×
117
         if(tcti_conf == nullptr) {
2✔
118
            return {};
×
119
         } else {
120
            return std::string(tcti_conf);
4✔
121
         }
122
      }();
2✔
123

124
      ctx->ctx = Botan::TPM2::Context::create(std::move(tcti_name_str), std::move(tcti_conf_str));
8✔
125
      return ffi_new_object(ctx_out, std::move(ctx));
2✔
126
   });
4✔
127
#else
128
   BOTAN_UNUSED(ctx_out, tcti_name, tcti_conf);
129
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
130
#endif
131
}
132

133
int botan_tpm2_ctx_from_esys(botan_tpm2_ctx_t* ctx_out, ESYS_CONTEXT* esys_ctx) {
1✔
134
#if defined(BOTAN_HAS_TPM2)
135
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
136
      if(ctx_out == nullptr || esys_ctx == nullptr) {
1✔
137
         return BOTAN_FFI_ERROR_NULL_POINTER;
138
      }
139

140
      auto ctx = std::make_unique<botan_tpm2_ctx_wrapper>();
1✔
141
      ctx->ctx = Botan::TPM2::Context::create(esys_ctx);
1✔
142
      return ffi_new_object(ctx_out, std::move(ctx));
1✔
143
   });
1✔
144
#else
145
   BOTAN_UNUSED(ctx_out, esys_ctx);
146
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
147
#endif
148
}
149

150
int botan_tpm2_ctx_enable_crypto_backend(botan_tpm2_ctx_t ctx, botan_rng_t rng) {
2✔
151
#if defined(BOTAN_HAS_TPM2)
152
   return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
6✔
153
      Botan::RandomNumberGenerator& rng_ref = safe_get(rng);
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);
163
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
164
#endif
165
}
166

167
/**
168
 * Frees all resources of a TPM2 context
169
 * @param ctx TPM2 context
170
 * @return 0 on success
171
 */
172
int botan_tpm2_ctx_destroy(botan_tpm2_ctx_t ctx) {
2✔
173
#if defined(BOTAN_HAS_TPM2)
174
   return BOTAN_FFI_CHECKED_DELETE(ctx);
2✔
175
#else
176
   BOTAN_UNUSED(ctx);
177
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
178
#endif
179
}
180

181
int botan_tpm2_enable_crypto_backend(botan_tpm2_crypto_backend_state_t* cbs_out,
1✔
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 {
1✔
186
      if(cbs_out == nullptr || esys_ctx == nullptr) {
1✔
187
         return BOTAN_FFI_ERROR_NULL_POINTER;
188
      }
189

190
      Botan::RandomNumberGenerator& rng_ref = safe_get(rng);
1✔
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*) {});
1✔
195
      return ffi_new_object(cbs_out, Botan::TPM2::use_botan_crypto_backend(esys_ctx, rng_ptr));
1✔
196
   });
1✔
197
#else
198
   BOTAN_UNUSED(cbs_out, esys_ctx, rng);
199
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
200
#endif
201
}
202

203
int botan_tpm2_crypto_backend_state_destroy(botan_tpm2_crypto_backend_state_t cbs) {
1✔
204
#if defined(BOTAN_HAS_TPM2_CRYPTO_BACKEND)
205
   return BOTAN_FFI_CHECKED_DELETE(cbs);
1✔
206
#else
207
   BOTAN_UNUSED(cbs);
208
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
209
#endif
210
}
211

212
int botan_tpm2_rng_init(botan_rng_t* rng_out,
6✔
213
                        botan_tpm2_ctx_t ctx,
214
                        botan_tpm2_session_t s1,
215
                        botan_tpm2_session_t s2,
216
                        botan_tpm2_session_t s3) {
217
#if defined(BOTAN_HAS_TPM2)
218
   return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
18✔
219
      if(rng_out == nullptr) {
220
         return BOTAN_FFI_ERROR_NULL_POINTER;
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);
228
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
229
#endif
230
}
231

232
int botan_tpm2_unauthenticated_session_init(botan_tpm2_session_t* session_out, botan_tpm2_ctx_t ctx) {
3✔
233
#if defined(BOTAN_HAS_TPM2)
234
   return BOTAN_FFI_VISIT(ctx, [=](botan_tpm2_ctx_wrapper& ctx_wrapper) -> int {
6✔
235
      if(session_out == nullptr) {
236
         return BOTAN_FFI_ERROR_NULL_POINTER;
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);
245
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
246
#endif
247
}
248

249
int botan_tpm2_session_destroy(botan_tpm2_session_t session) {
2✔
250
#if defined(BOTAN_HAS_TPM2)
251
   return BOTAN_FFI_CHECKED_DELETE(session);
2✔
252
#else
253
   BOTAN_UNUSED(session);
254
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
255
#endif
256
}
257
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc