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

randombit / botan / 21892189369

11 Feb 2026 12:53AM UTC coverage: 90.069% (-1.6%) from 91.638%
21892189369

push

github

web-flow
Merge pull request #5302 from randombit/jack/header-patrol-4

Cleanup various header inclusions

102230 of 113502 relevant lines covered (90.07%)

11577018.64 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/assert.h>
16
   #include <botan/data_src.h>
17
   #include <botan/x509_crl.h>
18
   #include <botan/x509cert.h>
19
   #include <botan/x509path.h>
20
   #include <botan/internal/ffi_mp.h>
21
   #include <botan/internal/ffi_oid.h>
22
#endif
23

24
#if defined(BOTAN_HAS_X509_CERTIFICATES)
25

26
namespace Botan_FFI {
27

28
namespace {
29

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

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

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

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

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

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

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

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

108
   BOTAN_ASSERT_UNREACHABLE();
×
109
}
110

111
}  // namespace
112

113
}  // namespace Botan_FFI
114

115
#endif
116

117
extern "C" {
118

119
using namespace Botan_FFI;
120

121
#if defined(BOTAN_HAS_X509_CERTIFICATES)
122

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

126
#endif
127

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

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

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

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

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

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

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

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

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

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

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

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

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

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

214
   *key = nullptr;
2✔
215

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

785
#if defined(BOTAN_HAS_X509_CERTIFICATES)
786

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

790
#endif
791

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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