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

randombit / botan / 21885850724

10 Feb 2026 11:05PM UTC coverage: 91.638% (+1.6%) from 90.068%
21885850724

push

github

web-flow
Merge pull request #5310 from randombit/jack/fix-build-deps

Fix some build dependency issues

104006 of 113497 relevant lines covered (91.64%)

11190952.72 hits per line

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

95.08
/src/lib/ffi/ffi_cert.cpp
1
/*
2
* (C) 2015,2017,2018 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/ffi.h>
8

9
#include <botan/internal/ffi_pkey.h>
10
#include <botan/internal/ffi_util.h>
11
#include <memory>
12

13
#if defined(BOTAN_HAS_X509_CERTIFICATES)
14
   #include <botan/asn1_time.h>
15
   #include <botan/data_src.h>
16
   #include <botan/x509_crl.h>
17
   #include <botan/x509cert.h>
18
   #include <botan/x509path.h>
19
   #include <botan/internal/ffi_mp.h>
20
   #include <botan/internal/ffi_oid.h>
21
#endif
22

23
#if defined(BOTAN_HAS_X509_CERTIFICATES)
24

25
namespace Botan_FFI {
26

27
namespace {
28

29
/**
30
 * As specified in RFC 5280 Section 4.2.1.6. alternative names essentially are a
31
 * collection of GeneralNames. This allows mapping a single entry of @p altnames
32
 * to a GeneralName by its @p index. If the index is out of range, std::nullopt
33
 * is returned.
34
 *
35
 * NOTE: if the set of alternative name types handled here is extended,
36
 *       count_general_names_in() must be updated accordingly!
37
 */
38
std::optional<Botan::GeneralName> extract_general_name_at(const Botan::AlternativeName& altnames, size_t index) {
132✔
39
   if(index < altnames.email().size()) {
132✔
40
      auto itr = altnames.email().begin();
12✔
41
      std::advance(itr, index);
12✔
42
      return Botan::GeneralName::email(*itr);
36✔
43
   }
44
   index -= altnames.email().size();
120✔
45

46
   if(index < altnames.dns().size()) {
120✔
47
      auto itr = altnames.dns().begin();
36✔
48
      std::advance(itr, index);
36✔
49
      return Botan::GeneralName::dns(*itr);
108✔
50
   }
51
   index -= altnames.dns().size();
84✔
52

53
   if(index < altnames.directory_names().size()) {
84✔
54
      auto itr = altnames.directory_names().begin();
36✔
55
      std::advance(itr, index);
36✔
56
      return Botan::GeneralName::directory_name(*itr);
108✔
57
   }
58
   index -= altnames.directory_names().size();
48✔
59

60
   if(index < altnames.uris().size()) {
48✔
61
      auto itr = altnames.uris().begin();
24✔
62
      std::advance(itr, index);
24✔
63
      return Botan::GeneralName::uri(*itr);
72✔
64
   }
65
   index -= altnames.uris().size();
24✔
66

67
   if(index < altnames.ipv4_address().size()) {
24✔
68
      auto itr = altnames.ipv4_address().begin();
12✔
69
      std::advance(itr, index);
12✔
70
      return Botan::GeneralName::ipv4_address(*itr);
36✔
71
   }
72

73
   return std::nullopt;
12✔
74
}
75

76
/**
77
 * Counts the total number of GeneralNames contained in the given
78
 * AlternativeName @p alt_names.
79
 *
80
 * NOTE: if the set of alternative name types handled here is extended,
81
 *       extract_general_name_at() must be updated accordingly!
82
 */
83
size_t count_general_names_in(const Botan::AlternativeName& alt_names) {
12✔
84
   return alt_names.email().size() + alt_names.dns().size() + alt_names.directory_names().size() +
12✔
85
          alt_names.uris().size() + alt_names.ipv4_address().size();
12✔
86
}
87

88
std::optional<botan_x509_general_name_types> to_botan_x509_general_name_types(Botan::GeneralName::NameType gn_type) {
301✔
89
   using Type = Botan::GeneralName::NameType;
301✔
90
   switch(gn_type) {
301✔
91
      case Type::Unknown:
1✔
92
         return std::nullopt;
1✔
93
      case Type::RFC822:
83✔
94
         return BOTAN_X509_EMAIL_ADDRESS;
83✔
95
      case Type::DNS:
73✔
96
         return BOTAN_X509_DNS_NAME;
73✔
97
      case Type::URI:
28✔
98
         return BOTAN_X509_URI;
28✔
99
      case Type::DN:
95✔
100
         return BOTAN_X509_DIRECTORY_NAME;
95✔
101
      case Type::IPv4:
21✔
102
         return BOTAN_X509_IP_ADDRESS;
21✔
103
      case Type::Other:
×
104
         return BOTAN_X509_OTHER_NAME;
×
105
   }
106

107
   BOTAN_ASSERT_UNREACHABLE();
×
108
}
109

110
}  // namespace
111

112
}  // namespace Botan_FFI
113

114
#endif
115

116
extern "C" {
117

118
using namespace Botan_FFI;
119

120
#if defined(BOTAN_HAS_X509_CERTIFICATES)
121

122
BOTAN_FFI_DECLARE_STRUCT(botan_x509_cert_struct, Botan::X509_Certificate, 0x8F628937);
30✔
123
BOTAN_FFI_DECLARE_STRUCT(botan_x509_general_name_struct, Botan::GeneralName, 0x563654FD);
198✔
124

125
#endif
126

127
int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path) {
29✔
128
   if(cert_obj == nullptr || cert_path == nullptr) {
29✔
129
      return BOTAN_FFI_ERROR_NULL_POINTER;
130
   }
131

132
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
133

134
   return ffi_guard_thunk(__func__, [=]() -> int {
29✔
135
      auto c = std::make_unique<Botan::X509_Certificate>(cert_path);
29✔
136
      return ffi_new_object(cert_obj, std::move(c));
29✔
137
   });
58✔
138

139
#else
140
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
141
#endif
142
}
143

144
int botan_x509_cert_dup(botan_x509_cert_t* cert_obj, botan_x509_cert_t cert) {
1✔
145
   if(cert_obj == nullptr) {
1✔
146
      return BOTAN_FFI_ERROR_NULL_POINTER;
147
   }
148

149
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
150

151
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
152
      auto c = std::make_unique<Botan::X509_Certificate>(safe_get(cert));
1✔
153
      return ffi_new_object(cert_obj, std::move(c));
1✔
154
   });
2✔
155

156
#else
157
   BOTAN_UNUSED(cert);
158
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
159
#endif
160
}
161

162
int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert_bits[], size_t cert_bits_len) {
×
163
   if(cert_obj == nullptr || cert_bits == nullptr) {
×
164
      return BOTAN_FFI_ERROR_NULL_POINTER;
165
   }
166

167
#if defined(BOTAN_HAS_X509_CERTIFICATES)
168
   return ffi_guard_thunk(__func__, [=]() -> int {
×
169
      Botan::DataSource_Memory bits(cert_bits, cert_bits_len);
×
170
      auto c = std::make_unique<Botan::X509_Certificate>(bits);
×
171
      return ffi_new_object(cert_obj, std::move(c));
×
172
   });
×
173
#else
174
   BOTAN_UNUSED(cert_bits_len);
175
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
176
#endif
177
}
178

179
int botan_x509_cert_is_ca(botan_x509_cert_t cert) {
2✔
180
#if defined(BOTAN_HAS_X509_CERTIFICATES)
181
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.is_CA_cert() ? 1 : 0; });
4✔
182
#else
183
   BOTAN_UNUSED(cert);
184
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
185
#endif
186
}
187

188
int botan_x509_cert_get_path_length_constraint(botan_x509_cert_t cert, size_t* path_limit) {
2✔
189
#if defined(BOTAN_HAS_X509_CERTIFICATES)
190
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
4✔
191
      if(Botan::any_null_pointers(path_limit)) {
192
         return BOTAN_FFI_ERROR_NULL_POINTER;
193
      }
194

195
      if(const auto path_len = c.path_length_constraint()) {
196
         *path_limit = path_len.value();
197
         return BOTAN_FFI_SUCCESS;
198
      } else {
199
         return BOTAN_FFI_ERROR_NO_VALUE;
200
      }
201
   });
202
#else
203
   BOTAN_UNUSED(cert, path_limit);
204
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
205
#endif
206
}
207

208
int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) {
2✔
209
   if(key == nullptr) {
2✔
210
      return BOTAN_FFI_ERROR_NULL_POINTER;
211
   }
212

213
   *key = nullptr;
2✔
214

215
#if defined(BOTAN_HAS_X509_CERTIFICATES)
216
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
217
      auto public_key = safe_get(cert).subject_public_key();
2✔
218
      return ffi_new_object(key, std::move(public_key));
2✔
219
   });
4✔
220
#else
221
   BOTAN_UNUSED(cert);
222
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
223
#endif
224
}
225

226
int botan_x509_cert_get_issuer_dn(
8✔
227
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
228
#if defined(BOTAN_HAS_X509_CERTIFICATES)
229
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
230
      auto issuer_info = c.issuer_info(key);
231
      if(index < issuer_info.size()) {
232
         // TODO(Botan4) change the type of out and remove this cast
233
         return write_str_output(reinterpret_cast<char*>(out), out_len, c.issuer_info(key).at(index));
234
      } else {
235
         return BOTAN_FFI_ERROR_BAD_PARAMETER;  // TODO(Botan4): use BOTAN_FFI_ERROR_OUT_OF_RANGE
236
      }
237
   });
238
#else
239
   BOTAN_UNUSED(cert, key, index, out, out_len);
240
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
241
#endif
242
}
243

244
int botan_x509_cert_get_issuer_dn_count(botan_x509_cert_t cert, const char* key, size_t* count) {
2✔
245
#if defined(BOTAN_HAS_X509_CERTIFICATES)
246
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
4✔
247
      if(Botan::any_null_pointers(count)) {
248
         return BOTAN_FFI_ERROR_NULL_POINTER;
249
      }
250

251
      *count = c.issuer_info(key).size();
252
      return BOTAN_FFI_SUCCESS;
253
   });
254
#else
255
   BOTAN_UNUSED(cert, key, count);
256
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
257
#endif
258
}
259

260
int botan_x509_cert_get_subject_dn(
8✔
261
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
262
#if defined(BOTAN_HAS_X509_CERTIFICATES)
263
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
264
      auto subject_info = c.subject_info(key);
265
      if(index < subject_info.size()) {
266
         // TODO(Botan4) change the type of out and remove this cast
267
         return write_str_output(reinterpret_cast<char*>(out), out_len, c.subject_info(key).at(index));
268
      } else {
269
         return BOTAN_FFI_ERROR_BAD_PARAMETER;  // TODO(Botan4): use BOTAN_FFI_ERROR_OUT_OF_RANGE
270
      }
271
   });
272
#else
273
   BOTAN_UNUSED(cert, key, index, out, out_len);
274
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
275
#endif
276
}
277

278
int botan_x509_cert_get_subject_dn_count(botan_x509_cert_t cert, const char* key, size_t* count) {
2✔
279
#if defined(BOTAN_HAS_X509_CERTIFICATES)
280
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
4✔
281
      if(Botan::any_null_pointers(count)) {
282
         return BOTAN_FFI_ERROR_NULL_POINTER;
283
      }
284

285
      *count = c.subject_info(key).size();
286
      return BOTAN_FFI_SUCCESS;
287
   });
288
#else
289
   BOTAN_UNUSED(cert, key, count);
290
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
291
#endif
292
}
293

294
int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
295
   return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert);
2✔
296
}
297

298
int botan_x509_cert_view_as_string(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) {
3✔
299
#if defined(BOTAN_HAS_X509_CERTIFICATES)
300
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return invoke_view_callback(view, ctx, c.to_string()); });
9✔
301
#else
302
   BOTAN_UNUSED(cert, ctx, view);
303
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
304
#endif
305
}
306

307
int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage) {
7✔
308
#if defined(BOTAN_HAS_X509_CERTIFICATES)
309
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
14✔
310
      const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
311
      if(c.allowed_usage(k)) {
312
         return BOTAN_FFI_SUCCESS;
313
      }
314
      return 1;
315
   });
316
#else
317
   BOTAN_UNUSED(cert, key_usage);
318
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
319
#endif
320
}
321

322
int botan_x509_cert_allowed_extended_usage_str(botan_x509_cert_t cert, const char* oid) {
12✔
323
#if defined(BOTAN_HAS_X509_CERTIFICATES)
324
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
32✔
325
      if(Botan::any_null_pointers(oid)) {
326
         return BOTAN_FFI_ERROR_NULL_POINTER;
327
      }
328

329
      return c.has_ex_constraint(oid) ? BOTAN_FFI_SUCCESS : 1;
330
   });
331
#else
332
   BOTAN_UNUSED(cert, oid);
333
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
334
#endif
335
}
336

337
int botan_x509_cert_allowed_extended_usage_oid(botan_x509_cert_t cert, botan_asn1_oid_t oid) {
4✔
338
#if defined(BOTAN_HAS_X509_CERTIFICATES)
339
   return BOTAN_FFI_VISIT(
8✔
340
      cert, [=](const auto& c) -> int { return c.has_ex_constraint(safe_get(oid)) ? BOTAN_FFI_SUCCESS : 1; });
341
#else
342
   BOTAN_UNUSED(cert, oid);
343
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
344
#endif
345
}
346

347
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
30✔
348
#if defined(BOTAN_HAS_X509_CERTIFICATES)
349
   return BOTAN_FFI_CHECKED_DELETE(cert);
30✔
350
#else
351
   BOTAN_UNUSED(cert);
352
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
353
#endif
354
}
355

356
int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len) {
3✔
357
#if defined(BOTAN_HAS_X509_CERTIFICATES)
358
   return BOTAN_FFI_VISIT(cert,
6✔
359
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_before().to_string()); });
360
#else
361
   BOTAN_UNUSED(cert, out, out_len);
362
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
363
#endif
364
}
365

366
int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
367
#if defined(BOTAN_HAS_X509_CERTIFICATES)
368
   return BOTAN_FFI_VISIT(cert,
4✔
369
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); });
370
#else
371
   BOTAN_UNUSED(cert, out, out_len);
372
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
373
#endif
374
}
375

376
int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
377
#if defined(BOTAN_HAS_X509_CERTIFICATES)
378
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_before().time_since_epoch(); });
4✔
379
#else
380
   BOTAN_UNUSED(cert, time_since_epoch);
381
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
382
#endif
383
}
384

385
int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
386
#if defined(BOTAN_HAS_X509_CERTIFICATES)
387
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); });
4✔
388
#else
389
   BOTAN_UNUSED(cert, time_since_epoch);
390
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
391
#endif
392
}
393

394
int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
5✔
395
#if defined(BOTAN_HAS_X509_CERTIFICATES)
396
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); });
10✔
397
#else
398
   BOTAN_UNUSED(cert, out, out_len);
399
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
400
#endif
401
}
402

403
int botan_x509_cert_serial_number(botan_x509_cert_t cert, botan_mp_t* serial_number) {
1✔
404
#if defined(BOTAN_HAS_X509_CERTIFICATES)
405
   return BOTAN_FFI_VISIT(cert, [=](const Botan::X509_Certificate& c) {
2✔
406
      if(Botan::any_null_pointers(serial_number)) {
407
         return BOTAN_FFI_ERROR_NULL_POINTER;
408
      }
409

410
      auto serial_bn = Botan::BigInt::from_bytes(c.serial_number());
411
      return ffi_new_object(serial_number, std::make_unique<Botan::BigInt>(std::move(serial_bn)));
412
   });
413
#else
414
   BOTAN_UNUSED(cert, serial_number);
415
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
416
#endif
417
}
418

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

423
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) {
6✔
424
      return write_str_output(reinterpret_cast<char*>(out), out_len, c.fingerprint(hash));
425
   });
426
#else
427
   BOTAN_UNUSED(cert, hash, out, out_len);
428
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
429
#endif
430
}
431

432
int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
1✔
433
#if defined(BOTAN_HAS_X509_CERTIFICATES)
434
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); });
2✔
435
#else
436
   BOTAN_UNUSED(cert, out, out_len);
437
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
438
#endif
439
}
440

441
int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
442
#if defined(BOTAN_HAS_X509_CERTIFICATES)
443
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
6✔
444
#else
445
   BOTAN_UNUSED(cert, out, out_len);
446
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
447
#endif
448
}
449

450
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
451
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
452
}
453

454
int botan_x509_cert_view_public_key_bits(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
455
#if defined(BOTAN_HAS_X509_CERTIFICATES)
456
   return BOTAN_FFI_VISIT(cert,
6✔
457
                          [=](const auto& c) { return invoke_view_callback(view, ctx, c.subject_public_key_bits()); });
458
#else
459
   BOTAN_UNUSED(cert, ctx, view);
460
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
461
#endif
462
}
463

464
int botan_x509_general_name_get_type(botan_x509_general_name_t name, unsigned int* type) {
198✔
465
#if defined(BOTAN_HAS_X509_CERTIFICATES)
466
   return BOTAN_FFI_VISIT(name, [=](const Botan::GeneralName& n) {
396✔
467
      if(Botan::any_null_pointers(type)) {
468
         return BOTAN_FFI_ERROR_NULL_POINTER;
469
      }
470

471
      const auto mapped_type = to_botan_x509_general_name_types(n.type_code());
472
      if(!mapped_type.has_value()) {
473
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
474
      }
475

476
      *type = mapped_type.value();
477
      if(*type == BOTAN_X509_OTHER_NAME /* ... viewing of other-names not supported */) {
478
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
479
      }
480

481
      return BOTAN_FFI_SUCCESS;
482
   });
483
#else
484
   BOTAN_UNUSED(name, type);
485
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
486
#endif
487
}
488

489
int botan_x509_general_name_view_string_value(botan_x509_general_name_t name,
66✔
490
                                              botan_view_ctx ctx,
491
                                              botan_view_str_fn view) {
492
#if defined(BOTAN_HAS_X509_CERTIFICATES)
493
   return BOTAN_FFI_VISIT(name, [=](const Botan::GeneralName& n) -> int {
197✔
494
      const auto type = to_botan_x509_general_name_types(n.type_code());
495
      if(!type) {
496
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
497
      }
498

499
      if(type != BOTAN_X509_EMAIL_ADDRESS && type != BOTAN_X509_DNS_NAME && type != BOTAN_X509_URI &&
500
         type != BOTAN_X509_IP_ADDRESS) {
501
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
502
      }
503

504
      return invoke_view_callback(view, ctx, n.name());
505
   });
506
#else
507
   BOTAN_UNUSED(name, ctx, view);
508
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
509
#endif
510
}
511

512
int botan_x509_general_name_view_binary_value(botan_x509_general_name_t name,
37✔
513
                                              botan_view_ctx ctx,
514
                                              botan_view_bin_fn view) {
515
#if defined(BOTAN_HAS_X509_CERTIFICATES)
516
   return BOTAN_FFI_VISIT(name, [=](const Botan::GeneralName& n) -> int {
144✔
517
      const auto type = to_botan_x509_general_name_types(n.type_code());
518
      if(!type) {
519
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
520
      }
521

522
      if(type != BOTAN_X509_DIRECTORY_NAME && type != BOTAN_X509_IP_ADDRESS) {
523
         return BOTAN_FFI_ERROR_INVALID_OBJECT_STATE;
524
      }
525

526
      return invoke_view_callback(view, ctx, n.binary_name());
527
   });
528
#else
529
   BOTAN_UNUSED(name, ctx, view);
530
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
531
#endif
532
}
533

534
int botan_x509_general_name_destroy(botan_x509_general_name_t name) {
198✔
535
#if defined(BOTAN_HAS_X509_CERTIFICATES)
536
   return BOTAN_FFI_CHECKED_DELETE(name);
198✔
537
#else
538
   BOTAN_UNUSED(name);
539
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
540
#endif
541
}
542

543
int botan_x509_cert_permitted_name_constraints(botan_x509_cert_t cert,
76✔
544
                                               size_t index,
545
                                               botan_x509_general_name_t* constraint) {
546
#if defined(BOTAN_HAS_X509_CERTIFICATES)
547
   return BOTAN_FFI_VISIT(cert, [=](const Botan::X509_Certificate& c) {
152✔
548
      if(Botan::any_null_pointers(constraint)) {
549
         return BOTAN_FFI_ERROR_NULL_POINTER;
550
      }
551

552
      const auto& constraints = c.name_constraints().permitted();
553
      if(index >= constraints.size()) {
554
         return BOTAN_FFI_ERROR_OUT_OF_RANGE;
555
      }
556

557
      return ffi_new_object(constraint, std::make_unique<Botan::GeneralName>(constraints[index].base()));
558
   });
559
#else
560
   BOTAN_UNUSED(cert, index, constraint);
561
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
562
#endif
563
}
564

565
int botan_x509_cert_permitted_name_constraints_count(botan_x509_cert_t cert, size_t* count) {
1✔
566
#if defined(BOTAN_HAS_X509_CERTIFICATES)
567
   if(Botan::any_null_pointers(count)) {
1✔
568
      return BOTAN_FFI_ERROR_NULL_POINTER;
569
   }
570

571
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *count = c.name_constraints().permitted().size(); });
2✔
572
#else
573
   BOTAN_UNUSED(cert, count);
574
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
575
#endif
576
}
577

578
int botan_x509_cert_excluded_name_constraints(botan_x509_cert_t cert,
4✔
579
                                              size_t index,
580
                                              botan_x509_general_name_t* constraint) {
581
#if defined(BOTAN_HAS_X509_CERTIFICATES)
582
   return BOTAN_FFI_VISIT(cert, [=](const Botan::X509_Certificate& c) {
8✔
583
      if(Botan::any_null_pointers(constraint)) {
584
         return BOTAN_FFI_ERROR_NULL_POINTER;
585
      }
586

587
      const auto& constraints = c.name_constraints().excluded();
588
      if(index >= constraints.size()) {
589
         return BOTAN_FFI_ERROR_OUT_OF_RANGE;
590
      }
591

592
      return ffi_new_object(constraint, std::make_unique<Botan::GeneralName>(constraints[index].base()));
593
   });
594
#else
595
   BOTAN_UNUSED(cert, index, constraint);
596
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
597
#endif
598
}
599

600
int botan_x509_cert_excluded_name_constraints_count(botan_x509_cert_t cert, size_t* count) {
1✔
601
#if defined(BOTAN_HAS_X509_CERTIFICATES)
602
   if(Botan::any_null_pointers(count)) {
1✔
603
      return BOTAN_FFI_ERROR_NULL_POINTER;
604
   }
605

606
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *count = c.name_constraints().excluded().size(); });
2✔
607
#else
608
   BOTAN_UNUSED(cert, count);
609
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
610
#endif
611
}
612

613
int botan_x509_cert_subject_alternative_names(botan_x509_cert_t cert,
73✔
614
                                              size_t index,
615
                                              botan_x509_general_name_t* alt_name) {
616
#if defined(BOTAN_HAS_X509_CERTIFICATES)
617
   return BOTAN_FFI_VISIT(cert, [=](const Botan::X509_Certificate& c) {
152✔
618
      if(Botan::any_null_pointers(alt_name)) {
619
         return BOTAN_FFI_ERROR_NULL_POINTER;
620
      }
621

622
      if(!c.v3_extensions().extension_set(Botan::OID::from_string("X509v3.SubjectAlternativeName"))) {
623
         return BOTAN_FFI_ERROR_NO_VALUE;
624
      }
625

626
      if(auto name = extract_general_name_at(c.subject_alt_name(), index)) {
627
         return ffi_new_object(alt_name, std::make_unique<Botan::GeneralName>(std::move(name).value()));
628
      }
629

630
      return BOTAN_FFI_ERROR_OUT_OF_RANGE;
631
   });
632
#else
633
   BOTAN_UNUSED(cert, index, alt_name);
634
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
635
#endif
636
}
637

638
int botan_x509_cert_subject_alternative_names_count(botan_x509_cert_t cert, size_t* count) {
6✔
639
#if defined(BOTAN_HAS_X509_CERTIFICATES)
640
   if(Botan::any_null_pointers(count)) {
6✔
641
      return BOTAN_FFI_ERROR_NULL_POINTER;
642
   }
643

644
   return BOTAN_FFI_VISIT(
12✔
645
      cert, [=](const Botan::X509_Certificate& c) { *count = count_general_names_in(c.subject_alt_name()); });
646
#else
647
   BOTAN_UNUSED(cert, count);
648
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
649
#endif
650
}
651

652
int botan_x509_cert_issuer_alternative_names(botan_x509_cert_t cert,
61✔
653
                                             size_t index,
654
                                             botan_x509_general_name_t* alt_name) {
655
#if defined(BOTAN_HAS_X509_CERTIFICATES)
656
   return BOTAN_FFI_VISIT(cert, [=](const Botan::X509_Certificate& c) {
128✔
657
      if(Botan::any_null_pointers(alt_name)) {
658
         return BOTAN_FFI_ERROR_NULL_POINTER;
659
      }
660

661
      if(!c.v3_extensions().extension_set(Botan::OID::from_string("X509v3.IssuerAlternativeName"))) {
662
         return BOTAN_FFI_ERROR_NO_VALUE;
663
      }
664

665
      if(auto name = extract_general_name_at(c.issuer_alt_name(), index)) {
666
         return ffi_new_object(alt_name, std::make_unique<Botan::GeneralName>(std::move(name).value()));
667
      }
668

669
      return BOTAN_FFI_ERROR_OUT_OF_RANGE;
670
   });
671
#else
672
   BOTAN_UNUSED(cert, index, alt_name);
673
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
674
#endif
675
}
676

677
int botan_x509_cert_issuer_alternative_names_count(botan_x509_cert_t cert, size_t* count) {
6✔
678
#if defined(BOTAN_HAS_X509_CERTIFICATES)
679
   if(Botan::any_null_pointers(count)) {
6✔
680
      return BOTAN_FFI_ERROR_NULL_POINTER;
681
   }
682

683
   return BOTAN_FFI_VISIT(
12✔
684
      cert, [=](const Botan::X509_Certificate& c) { *count = count_general_names_in(c.issuer_alt_name()); });
685
#else
686
   BOTAN_UNUSED(cert, count);
687
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
688
#endif
689
}
690

691
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
6✔
692
   if(hostname == nullptr) {
6✔
693
      return BOTAN_FFI_ERROR_NULL_POINTER;
694
   }
695

696
#if defined(BOTAN_HAS_X509_CERTIFICATES)
697
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
12✔
698
#else
699
   BOTAN_UNUSED(cert);
700
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
701
#endif
702
}
703

704
int botan_x509_cert_verify(int* result_code,
4✔
705
                           botan_x509_cert_t cert,
706
                           const botan_x509_cert_t* intermediates,
707
                           size_t intermediates_len,
708
                           const botan_x509_cert_t* trusted,
709
                           size_t trusted_len,
710
                           const char* trusted_path,
711
                           size_t required_strength,
712
                           const char* hostname_cstr,
713
                           uint64_t reference_time) {
714
   if(required_strength == 0) {
4✔
715
      required_strength = 110;
3✔
716
   }
717

718
#if defined(BOTAN_HAS_X509_CERTIFICATES)
719
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
720
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
4✔
721
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
4✔
722
      const auto validation_time = reference_time == 0
4✔
723
                                      ? std::chrono::system_clock::now()
4✔
724
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
×
725

726
      std::vector<Botan::X509_Certificate> end_certs;
4✔
727
      end_certs.push_back(safe_get(cert));
4✔
728
      for(size_t i = 0; i != intermediates_len; ++i) {
9✔
729
         end_certs.push_back(safe_get(intermediates[i]));
5✔
730
      }
731

732
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
4✔
733
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
4✔
734
      std::vector<Botan::Certificate_Store*> trusted_roots;
4✔
735

736
      if(trusted_path != nullptr && *trusted_path != 0) {
4✔
737
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
738
         trusted_roots.push_back(trusted_from_path.get());
×
739
      }
740

741
      if(trusted_len > 0) {
4✔
742
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
8✔
743
         for(size_t i = 0; i != trusted_len; ++i) {
8✔
744
            trusted_extra->add_certificate(safe_get(trusted[i]));
4✔
745
         }
746
         trusted_roots.push_back(trusted_extra.get());
4✔
747
      }
748

749
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
8✔
750

751
      auto validation_result =
4✔
752
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
4✔
753

754
      if(result_code != nullptr) {
4✔
755
         *result_code = static_cast<int>(validation_result.result());
4✔
756
      }
757

758
      if(validation_result.successful_validation()) {
4✔
759
         return 0;
760
      } else {
761
         return 1;
3✔
762
      }
763
   });
4✔
764
#else
765
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
766
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
767
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
768
#endif
769
}
770

771
const char* botan_x509_cert_validation_status(int code) {
11✔
772
   if(code < 0) {
11✔
773
      return nullptr;
774
   }
775

776
#if defined(BOTAN_HAS_X509_CERTIFICATES)
777
   const Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
778
   return Botan::to_string(sc);
11✔
779
#else
780
   return nullptr;
781
#endif
782
}
783

784
#if defined(BOTAN_HAS_X509_CERTIFICATES)
785

786
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
8✔
787
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_entry_struct, Botan::CRL_Entry, 0x4EAA5346);
1✔
788

789
#endif
790

791
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
7✔
792
   if(crl_obj == nullptr || crl_path == nullptr) {
7✔
793
      return BOTAN_FFI_ERROR_NULL_POINTER;
794
   }
795

796
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
797

798
   return ffi_guard_thunk(__func__, [=]() -> int {
7✔
799
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
7✔
800
      return ffi_new_object(crl_obj, std::move(c));
14✔
801
   });
14✔
802

803
#else
804
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
805
#endif
806
}
807

808
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
1✔
809
   if(crl_obj == nullptr || crl_bits == nullptr) {
1✔
810
      return BOTAN_FFI_ERROR_NULL_POINTER;
811
   }
812

813
#if defined(BOTAN_HAS_X509_CERTIFICATES)
814
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
815
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
1✔
816
      auto c = std::make_unique<Botan::X509_CRL>(bits);
1✔
817
      return ffi_new_object(crl_obj, std::move(c));
1✔
818
   });
3✔
819
#else
820
   BOTAN_UNUSED(crl_bits_len);
821
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
822
#endif
823
}
824

825
int botan_x509_crl_this_update(botan_x509_crl_t crl, uint64_t* time_since_epoch) {
2✔
826
#if defined(BOTAN_HAS_X509_CERTIFICATES)
827
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) {
4✔
828
      if(Botan::any_null_pointers(time_since_epoch)) {
829
         return BOTAN_FFI_ERROR_NULL_POINTER;
830
      }
831
      *time_since_epoch = c.this_update().time_since_epoch();
832
      return BOTAN_FFI_SUCCESS;
833
   });
834
#else
835
   BOTAN_UNUSED(crl, time_since_epoch);
836
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
837
#endif
838
}
839

840
int botan_x509_crl_next_update(botan_x509_crl_t crl, uint64_t* time_since_epoch) {
4✔
841
#if defined(BOTAN_HAS_X509_CERTIFICATES)
842
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) {
8✔
843
      const auto& time = c.next_update();
844
      if(!time.time_is_set()) {
845
         return BOTAN_FFI_ERROR_NO_VALUE;
846
      }
847

848
      if(Botan::any_null_pointers(time_since_epoch)) {
849
         return BOTAN_FFI_ERROR_NULL_POINTER;
850
      }
851

852
      *time_since_epoch = c.next_update().time_since_epoch();
853
      return BOTAN_FFI_SUCCESS;
854
   });
855
#else
856
   BOTAN_UNUSED(crl, time_since_epoch);
857
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
858
#endif
859
}
860

861
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
8✔
862
#if defined(BOTAN_HAS_X509_CERTIFICATES)
863
   return BOTAN_FFI_CHECKED_DELETE(crl);
8✔
864
#else
865
   BOTAN_UNUSED(crl);
866
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
867
#endif
868
}
869

870
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
871
#if defined(BOTAN_HAS_X509_CERTIFICATES)
872
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
873
#else
874
   BOTAN_UNUSED(cert);
875
   BOTAN_UNUSED(crl);
876
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
877
#endif
878
}
879

880
int botan_x509_crl_entries(botan_x509_crl_t crl, size_t index, botan_x509_crl_entry_t* entry) {
3✔
881
#if defined(BOTAN_HAS_X509_CERTIFICATES)
882
   return BOTAN_FFI_VISIT(crl, [=](const Botan::X509_CRL& c) -> int {
6✔
883
      const auto& entries = c.get_revoked();
884
      if(index >= entries.size()) {
885
         return BOTAN_FFI_ERROR_OUT_OF_RANGE;
886
      }
887

888
      if(Botan::any_null_pointers(entry)) {
889
         return BOTAN_FFI_ERROR_NULL_POINTER;
890
      }
891

892
      return ffi_new_object(entry, std::make_unique<Botan::CRL_Entry>(entries[index]));
893
   });
894
#else
895
   BOTAN_UNUSED(crl, index, entry);
896
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
897
#endif
898
}
899

900
int botan_x509_crl_entries_count(botan_x509_crl_t crl, size_t* count) {
2✔
901
#if defined(BOTAN_HAS_X509_CERTIFICATES)
902
   if(Botan::any_null_pointers(count)) {
2✔
903
      return BOTAN_FFI_ERROR_NULL_POINTER;
904
   }
905

906
   return BOTAN_FFI_VISIT(crl, [=](const Botan::X509_CRL& c) { *count = c.get_revoked().size(); });
4✔
907
#else
908
   BOTAN_UNUSED(crl, count);
909
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
910
#endif
911
}
912

913
int botan_x509_crl_entry_destroy(botan_x509_crl_entry_t entry) {
1✔
914
#if defined(BOTAN_HAS_X509_CERTIFICATES)
915
   return BOTAN_FFI_CHECKED_DELETE(entry);
1✔
916
#else
917
   BOTAN_UNUSED(entry);
918
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
919
#endif
920
}
921

922
int botan_x509_crl_entry_reason(botan_x509_crl_entry_t entry, int* reason_code) {
1✔
923
#if defined(BOTAN_HAS_X509_CERTIFICATES)
924
   return BOTAN_FFI_VISIT(entry, [=](const Botan::CRL_Entry& e) {
2✔
925
      if(Botan::any_null_pointers(reason_code)) {
926
         return BOTAN_FFI_ERROR_NULL_POINTER;
927
      }
928

929
      *reason_code = static_cast<int>(e.reason_code());
930
      return BOTAN_FFI_SUCCESS;
931
   });
932
#else
933
   BOTAN_UNUSED(entry, reason_code);
934
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
935
#endif
936
}
937

938
int botan_x509_crl_entry_serial_number(botan_x509_crl_entry_t entry, botan_mp_t* serial_number) {
1✔
939
#if defined(BOTAN_HAS_X509_CERTIFICATES)
940
   return BOTAN_FFI_VISIT(entry, [=](const Botan::CRL_Entry& e) {
2✔
941
      if(Botan::any_null_pointers(serial_number)) {
942
         return BOTAN_FFI_ERROR_NULL_POINTER;
943
      }
944

945
      auto serial_bn = Botan::BigInt::from_bytes(e.serial_number());
946
      return ffi_new_object(serial_number, std::make_unique<Botan::BigInt>(std::move(serial_bn)));
947
   });
948
#else
949
   BOTAN_UNUSED(entry, serial_number);
950
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
951
#endif
952
}
953

954
int botan_x509_crl_entry_view_serial_number(botan_x509_crl_entry_t entry, botan_view_ctx ctx, botan_view_bin_fn view) {
1✔
955
#if defined(BOTAN_HAS_X509_CERTIFICATES)
956
   return BOTAN_FFI_VISIT(
2✔
957
      entry, [=](const Botan::CRL_Entry& e) { return invoke_view_callback(view, ctx, e.serial_number()); });
958
#else
959
   BOTAN_UNUSED(entry, ctx, view);
960
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
961
#endif
962
}
963

964
int botan_x509_crl_entry_revocation_date(botan_x509_crl_entry_t entry, uint64_t* time_since_epoch) {
1✔
965
#if defined(BOTAN_HAS_X509_CERTIFICATES)
966
   return BOTAN_FFI_VISIT(entry, [=](const Botan::CRL_Entry& e) {
2✔
967
      if(Botan::any_null_pointers(time_since_epoch)) {
968
         return BOTAN_FFI_ERROR_NULL_POINTER;
969
      }
970

971
      *time_since_epoch = e.expire_time().time_since_epoch();
972
      return BOTAN_FFI_SUCCESS;
973
   });
974
#else
975
   BOTAN_UNUSED(entry, time_since_epoch);
976
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
977
#endif
978
}
979

980
int botan_x509_cert_verify_with_crl(int* result_code,
12✔
981
                                    botan_x509_cert_t cert,
982
                                    const botan_x509_cert_t* intermediates,
983
                                    size_t intermediates_len,
984
                                    const botan_x509_cert_t* trusted,
985
                                    size_t trusted_len,
986
                                    const botan_x509_crl_t* crls,
987
                                    size_t crls_len,
988
                                    const char* trusted_path,
989
                                    size_t required_strength,
990
                                    const char* hostname_cstr,
991
                                    uint64_t reference_time) {
992
   if(required_strength == 0) {
12✔
993
      required_strength = 110;
2✔
994
   }
995

996
#if defined(BOTAN_HAS_X509_CERTIFICATES)
997
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
998
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
14✔
999
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
12✔
1000
      const auto validation_time = reference_time == 0
12✔
1001
                                      ? std::chrono::system_clock::now()
12✔
1002
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
1✔
1003

1004
      std::vector<Botan::X509_Certificate> end_certs;
12✔
1005
      end_certs.push_back(safe_get(cert));
12✔
1006
      for(size_t i = 0; i != intermediates_len; ++i) {
30✔
1007
         end_certs.push_back(safe_get(intermediates[i]));
18✔
1008
      }
1009

1010
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
12✔
1011
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
12✔
1012
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
12✔
1013
      std::vector<Botan::Certificate_Store*> trusted_roots;
12✔
1014

1015
      if(trusted_path != nullptr && *trusted_path != 0) {
12✔
1016
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
1017
         trusted_roots.push_back(trusted_from_path.get());
2✔
1018
      }
1019

1020
      if(trusted_len > 0) {
12✔
1021
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
18✔
1022
         for(size_t i = 0; i != trusted_len; ++i) {
18✔
1023
            trusted_extra->add_certificate(safe_get(trusted[i]));
9✔
1024
         }
1025
         trusted_roots.push_back(trusted_extra.get());
9✔
1026
      }
1027

1028
      if(crls_len > 0) {
12✔
1029
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
10✔
1030
         for(size_t i = 0; i != crls_len; ++i) {
13✔
1031
            trusted_crls->add_crl(safe_get(crls[i]));
8✔
1032
         }
1033
         trusted_roots.push_back(trusted_crls.get());
5✔
1034
      }
1035

1036
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
24✔
1037

1038
      auto validation_result =
12✔
1039
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
12✔
1040

1041
      if(result_code != nullptr) {
12✔
1042
         *result_code = static_cast<int>(validation_result.result());
12✔
1043
      }
1044

1045
      if(validation_result.successful_validation()) {
12✔
1046
         return 0;
1047
      } else {
1048
         return 1;
8✔
1049
      }
1050
   });
14✔
1051
#else
1052
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
1053
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
1054
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
1055
#endif
1056
}
1057
}
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