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

randombit / botan / 16248620128

13 Jul 2025 11:27AM UTC coverage: 90.565% (-0.01%) from 90.575%
16248620128

push

github

web-flow
Merge pull request #4983 from randombit/jack/clang-tidy-cppcoreguidelines-owning-memory

Enable and fix clang-tidy warning cppcoreguidelines-owning-memory

99026 of 109342 relevant lines covered (90.57%)

12444574.04 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/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

25
extern "C" {
26

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

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

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

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

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

50
}  // extern "C"
51

52
namespace {
53

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

60
}  // namespace
61

62
extern "C" {
63

64
#endif
65

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

74
int 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) {
×
78
         return BOTAN_FFI_ERROR_NULL_POINTER;
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);
95
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
96
#endif
97
}
98

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

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

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

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

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

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

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

167
/**
168
 * Frees all resouces 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
      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