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

randombit / botan / 16905922066

12 Aug 2025 10:17AM UTC coverage: 90.666% (+0.002%) from 90.664%
16905922066

Pull #4877

github

web-flow
Merge 32b12bb53 into 7fe3a730a
Pull Request #4877: Add FFI for X.509 creation

100754 of 111127 relevant lines covered (90.67%)

12150234.81 hits per line

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

88.83
/src/lib/ffi/ffi_cert.cpp
1
/*
2
* (C) 2015,2017,2018 Jack Lloyd
3
* (C) 2025 Dominik Schricker
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_cert.h>
11
#include <botan/internal/ffi_cert_ext.h>
12
#include <botan/internal/ffi_mp.h>
13
#include <botan/internal/ffi_oid.h>
14
#include <botan/internal/ffi_pkey.h>
15
#include <botan/internal/ffi_rng.h>
16
#include <botan/internal/ffi_util.h>
17
#include <memory>
18

19
namespace {
20
std::chrono::system_clock::time_point timepoint_from_timestamp(uint64_t time_since_epoch) {
21✔
21
   return std::chrono::system_clock::time_point(std::chrono::seconds(time_since_epoch));
4✔
22
}
23

24
Botan::X509_Time time_from_timestamp(uint64_t time_since_epoch) {
12✔
25
   return Botan::X509_Time(timepoint_from_timestamp(time_since_epoch));
18✔
26
}
27

28
template <typename T, typename U>
29
T default_from_ptr(U* value) {
20✔
30
   T ret;
20✔
31
   if(value != nullptr) {
20✔
32
      ret = value;
20✔
33
   }
34
   return ret;
20✔
35
}
×
36

37
template <typename T>
38
std::optional<T> optional_from_ptr(T* value) {
5✔
39
   if(value != nullptr) {
5✔
40
      return *value;
3✔
41
   }
42
   return std::nullopt;
43
}
44

45
std::optional<std::string> optional_from_ptr(const char* value) {
28✔
46
   if(value != nullptr) {
28✔
47
      return std::string(value);
10✔
48
   }
49
   return std::nullopt;
23✔
50
}
51
}  // namespace
52

53
extern "C" {
54

55
using namespace Botan_FFI;
56

57
int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path) {
23✔
58
   if(cert_obj == nullptr || cert_path == nullptr) {
23✔
59
      return BOTAN_FFI_ERROR_NULL_POINTER;
60
   }
61

62
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
63

64
   return ffi_guard_thunk(__func__, [=]() -> int {
23✔
65
      auto c = std::make_unique<Botan::X509_Certificate>(cert_path);
23✔
66
      return ffi_new_object(cert_obj, std::move(c));
23✔
67
   });
46✔
68

69
#else
70
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
71
#endif
72
}
73

74
int botan_x509_cert_dup(botan_x509_cert_t* cert_obj, botan_x509_cert_t cert) {
1✔
75
   if(cert_obj == nullptr) {
1✔
76
      return BOTAN_FFI_ERROR_NULL_POINTER;
77
   }
78

79
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
80

81
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
82
      auto c = std::make_unique<Botan::X509_Certificate>(safe_get(cert));
1✔
83
      return ffi_new_object(cert_obj, std::move(c));
1✔
84
   });
2✔
85

86
#else
87
   BOTAN_UNUSED(cert);
88
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
89
#endif
90
}
91

92
int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert_bits[], size_t cert_bits_len) {
×
93
   if(cert_obj == nullptr || cert_bits == nullptr) {
×
94
      return BOTAN_FFI_ERROR_NULL_POINTER;
95
   }
96

97
#if defined(BOTAN_HAS_X509_CERTIFICATES)
98
   return ffi_guard_thunk(__func__, [=]() -> int {
×
99
      Botan::DataSource_Memory bits(cert_bits, cert_bits_len);
×
100
      auto c = std::make_unique<Botan::X509_Certificate>(bits);
×
101
      return ffi_new_object(cert_obj, std::move(c));
×
102
   });
×
103
#else
104
   BOTAN_UNUSED(cert_bits_len);
105
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
106
#endif
107
}
108

109
int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) {
4✔
110
   if(key == nullptr) {
4✔
111
      return BOTAN_FFI_ERROR_NULL_POINTER;
112
   }
113

114
   *key = nullptr;
4✔
115

116
#if defined(BOTAN_HAS_X509_CERTIFICATES)
117
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
118
      auto public_key = safe_get(cert).subject_public_key();
4✔
119
      return ffi_new_object(key, std::move(public_key));
4✔
120
   });
8✔
121
#else
122
   BOTAN_UNUSED(cert);
123
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
124
#endif
125
}
126

127
int botan_x509_cert_get_issuer_dn(
8✔
128
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
129
#if defined(BOTAN_HAS_X509_CERTIFICATES)
130
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
131
      auto issuer_info = c.issuer_info(key);
132
      if(index < issuer_info.size()) {
133
         // TODO(Botan4) change the type of out and remove this cast
134
         return write_str_output(reinterpret_cast<char*>(out), out_len, c.issuer_info(key).at(index));
135
      } else {
136
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
137
      }
138
   });
139
#else
140
   BOTAN_UNUSED(cert, key, index, out, out_len);
141
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
142
#endif
143
}
144

145
int botan_x509_cert_get_subject_dn(
8✔
146
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
147
#if defined(BOTAN_HAS_X509_CERTIFICATES)
148
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
149
      auto subject_info = c.subject_info(key);
150
      if(index < subject_info.size()) {
151
         // TODO(Botan4) change the type of out and remove this cast
152
         return write_str_output(reinterpret_cast<char*>(out), out_len, c.subject_info(key).at(index));
153
      } else {
154
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
155
      }
156
   });
157
#else
158
   BOTAN_UNUSED(cert, key, index, out, out_len);
159
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
160
#endif
161
}
162

163
int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
164
#if defined(BOTAN_HAS_X509_CERTIFICATES)
165
   return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert);
2✔
166
#else
167
   BOTAN_UNUSED(cert, out, out_len)
168
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
169
#endif
170
}
171

172
int botan_x509_cert_view_as_string(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) {
3✔
173
#if defined(BOTAN_HAS_X509_CERTIFICATES)
174
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return invoke_view_callback(view, ctx, c.to_string()); });
9✔
175
#else
176
   BOTAN_UNUSED(cert, ctx, view);
177
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
178
#endif
179
}
180

181
int botan_x509_cert_view_pem(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) {
×
182
#if defined(BOTAN_HAS_X509_CERTIFICATES)
183
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return invoke_view_callback(view, ctx, c.PEM_encode()); });
×
184
#else
185
   BOTAN_UNUSED(cert, ctx, view);
186
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
187
#endif
188
}
189

190
int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage) {
8✔
191
#if defined(BOTAN_HAS_X509_CERTIFICATES)
192
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
193
      const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
194
      if(c.allowed_usage(k)) {
195
         return BOTAN_FFI_SUCCESS;
196
      }
197
      return 1;
198
   });
199
#else
200
   BOTAN_UNUSED(cert, key_usage);
201
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
202
#endif
203
}
204

205
int botan_x509_cert_get_key_constraints(botan_x509_cert_t cert, uint32_t* usage) {
2✔
206
   if(usage == nullptr) {
2✔
207
      return BOTAN_FFI_ERROR_NULL_POINTER;
208
   }
209

210
#if defined(BOTAN_HAS_X509_CERTIFICATES)
211
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
4✔
212
      *usage = c.constraints().value();
213
      return BOTAN_FFI_SUCCESS;
214
   });
215
#else
216
   BOTAN_UNUSED(cert)
217
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
218
#endif
219
}
220

221
int botan_x509_cert_is_ca(botan_x509_cert_t cert, int* is_ca, size_t* limit) {
×
222
   if(is_ca == nullptr || limit == nullptr) {
×
223
      return BOTAN_FFI_ERROR_NULL_POINTER;
224
   }
225

226
#if defined(BOTAN_HAS_X509_CERTIFICATES)
227
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
×
228
      if(c.is_CA_cert()) {
229
         *is_ca = 1;
230
         *limit = c.path_limit();
231
      } else {
232
         *is_ca = 0;
233
         *limit = 0;
234
      }
235
      return BOTAN_FFI_SUCCESS;
236
   });
237
#else
238
   BOTAN_UNUSED(cert)
239
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
240
#endif
241
}
242

243
int botan_x509_cert_get_ocsp_responder(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) {
×
244
#if defined(BOTAN_HAS_X509_CERTIFICATES)
245
   return BOTAN_FFI_VISIT(cert,
×
246
                          [=](const auto& c) -> int { return invoke_view_callback(view, ctx, c.ocsp_responder()); });
247
#else
248
   BOTAN_UNUSED(cert, ctx, view)
249
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
250
#endif
251
}
252

253
int botan_x509_cert_is_self_signed(botan_x509_cert_t cert, int* out) {
2✔
254
   if(out == nullptr) {
2✔
255
      return BOTAN_FFI_ERROR_NULL_POINTER;
256
   }
257

258
#if defined(BOTAN_HAS_X509_CERTIFICATES)
259
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) {
4✔
260
      if(c.is_self_signed()) {
261
         *out = 1;
262
      } else {
263
         *out = 0;
264
      }
265
      return BOTAN_FFI_SUCCESS;
266
   });
267
#else
268
   BOTAN_UNUSED(cert, out)
269
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
270
#endif
271
}
272

273
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
35✔
274
#if defined(BOTAN_HAS_X509_CERTIFICATES)
275
   return BOTAN_FFI_CHECKED_DELETE(cert);
35✔
276
#else
277
   BOTAN_UNUSED(cert);
278
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
279
#endif
280
}
281

282
int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len) {
3✔
283
#if defined(BOTAN_HAS_X509_CERTIFICATES)
284
   return BOTAN_FFI_VISIT(cert,
6✔
285
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_before().to_string()); });
286
#else
287
   BOTAN_UNUSED(cert, out, out_len);
288
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
289
#endif
290
}
291

292
int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
293
#if defined(BOTAN_HAS_X509_CERTIFICATES)
294
   return BOTAN_FFI_VISIT(cert,
4✔
295
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); });
296
#else
297
   BOTAN_UNUSED(cert, out, out_len);
298
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
299
#endif
300
}
301

302
int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
303
#if defined(BOTAN_HAS_X509_CERTIFICATES)
304
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_before().time_since_epoch(); });
4✔
305
#else
306
   BOTAN_UNUSED(cert, time_since_epoch);
307
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
308
#endif
309
}
310

311
int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
3✔
312
#if defined(BOTAN_HAS_X509_CERTIFICATES)
313
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); });
6✔
314
#else
315
   BOTAN_UNUSED(cert, time_since_epoch);
316
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
317
#endif
318
}
319

320
int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
4✔
321
#if defined(BOTAN_HAS_X509_CERTIFICATES)
322
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); });
8✔
323
#else
324
   BOTAN_UNUSED(cert, out, out_len);
325
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
326
#endif
327
}
328

329
int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len) {
3✔
330
#if defined(BOTAN_HAS_X509_CERTIFICATES)
331
   // TODO(Botan4) change the type of out and remove this cast
332

333
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) {
6✔
334
      return write_str_output(reinterpret_cast<char*>(out), out_len, c.fingerprint(hash));
335
   });
336
#else
337
   BOTAN_UNUSED(cert, hash, out, out_len);
338
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
339
#endif
340
}
341

342
int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
1✔
343
#if defined(BOTAN_HAS_X509_CERTIFICATES)
344
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); });
2✔
345
#else
346
   BOTAN_UNUSED(cert, out, out_len);
347
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
348
#endif
349
}
350

351
int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
352
#if defined(BOTAN_HAS_X509_CERTIFICATES)
353
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
6✔
354
#else
355
   BOTAN_UNUSED(cert, out, out_len);
356
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
357
#endif
358
}
359

360
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
361
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
362
}
363

364
int botan_x509_cert_view_public_key_bits(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
365
#if defined(BOTAN_HAS_X509_CERTIFICATES)
366
   return BOTAN_FFI_VISIT(cert,
6✔
367
                          [=](const auto& c) { return invoke_view_callback(view, ctx, c.subject_public_key_bits()); });
368
#else
369
   BOTAN_UNUSED(cert, ctx, view);
370
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
371
#endif
372
}
373

374
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
6✔
375
   if(hostname == nullptr) {
6✔
376
      return BOTAN_FFI_ERROR_NULL_POINTER;
377
   }
378

379
#if defined(BOTAN_HAS_X509_CERTIFICATES)
380
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
12✔
381
#else
382
   BOTAN_UNUSED(cert);
383
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
384
#endif
385
}
386

387
int botan_x509_cert_verify(int* result_code,
6✔
388
                           botan_x509_cert_t cert,
389
                           const botan_x509_cert_t* intermediates,
390
                           size_t intermediates_len,
391
                           const botan_x509_cert_t* trusted,
392
                           size_t trusted_len,
393
                           const char* trusted_path,
394
                           size_t required_strength,
395
                           const char* hostname_cstr,
396
                           uint64_t reference_time) {
397
   if(required_strength == 0) {
6✔
398
      required_strength = 110;
5✔
399
   }
400

401
#if defined(BOTAN_HAS_X509_CERTIFICATES)
402
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
403
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
6✔
404
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
6✔
405
      const auto validation_time = reference_time == 0
6✔
406
                                      ? std::chrono::system_clock::now()
6✔
407
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
×
408

409
      std::vector<Botan::X509_Certificate> end_certs;
6✔
410
      end_certs.push_back(safe_get(cert));
6✔
411
      for(size_t i = 0; i != intermediates_len; ++i) {
11✔
412
         end_certs.push_back(safe_get(intermediates[i]));
5✔
413
      }
414

415
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
6✔
416
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
6✔
417
      std::vector<Botan::Certificate_Store*> trusted_roots;
6✔
418

419
      if(trusted_path != nullptr && *trusted_path != 0) {
6✔
420
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
421
         trusted_roots.push_back(trusted_from_path.get());
×
422
      }
423

424
      if(trusted_len > 0) {
6✔
425
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
12✔
426
         for(size_t i = 0; i != trusted_len; ++i) {
12✔
427
            trusted_extra->add_certificate(safe_get(trusted[i]));
6✔
428
         }
429
         trusted_roots.push_back(trusted_extra.get());
6✔
430
      }
431

432
      Botan::Path_Validation_Restrictions restrictions(false, required_strength);
12✔
433

434
      auto validation_result =
6✔
435
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
6✔
436

437
      if(result_code != nullptr) {
6✔
438
         *result_code = static_cast<int>(validation_result.result());
6✔
439
      }
440

441
      if(validation_result.successful_validation()) {
6✔
442
         return 0;
443
      } else {
444
         return 1;
3✔
445
      }
446
   });
6✔
447
#else
448
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
449
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
450
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
451
#endif
452
}
453

454
const char* botan_x509_cert_validation_status(int code) {
11✔
455
   if(code < 0) {
11✔
456
      return nullptr;
457
   }
458

459
#if defined(BOTAN_HAS_X509_CERTIFICATES)
460
   Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
461
   return Botan::to_string(sc);
11✔
462
#else
463
   return nullptr;
464
#endif
465
}
466

467
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
6✔
468
   if(crl_obj == nullptr || crl_path == nullptr) {
6✔
469
      return BOTAN_FFI_ERROR_NULL_POINTER;
470
   }
471

472
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
473

474
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
475
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
6✔
476
      return ffi_new_object(crl_obj, std::move(c));
12✔
477
   });
12✔
478

479
#else
480
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
481
#endif
482
}
483

484
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
2✔
485
   if(crl_obj == nullptr || crl_bits == nullptr) {
2✔
486
      return BOTAN_FFI_ERROR_NULL_POINTER;
487
   }
488

489
#if defined(BOTAN_HAS_X509_CERTIFICATES)
490
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
491
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
2✔
492
      auto c = std::make_unique<Botan::X509_CRL>(bits);
2✔
493
      return ffi_new_object(crl_obj, std::move(c));
2✔
494
   });
6✔
495
#else
496
   BOTAN_UNUSED(crl_bits_len);
497
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
498
#endif
499
}
500

501
int botan_x509_crl_create(botan_x509_crl_t* crl_obj,
2✔
502
                          botan_rng_t rng,
503
                          botan_x509_cert_t ca_cert,
504
                          botan_privkey_t ca_key,
505
                          uint64_t issue_time,
506
                          uint32_t next_update,
507
                          const char* hash_fn,
508
                          const char* padding) {
509
   if(crl_obj == nullptr) {
2✔
510
      return BOTAN_FFI_ERROR_NULL_POINTER;
511
   }
512
#if defined(BOTAN_HAS_X509_CERTIFICATES)
513
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
514
      auto& rng_ = safe_get(rng);
2✔
515
      auto ca = Botan::X509_CA(safe_get(ca_cert),
2✔
516
                               safe_get(ca_key),
2✔
517
                               default_from_ptr<std::string>(hash_fn),
2✔
518
                               default_from_ptr<std::string>(padding),
2✔
519
                               rng_);
4✔
520
      auto crl = std::make_unique<Botan::X509_CRL>(
2✔
521
         ca.new_crl(rng_, timepoint_from_timestamp(issue_time), std::chrono::seconds(next_update)));
2✔
522
      return ffi_new_object(crl_obj, std::move(crl));
4✔
523
   });
4✔
524
#else
525
   BOTAN_UNUSED(rng, ca_cert, ca_key, hash_fn, padding, issue_time, next_update);
526
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
527
#endif
528
}
529

530
int botan_x509_crl_update(botan_x509_crl_t* crl_obj,
2✔
531
                          botan_x509_crl_t last_crl,
532
                          botan_rng_t rng,
533
                          botan_x509_cert_t ca_cert,
534
                          botan_privkey_t ca_key,
535
                          uint64_t issue_time,
536
                          uint32_t next_update,
537
                          const botan_x509_cert_t* revoked,
538
                          size_t revoked_len,
539
                          uint8_t reason,
540
                          const char* hash_fn,
541
                          const char* padding) {
542
   if(crl_obj == nullptr) {
2✔
543
      return BOTAN_FFI_ERROR_NULL_POINTER;
544
   }
545
#if defined(BOTAN_HAS_X509_CERTIFICATES)
546
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
547
      if(revoked_len == 0) {
2✔
548
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
549
      }
550
      auto& rng_ = safe_get(rng);
2✔
551
      auto ca = Botan::X509_CA(safe_get(ca_cert),
2✔
552
                               safe_get(ca_key),
2✔
553
                               default_from_ptr<std::string>(hash_fn),
2✔
554
                               default_from_ptr<std::string>(padding),
2✔
555
                               rng_);
4✔
556

557
      std::vector<Botan::CRL_Entry> entries;
2✔
558
      for(size_t i = 0; i < revoked_len; i++) {
4✔
559
         entries.push_back(Botan::CRL_Entry(safe_get(revoked[i]), static_cast<Botan::CRL_Code>(reason)));
4✔
560
      }
561

562
      auto crl = std::make_unique<Botan::X509_CRL>(ca.update_crl(
4✔
563
         safe_get(last_crl), entries, rng_, timepoint_from_timestamp(issue_time), std::chrono::seconds(next_update)));
4✔
564
      return ffi_new_object(crl_obj, std::move(crl));
2✔
565
   });
4✔
566
#else
567
   BOTAN_UNUSED(last_crl, rng, ca_cert, ca_key, hash_fn, padding, issue_time, next_update, revoked_cert, reason);
568
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
569
#endif
570
}
571

572
int botan_x509_crl_get_count(botan_x509_crl_t crl, size_t* count) {
4✔
573
   if(count == nullptr) {
4✔
574
      return BOTAN_FFI_ERROR_NULL_POINTER;
575
   }
576
#if defined(BOTAN_HAS_X509_CERTIFICATES)
577
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) {
8✔
578
      *count = c.get_revoked().size();
579
      return BOTAN_FFI_SUCCESS;
580
   });
581
#else
582
   BOTAN_UNUSED(crl);
583
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
584
#endif
585
}
586

587
int botan_x509_crl_get_entry(
4✔
588
   botan_x509_crl_t crl, size_t i, uint8_t serial[], size_t* serial_len, uint64_t* expire_time, uint8_t* reason) {
589
   if(expire_time == nullptr || reason == nullptr) {
4✔
590
      return BOTAN_FFI_ERROR_NULL_POINTER;
591
   }
592

593
#if defined(BOTAN_HAS_X509_CERTIFICATES)
594
   const auto& entries = safe_get(crl).get_revoked();
4✔
595
   if(i >= entries.size()) {
4✔
596
      return BOTAN_FFI_ERROR_BAD_PARAMETER;
597
   }
598
   *reason = static_cast<uint8_t>(entries[i].reason_code());
4✔
599
   *expire_time = entries[i].expire_time().time_since_epoch();
4✔
600
   return write_vec_output(serial, serial_len, entries[i].serial_number());
4✔
601
#else
602
   BOTAN_UNUSED(crl, i, serial, serial_len);
603
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
604
#endif
605
}
606

607
int botan_x509_crl_verify_signature(botan_x509_crl_t crl, botan_pubkey_t key, int* result) {
2✔
608
   if(result == nullptr) {
2✔
609
      return BOTAN_FFI_ERROR_NULL_POINTER;
610
   }
611
#if defined(BOTAN_HAS_X509_CERTIFICATES)
612
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
613
      bool ok = safe_get(crl).check_signature(safe_get(key));
2✔
614
      if(ok) {
2✔
615
         *result = 1;
2✔
616
      } else {
617
         *result = 0;
×
618
      }
619
      return BOTAN_FFI_SUCCESS;
2✔
620
   });
2✔
621
#else
622
   BOTAN_UNUSED(crl, key);
623
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
624
#endif
625
}
626

627
int botan_x509_crl_view_pem(botan_x509_crl_t crl, botan_view_ctx ctx, botan_view_str_fn view) {
1✔
628
#if defined(BOTAN_HAS_X509_CERTIFICATES)
629
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) -> int { return invoke_view_callback(view, ctx, c.PEM_encode()); });
3✔
630
#else
631
   BOTAN_UNUSED(crl, ctx, view);
632
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
633
#endif
634
}
635

636
int botan_x509_crl_view_der(botan_x509_crl_t crl, botan_view_ctx ctx, botan_view_bin_fn view) {
×
637
#if defined(BOTAN_HAS_X509_CERTIFICATES)
638
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) -> int { return invoke_view_callback(view, ctx, c.BER_encode()); });
×
639
#else
640
   BOTAN_UNUSED(crl, ctx, view);
641
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
642
#endif
643
}
644

645
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
12✔
646
#if defined(BOTAN_HAS_X509_CERTIFICATES)
647
   return BOTAN_FFI_CHECKED_DELETE(crl);
12✔
648
#else
649
   BOTAN_UNUSED(crl);
650
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
651
#endif
652
}
653

654
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
655
#if defined(BOTAN_HAS_X509_CERTIFICATES)
656
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
657
#else
658
   BOTAN_UNUSED(cert);
659
   BOTAN_UNUSED(crl);
660
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
661
#endif
662
}
663

664
int botan_x509_cert_verify_with_crl(int* result_code,
20✔
665
                                    botan_x509_cert_t cert,
666
                                    const botan_x509_cert_t* intermediates,
667
                                    size_t intermediates_len,
668
                                    const botan_x509_cert_t* trusted,
669
                                    size_t trusted_len,
670
                                    const botan_x509_crl_t* crls,
671
                                    size_t crls_len,
672
                                    const char* trusted_path,
673
                                    size_t required_strength,
674
                                    const char* hostname_cstr,
675
                                    uint64_t reference_time) {
676
   if(required_strength == 0) {
20✔
677
      required_strength = 110;
10✔
678
   }
679

680
#if defined(BOTAN_HAS_X509_CERTIFICATES)
681
   return ffi_guard_thunk(__func__, [=]() -> int {
20✔
682
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
22✔
683
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
20✔
684
      const auto validation_time = reference_time == 0
20✔
685
                                      ? std::chrono::system_clock::now()
20✔
686
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
1✔
687

688
      std::vector<Botan::X509_Certificate> end_certs;
20✔
689
      end_certs.push_back(safe_get(cert));
20✔
690
      for(size_t i = 0; i != intermediates_len; ++i) {
38✔
691
         end_certs.push_back(safe_get(intermediates[i]));
18✔
692
      }
693

694
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
20✔
695
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
20✔
696
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
20✔
697
      std::vector<Botan::Certificate_Store*> trusted_roots;
20✔
698

699
      if(trusted_path != nullptr && *trusted_path != 0) {
20✔
700
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
701
         trusted_roots.push_back(trusted_from_path.get());
2✔
702
      }
703

704
      if(trusted_len > 0) {
20✔
705
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
34✔
706
         for(size_t i = 0; i != trusted_len; ++i) {
34✔
707
            trusted_extra->add_certificate(safe_get(trusted[i]));
17✔
708
         }
709
         trusted_roots.push_back(trusted_extra.get());
17✔
710
      }
711

712
      if(crls_len > 0) {
20✔
713
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
22✔
714
         for(size_t i = 0; i != crls_len; ++i) {
25✔
715
            trusted_crls->add_crl(safe_get(crls[i]));
14✔
716
         }
717
         trusted_roots.push_back(trusted_crls.get());
11✔
718
      }
719

720
      Botan::Path_Validation_Restrictions restrictions(false, required_strength);
40✔
721

722
      auto validation_result =
20✔
723
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
20✔
724

725
      if(result_code != nullptr) {
20✔
726
         *result_code = static_cast<int>(validation_result.result());
20✔
727
      }
728

729
      if(validation_result.successful_validation()) {
20✔
730
         return 0;
731
      } else {
732
         return 1;
10✔
733
      }
734
   });
22✔
735
#else
736
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
737
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
738
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
739
#endif
740
}
741

742
int botan_x509_cert_params_builder_destroy(botan_x509_cert_params_builder_t builder) {
11✔
743
#if defined(BOTAN_HAS_X509_CERTIFICATES)
744
   return BOTAN_FFI_CHECKED_DELETE(builder);
11✔
745
#else
746
   BOTAN_UNUSED(builder);
747
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
748
#endif
749
}
750

751
int botan_x509_cert_params_builder_create(botan_x509_cert_params_builder_t* builder_obj) {
11✔
752
   if(builder_obj == nullptr) {
11✔
753
      return BOTAN_FFI_ERROR_NULL_POINTER;
754
   }
755

756
#if defined(BOTAN_HAS_X509_CERTIFICATES)
757
   return ffi_guard_thunk(__func__, [=]() -> int {
11✔
758
      auto co = std::make_unique<Botan::CertificateParametersBuilder>();
11✔
759
      return ffi_new_object(builder_obj, std::move(co));
22✔
760
   });
22✔
761
#else
762
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
763
#endif
764
}
765

766
#if defined(BOTAN_HAS_X509_CERTIFICATES)
767
   // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
768
   #define X509_GET_CERT_PARAMS_BUILDER_STRING(FIELD_NAME)                                          \
769
      int botan_x509_cert_params_builder_add_##FIELD_NAME(botan_x509_cert_params_builder_t builder, \
770
                                                          const char* value) {                      \
771
         if(value == nullptr) {                                                                     \
772
            return BOTAN_FFI_ERROR_NULL_POINTER;                                                    \
773
         }                                                                                          \
774
         return BOTAN_FFI_VISIT(builder, [=](auto& o) { o.add_##FIELD_NAME(value); });              \
775
      }
776
#else
777
   // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
778
   #define X509_GET_CERT_PARAMS_BUILDER_STRING(FIELD_NAME)                                          \
779
      int botan_x509_cert_params_builder_add_##FIELD_NAME(botan_x509_cert_params_builder_t builder, \
780
                                                          const char* value) {                      \
781
         if(value == nullptr) {                                                                     \
782
            return BOTAN_FFI_ERROR_NULL_POINTER;                                                    \
783
         }                                                                                          \
784
         BOTAN_UNUSED(builder);                                                                     \
785
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;                                                    \
786
      }
787
#endif
788

789
X509_GET_CERT_PARAMS_BUILDER_STRING(common_name)
4✔
790
X509_GET_CERT_PARAMS_BUILDER_STRING(country)
4✔
791
X509_GET_CERT_PARAMS_BUILDER_STRING(state)
×
792
X509_GET_CERT_PARAMS_BUILDER_STRING(locality)
×
793
X509_GET_CERT_PARAMS_BUILDER_STRING(serial_number)
×
794
X509_GET_CERT_PARAMS_BUILDER_STRING(organization)
4✔
795
X509_GET_CERT_PARAMS_BUILDER_STRING(organizational_unit)
4✔
796
X509_GET_CERT_PARAMS_BUILDER_STRING(email)
×
797
X509_GET_CERT_PARAMS_BUILDER_STRING(dns)
12✔
798
X509_GET_CERT_PARAMS_BUILDER_STRING(uri)
4✔
799
X509_GET_CERT_PARAMS_BUILDER_STRING(xmpp)
×
800

801
int botan_x509_cert_params_builder_add_ipv4(botan_x509_cert_params_builder_t builder, uint32_t ipv4) {
×
802
#if defined(BOTAN_HAS_X509_CERTIFICATES)
803
   return BOTAN_FFI_VISIT(builder, [=](auto& o) { o.add_ipv4(ipv4); });
×
804
#else
805
   BOTAN_UNUSED(builder, ipv4);
806
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
807
#endif
808
}
809

810
int botan_x509_cert_params_builder_add_allowed_usage(botan_x509_cert_params_builder_t builder, uint32_t usage) {
2✔
811
#if defined(BOTAN_HAS_X509_CERTIFICATES)
812
   return BOTAN_FFI_VISIT(builder, [=](auto& o) { o.add_allowed_usage(Botan::Key_Constraints(usage)); });
4✔
813
#else
814
   BOTAN_UNUSED(builder, usage);
815
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
816
#endif
817
}
818

819
int botan_x509_cert_params_builder_add_allowed_extended_usage(botan_x509_cert_params_builder_t builder,
×
820
                                                              botan_asn1_oid_t oid) {
821
#if defined(BOTAN_HAS_X509_CERTIFICATES)
822
   return ffi_guard_thunk(__func__, [=]() -> int {
×
823
      safe_get(builder).add_allowed_extended_usage(safe_get(oid));
×
824
      return BOTAN_FFI_SUCCESS;
×
825
   });
×
826
#else
827
   BOTAN_UNUSED(builder, oid);
828
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
829
#endif
830
}
831

832
int botan_x509_cert_params_builder_set_as_ca_certificate(botan_x509_cert_params_builder_t builder, size_t* limit) {
5✔
833
#if defined(BOTAN_HAS_X509_CERTIFICATES)
834
   return BOTAN_FFI_VISIT(builder, [=](auto& o) {
13✔
835
      auto limit_ = optional_from_ptr<size_t>(limit);
836
      o.set_as_ca_certificate(limit_);
837
   });
838
#else
839
   BOTAN_UNUSED(builder, limit);
840
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
841
#endif
842
}
843

844
int botan_x509_cert_params_builder_add_ext_ip_addr_blocks(botan_x509_cert_params_builder_t builder,
6✔
845
                                                          botan_x509_ext_ip_addr_blocks_t ip_addr_blocks,
846
                                                          int is_critical) {
847
#if defined(BOTAN_HAS_X509_CERTIFICATES)
848
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
849
      if(is_critical != 0 && is_critical != 1) {
6✔
850
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
851
      }
852
      try {
6✔
853
         safe_get(builder).add_extension(safe_get(ip_addr_blocks).copy(), static_cast<bool>(is_critical));
8✔
854
      } catch(Botan::Invalid_Argument&) {
2✔
855
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
2✔
856
      }
2✔
857
      return BOTAN_FFI_SUCCESS;
4✔
858
   });
6✔
859
#else
860
   BOTAN_UNUSED(builder, ip_addr_blocks, is_critical);
861
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
862
#endif
863
}
864

865
int botan_x509_cert_params_builder_add_ext_as_blocks(botan_x509_cert_params_builder_t builder,
6✔
866
                                                     botan_x509_ext_as_blocks_t as_blocks,
867
                                                     int is_critical) {
868
#if defined(BOTAN_HAS_X509_CERTIFICATES)
869
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
870
      if(is_critical != 0 && is_critical != 1) {
6✔
871
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
872
      }
873
      try {
6✔
874
         safe_get(builder).add_extension(safe_get(as_blocks).copy(), static_cast<bool>(is_critical));
8✔
875
      } catch(Botan::Invalid_Argument&) {
2✔
876
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
2✔
877
      }
2✔
878
      return BOTAN_FFI_SUCCESS;
4✔
879
   });
6✔
880
#else
881
   BOTAN_UNUSED(builder, as_blocks, is_critical);
882
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
883
#endif
884
}
885

886
int botan_x509_cert_create_self_signed(botan_x509_cert_t* cert_obj,
5✔
887
                                       botan_privkey_t key,
888
                                       botan_x509_cert_params_builder_t builder,
889
                                       botan_rng_t rng,
890
                                       uint64_t not_before,
891
                                       uint64_t not_after,
892
                                       const botan_mp_t* serial_number,
893
                                       const char* hash_fn,
894
                                       const char* padding) {
895
   if(cert_obj == nullptr) {
5✔
896
      return BOTAN_FFI_ERROR_NULL_POINTER;
897
   }
898
#if defined(BOTAN_HAS_X509_CERTIFICATES)
899
   return ffi_guard_thunk(__func__, [=]() -> int {
5✔
900
      auto hash_fn_ = optional_from_ptr(hash_fn);
5✔
901
      auto padding_ = optional_from_ptr(padding);
5✔
902

903
      std::unique_ptr<Botan::X509_Certificate> cert;
5✔
904
      if(serial_number != nullptr && false) {
5✔
905
         // TODO
906
         auto serial_no = safe_get(*serial_number);
907
      } else {
908
         cert = std::make_unique<Botan::X509_Certificate>(
5✔
909
            safe_get(builder).into_self_signed_cert(timepoint_from_timestamp(not_before),
18✔
910
                                                    timepoint_from_timestamp(not_after),
911
                                                    safe_get(key),
5✔
912
                                                    safe_get(rng),
913
                                                    hash_fn_,
914
                                                    padding_));
5✔
915
      }
916

917
      return ffi_new_object(cert_obj, std::move(cert));
5✔
918
   });
13✔
919
#else
920
   BOTAN_UNUSED(key, builder, rng, not_before, not_after, hash_fn, padding);
921
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
922
#endif
923
}
924

925
int botan_x509_pkcs10_req_destroy(botan_x509_pkcs10_req_t req) {
7✔
926
#if defined(BOTAN_HAS_X509_CERTIFICATES)
927
   return BOTAN_FFI_CHECKED_DELETE(req);
7✔
928
#else
929
   BOTAN_UNUSED(req);
930
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
931
#endif
932
}
933

934
int botan_x509_pkcs10_req_load_file(botan_x509_pkcs10_req_t* req_obj, const char* req_path) {
×
935
   if(req_obj == nullptr || req_path == nullptr) {
×
936
      return BOTAN_FFI_ERROR_NULL_POINTER;
937
   }
938
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
939
   return ffi_guard_thunk(__func__, [=]() -> int {
×
940
      auto req = std::make_unique<Botan::PKCS10_Request>(req_path);
×
941
      return ffi_new_object(req_obj, std::move(req));
×
942
   });
×
943
#else
944
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
945
#endif
946
}
947

948
int botan_x509_pkcs10_req_load(botan_x509_pkcs10_req_t* req_obj, const uint8_t req_bits[], size_t req_bits_len) {
1✔
949
   if(req_obj == nullptr || req_bits == nullptr) {
1✔
950
      return BOTAN_FFI_ERROR_NULL_POINTER;
951
   }
952

953
#if defined(BOTAN_HAS_X509_CERTIFICATES)
954
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
955
      Botan::DataSource_Memory bits(req_bits, req_bits_len);
1✔
956
      auto req = std::make_unique<Botan::PKCS10_Request>(bits);
1✔
957
      return ffi_new_object(req_obj, std::move(req));
1✔
958
   });
3✔
959
#else
960
   BOTAN_UNUSED(req_bits_len);
961
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
962
#endif
963
}
964

965
int botan_x509_pkcs10_req_create(botan_x509_pkcs10_req_t* req_obj,
6✔
966
                                 botan_privkey_t key,
967
                                 botan_x509_cert_params_builder_t builder,
968
                                 botan_rng_t rng,
969
                                 const char* hash_fn,
970
                                 const char* padding,
971
                                 const char* challenge_password) {
972
   if(req_obj == nullptr) {
6✔
973
      return BOTAN_FFI_ERROR_NULL_POINTER;
974
   }
975
#if defined(BOTAN_HAS_X509_CERTIFICATES)
976
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
977
      auto req = std::make_unique<Botan::PKCS10_Request>(
6✔
978
         safe_get(builder).into_pkcs10_request(safe_get(key),
18✔
979
                                               safe_get(rng),
980
                                               optional_from_ptr(hash_fn),
12✔
981
                                               optional_from_ptr(padding),
12✔
982
                                               optional_from_ptr(challenge_password)));
12✔
983
      return ffi_new_object(req_obj, std::move(req));
12✔
984
   });
12✔
985
#else
986
   BOTAN_UNUSED(key, builder, rng, padding, hash_fn, challenge_password);
987
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
988
#endif
989
}
990

991
int botan_x509_pkcs10_req_view_pem(botan_x509_pkcs10_req_t req, botan_view_ctx ctx, botan_view_str_fn view) {
1✔
992
#if defined(BOTAN_HAS_X509_CERTIFICATES)
993
   return BOTAN_FFI_VISIT(req, [=](const auto& r) -> int { return invoke_view_callback(view, ctx, r.PEM_encode()); });
3✔
994
#else
995
   BOTAN_UNUSED(req, ctx, view);
996
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
997
#endif
998
}
999

1000
int botan_x509_pkcs10_req_view_der(botan_x509_pkcs10_req_t req, botan_view_ctx ctx, botan_view_bin_fn view) {
×
1001
#if defined(BOTAN_HAS_X509_CERTIFICATES)
1002
   return BOTAN_FFI_VISIT(req, [=](const auto& r) -> int { return invoke_view_callback(view, ctx, r.BER_encode()); });
×
1003
#else
1004
   BOTAN_UNUSED(crl, ctx, view);
1005
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1006
#endif
1007
}
1008

1009
int botan_x509_pkcs10_req_get_public_key(botan_x509_pkcs10_req_t req, botan_pubkey_t* key) {
1✔
1010
   if(key == nullptr) {
1✔
1011
      return BOTAN_FFI_ERROR_NULL_POINTER;
1012
   }
1013

1014
#if defined(BOTAN_HAS_X509_CERTIFICATES)
1015
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
1016
      auto public_key = safe_get(req).subject_public_key();
1✔
1017
      return ffi_new_object(key, std::move(public_key));
1✔
1018
   });
2✔
1019
#else
1020
   BOTAN_UNUSED(req);
1021
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1022
#endif
1023
}
1024

1025
int botan_x509_pkcs10_req_get_key_constraints(botan_x509_pkcs10_req_t req, uint32_t* usage) {
1✔
1026
   if(usage == nullptr) {
1✔
1027
      return BOTAN_FFI_ERROR_NULL_POINTER;
1028
   }
1029

1030
#if defined(BOTAN_HAS_X509_CERTIFICATES)
1031
   return BOTAN_FFI_VISIT(req, [=](const auto& r) -> int {
2✔
1032
      *usage = r.constraints().value();
1033
      return BOTAN_FFI_SUCCESS;
1034
   });
1035
#else
1036
   BOTAN_UNUSED(cert)
1037
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1038
#endif
1039
}
1040

1041
int botan_x509_pkcs10_req_is_ca(botan_x509_pkcs10_req_t req, int* is_ca, size_t* limit) {
1✔
1042
   if(is_ca == nullptr || limit == nullptr) {
1✔
1043
      return BOTAN_FFI_ERROR_NULL_POINTER;
1044
   }
1045

1046
#if defined(BOTAN_HAS_X509_CERTIFICATES)
1047
   return BOTAN_FFI_VISIT(req, [=](const auto& r) -> int {
2✔
1048
      if(r.is_CA()) {
1049
         *is_ca = 1;
1050
         // TODO
1051
         if(r.path_length_constraint().has_value()) {
1052
            *limit = r.path_length_constraint().value();
1053
         } else {
1054
            *limit = 32;
1055
         }
1056
      } else {
1057
         *is_ca = 0;
1058
         *limit = 0;
1059
      }
1060
      return BOTAN_FFI_SUCCESS;
1061
   });
1062
#else
1063
   BOTAN_UNUSED(cert)
1064
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1065
#endif
1066
}
1067

1068
int botan_x509_pkcs10_req_verify_signature(botan_x509_pkcs10_req_t req, botan_pubkey_t key, int* result) {
5✔
1069
   if(result == nullptr) {
5✔
1070
      return BOTAN_FFI_ERROR_NULL_POINTER;
1071
   }
1072
#if defined(BOTAN_HAS_X509_CERTIFICATES)
1073
   return ffi_guard_thunk(__func__, [=]() -> int {
5✔
1074
      bool ok = safe_get(req).check_signature(safe_get(key));
5✔
1075
      if(ok) {
5✔
1076
         *result = 1;
4✔
1077
      } else {
1078
         *result = 0;
1✔
1079
      }
1080
      return BOTAN_FFI_SUCCESS;
5✔
1081
   });
5✔
1082
#else
1083
   BOTAN_UNUSED(req, key);
1084
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1085
#endif
1086
}
1087

1088
int botan_x509_pkcs10_req_sign(botan_x509_cert_t* subject_cert,
6✔
1089
                               botan_x509_pkcs10_req_t subject_req,
1090
                               botan_x509_cert_t issuing_cert,
1091
                               botan_privkey_t issuing_key,
1092
                               botan_rng_t rng,
1093
                               uint64_t not_before,
1094
                               uint64_t not_after,
1095
                               const botan_mp_t* serial_number,
1096
                               const char* hash_fn,
1097
                               const char* padding) {
1098
   if(subject_cert == nullptr) {
6✔
1099
      return BOTAN_FFI_ERROR_NULL_POINTER;
1100
   }
1101
#if defined(BOTAN_HAS_X509_CERTIFICATES)
1102
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
1103
      auto& rng_ = safe_get(rng);
6✔
1104

1105
      auto ca = Botan::X509_CA(safe_get(issuing_cert),
6✔
1106
                               safe_get(issuing_key),
6✔
1107
                               default_from_ptr<std::string>(hash_fn),
6✔
1108
                               default_from_ptr<std::string>(padding),
6✔
1109
                               rng_);
12✔
1110

1111
      std::unique_ptr<Botan::X509_Certificate> cert;
6✔
1112
      if(serial_number != nullptr) {
6✔
1113
         auto serial_no = safe_get(*serial_number);
3✔
1114
         cert = std::make_unique<Botan::X509_Certificate>(ca.sign_request(
3✔
1115
            safe_get(subject_req), rng_, serial_no, time_from_timestamp(not_before), time_from_timestamp(not_after)));
6✔
1116
      } else {
3✔
1117
         cert = std::make_unique<Botan::X509_Certificate>(ca.sign_request(
3✔
1118
            safe_get(subject_req), rng_, time_from_timestamp(not_before), time_from_timestamp(not_after)));
6✔
1119
      }
1120

1121
      return ffi_new_object(subject_cert, std::move(cert));
6✔
1122
   });
12✔
1123
#else
1124
   BOTAN_UNUSED(subject_req, issuing_cert, issuing_key, rng, not_before, not_after, hash_fn, padding);
1125
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1126
#endif
1127
}
1128
}
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