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

randombit / botan / 20858472605

09 Jan 2026 04:29PM UTC coverage: 90.432% (+0.005%) from 90.427%
20858472605

Pull #5221

github

web-flow
Merge b56bd83fd into 1295fc35c
Pull Request #5221: FFI: Allow querying more X.509 Certificate Constraints

101734 of 112498 relevant lines covered (90.43%)

12956199.65 hits per line

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

93.75
/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/data_src.h>
15
   #include <botan/x509_crl.h>
16
   #include <botan/x509cert.h>
17
   #include <botan/x509path.h>
18
#endif
19

20
extern "C" {
21

22
using namespace Botan_FFI;
23

24
#if defined(BOTAN_HAS_X509_CERTIFICATES)
25

26
BOTAN_FFI_DECLARE_STRUCT(botan_x509_cert_struct, Botan::X509_Certificate, 0x8F628937);
27✔
27

28
#endif
29

30
int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path) {
26✔
31
   if(cert_obj == nullptr || cert_path == nullptr) {
26✔
32
      return BOTAN_FFI_ERROR_NULL_POINTER;
33
   }
34

35
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
36

37
   return ffi_guard_thunk(__func__, [=]() -> int {
26✔
38
      auto c = std::make_unique<Botan::X509_Certificate>(cert_path);
26✔
39
      return ffi_new_object(cert_obj, std::move(c));
26✔
40
   });
52✔
41

42
#else
43
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
44
#endif
45
}
46

47
int botan_x509_cert_dup(botan_x509_cert_t* cert_obj, botan_x509_cert_t cert) {
1✔
48
   if(cert_obj == nullptr) {
1✔
49
      return BOTAN_FFI_ERROR_NULL_POINTER;
50
   }
51

52
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
53

54
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
55
      auto c = std::make_unique<Botan::X509_Certificate>(safe_get(cert));
1✔
56
      return ffi_new_object(cert_obj, std::move(c));
1✔
57
   });
2✔
58

59
#else
60
   BOTAN_UNUSED(cert);
61
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
62
#endif
63
}
64

65
int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert_bits[], size_t cert_bits_len) {
×
66
   if(cert_obj == nullptr || cert_bits == nullptr) {
×
67
      return BOTAN_FFI_ERROR_NULL_POINTER;
68
   }
69

70
#if defined(BOTAN_HAS_X509_CERTIFICATES)
71
   return ffi_guard_thunk(__func__, [=]() -> int {
×
72
      Botan::DataSource_Memory bits(cert_bits, cert_bits_len);
×
73
      auto c = std::make_unique<Botan::X509_Certificate>(bits);
×
74
      return ffi_new_object(cert_obj, std::move(c));
×
75
   });
×
76
#else
77
   BOTAN_UNUSED(cert_bits_len);
78
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
79
#endif
80
}
81

82
int botan_x509_cert_is_ca(botan_x509_cert_t cert) {
2✔
83
#if defined(BOTAN_HAS_X509_CERTIFICATES)
84
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.is_CA_cert() ? BOTAN_FFI_SUCCESS : 1; });
4✔
85
#else
86
   BOTAN_UNUSED(cert);
87
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
88
#endif
89
}
90

91
int botan_x509_cert_get_path_length_constraint(botan_x509_cert_t cert, size_t* path_limit) {
2✔
92
#if defined(BOTAN_HAS_X509_CERTIFICATES)
93
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
4✔
94
      if(Botan::any_null_pointers(path_limit)) {
95
         return BOTAN_FFI_ERROR_NULL_POINTER;
96
      }
97

98
      if(const auto path_len = c.path_length_constraint()) {
99
         *path_limit = path_len.value();
100
         return BOTAN_FFI_SUCCESS;
101
      } else {
102
         return BOTAN_FFI_ERROR_NO_VALUE;
103
      }
104
   });
105
#else
106
   BOTAN_UNUSED(cert, path_limit);
107
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
108
#endif
109
}
110

111
int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) {
2✔
112
   if(key == nullptr) {
2✔
113
      return BOTAN_FFI_ERROR_NULL_POINTER;
114
   }
115

116
   *key = nullptr;
2✔
117

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

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

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

165
int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
166
   return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert);
2✔
167
}
168

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

178
int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage) {
7✔
179
#if defined(BOTAN_HAS_X509_CERTIFICATES)
180
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
14✔
181
      const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
182
      if(c.allowed_usage(k)) {
183
         return BOTAN_FFI_SUCCESS;
184
      }
185
      return 1;
186
   });
187
#else
188
   BOTAN_UNUSED(cert, key_usage);
189
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
190
#endif
191
}
192

193
int botan_x509_cert_allowed_extended_usage(botan_x509_cert_t cert, const char* oid) {
12✔
194
#if defined(BOTAN_HAS_X509_CERTIFICATES)
195
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
32✔
196
      if(Botan::any_null_pointers(oid)) {
197
         return BOTAN_FFI_ERROR_NULL_POINTER;
198
      }
199

200
      return c.has_ex_constraint(oid) ? BOTAN_FFI_SUCCESS : 1;
201
   });
202
#else
203
   BOTAN_UNUSED(cert, oid);
204
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
205
#endif
206
}
207

208
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
27✔
209
#if defined(BOTAN_HAS_X509_CERTIFICATES)
210
   return BOTAN_FFI_CHECKED_DELETE(cert);
27✔
211
#else
212
   BOTAN_UNUSED(cert);
213
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
214
#endif
215
}
216

217
int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len) {
3✔
218
#if defined(BOTAN_HAS_X509_CERTIFICATES)
219
   return BOTAN_FFI_VISIT(cert,
6✔
220
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_before().to_string()); });
221
#else
222
   BOTAN_UNUSED(cert, out, out_len);
223
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
224
#endif
225
}
226

227
int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
228
#if defined(BOTAN_HAS_X509_CERTIFICATES)
229
   return BOTAN_FFI_VISIT(cert,
4✔
230
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); });
231
#else
232
   BOTAN_UNUSED(cert, out, out_len);
233
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
234
#endif
235
}
236

237
int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
238
#if defined(BOTAN_HAS_X509_CERTIFICATES)
239
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_before().time_since_epoch(); });
4✔
240
#else
241
   BOTAN_UNUSED(cert, time_since_epoch);
242
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
243
#endif
244
}
245

246
int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
247
#if defined(BOTAN_HAS_X509_CERTIFICATES)
248
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); });
4✔
249
#else
250
   BOTAN_UNUSED(cert, time_since_epoch);
251
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
252
#endif
253
}
254

255
int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
256
#if defined(BOTAN_HAS_X509_CERTIFICATES)
257
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); });
6✔
258
#else
259
   BOTAN_UNUSED(cert, out, out_len);
260
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
261
#endif
262
}
263

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

268
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) {
6✔
269
      return write_str_output(reinterpret_cast<char*>(out), out_len, c.fingerprint(hash));
270
   });
271
#else
272
   BOTAN_UNUSED(cert, hash, out, out_len);
273
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
274
#endif
275
}
276

277
int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
1✔
278
#if defined(BOTAN_HAS_X509_CERTIFICATES)
279
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); });
2✔
280
#else
281
   BOTAN_UNUSED(cert, out, out_len);
282
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
283
#endif
284
}
285

286
int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
287
#if defined(BOTAN_HAS_X509_CERTIFICATES)
288
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
6✔
289
#else
290
   BOTAN_UNUSED(cert, out, out_len);
291
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
292
#endif
293
}
294

295
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
296
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
297
}
298

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

309
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
6✔
310
   if(hostname == nullptr) {
6✔
311
      return BOTAN_FFI_ERROR_NULL_POINTER;
312
   }
313

314
#if defined(BOTAN_HAS_X509_CERTIFICATES)
315
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
12✔
316
#else
317
   BOTAN_UNUSED(cert);
318
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
319
#endif
320
}
321

322
int botan_x509_cert_verify(int* result_code,
4✔
323
                           botan_x509_cert_t cert,
324
                           const botan_x509_cert_t* intermediates,
325
                           size_t intermediates_len,
326
                           const botan_x509_cert_t* trusted,
327
                           size_t trusted_len,
328
                           const char* trusted_path,
329
                           size_t required_strength,
330
                           const char* hostname_cstr,
331
                           uint64_t reference_time) {
332
   if(required_strength == 0) {
4✔
333
      required_strength = 110;
3✔
334
   }
335

336
#if defined(BOTAN_HAS_X509_CERTIFICATES)
337
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
338
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
4✔
339
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
4✔
340
      const auto validation_time = reference_time == 0
4✔
341
                                      ? std::chrono::system_clock::now()
4✔
342
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
×
343

344
      std::vector<Botan::X509_Certificate> end_certs;
4✔
345
      end_certs.push_back(safe_get(cert));
4✔
346
      for(size_t i = 0; i != intermediates_len; ++i) {
9✔
347
         end_certs.push_back(safe_get(intermediates[i]));
5✔
348
      }
349

350
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
4✔
351
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
4✔
352
      std::vector<Botan::Certificate_Store*> trusted_roots;
4✔
353

354
      if(trusted_path != nullptr && *trusted_path != 0) {
4✔
355
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
356
         trusted_roots.push_back(trusted_from_path.get());
×
357
      }
358

359
      if(trusted_len > 0) {
4✔
360
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
8✔
361
         for(size_t i = 0; i != trusted_len; ++i) {
8✔
362
            trusted_extra->add_certificate(safe_get(trusted[i]));
4✔
363
         }
364
         trusted_roots.push_back(trusted_extra.get());
4✔
365
      }
366

367
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
8✔
368

369
      auto validation_result =
4✔
370
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
4✔
371

372
      if(result_code != nullptr) {
4✔
373
         *result_code = static_cast<int>(validation_result.result());
4✔
374
      }
375

376
      if(validation_result.successful_validation()) {
4✔
377
         return 0;
378
      } else {
379
         return 1;
3✔
380
      }
381
   });
4✔
382
#else
383
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
384
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
385
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
386
#endif
387
}
388

389
const char* botan_x509_cert_validation_status(int code) {
11✔
390
   if(code < 0) {
11✔
391
      return nullptr;
392
   }
393

394
#if defined(BOTAN_HAS_X509_CERTIFICATES)
395
   const Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
396
   return Botan::to_string(sc);
11✔
397
#else
398
   return nullptr;
399
#endif
400
}
401

402
#if defined(BOTAN_HAS_X509_CERTIFICATES)
403

404
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
7✔
405

406
#endif
407

408
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
6✔
409
   if(crl_obj == nullptr || crl_path == nullptr) {
6✔
410
      return BOTAN_FFI_ERROR_NULL_POINTER;
411
   }
412

413
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
414

415
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
416
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
6✔
417
      return ffi_new_object(crl_obj, std::move(c));
12✔
418
   });
12✔
419

420
#else
421
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
422
#endif
423
}
424

425
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
1✔
426
   if(crl_obj == nullptr || crl_bits == nullptr) {
1✔
427
      return BOTAN_FFI_ERROR_NULL_POINTER;
428
   }
429

430
#if defined(BOTAN_HAS_X509_CERTIFICATES)
431
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
432
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
1✔
433
      auto c = std::make_unique<Botan::X509_CRL>(bits);
1✔
434
      return ffi_new_object(crl_obj, std::move(c));
1✔
435
   });
3✔
436
#else
437
   BOTAN_UNUSED(crl_bits_len);
438
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
439
#endif
440
}
441

442
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
7✔
443
#if defined(BOTAN_HAS_X509_CERTIFICATES)
444
   return BOTAN_FFI_CHECKED_DELETE(crl);
7✔
445
#else
446
   BOTAN_UNUSED(crl);
447
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
448
#endif
449
}
450

451
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
452
#if defined(BOTAN_HAS_X509_CERTIFICATES)
453
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
454
#else
455
   BOTAN_UNUSED(cert);
456
   BOTAN_UNUSED(crl);
457
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
458
#endif
459
}
460

461
int botan_x509_cert_verify_with_crl(int* result_code,
12✔
462
                                    botan_x509_cert_t cert,
463
                                    const botan_x509_cert_t* intermediates,
464
                                    size_t intermediates_len,
465
                                    const botan_x509_cert_t* trusted,
466
                                    size_t trusted_len,
467
                                    const botan_x509_crl_t* crls,
468
                                    size_t crls_len,
469
                                    const char* trusted_path,
470
                                    size_t required_strength,
471
                                    const char* hostname_cstr,
472
                                    uint64_t reference_time) {
473
   if(required_strength == 0) {
12✔
474
      required_strength = 110;
2✔
475
   }
476

477
#if defined(BOTAN_HAS_X509_CERTIFICATES)
478
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
479
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
14✔
480
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
12✔
481
      const auto validation_time = reference_time == 0
12✔
482
                                      ? std::chrono::system_clock::now()
12✔
483
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
1✔
484

485
      std::vector<Botan::X509_Certificate> end_certs;
12✔
486
      end_certs.push_back(safe_get(cert));
12✔
487
      for(size_t i = 0; i != intermediates_len; ++i) {
30✔
488
         end_certs.push_back(safe_get(intermediates[i]));
18✔
489
      }
490

491
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
12✔
492
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
12✔
493
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
12✔
494
      std::vector<Botan::Certificate_Store*> trusted_roots;
12✔
495

496
      if(trusted_path != nullptr && *trusted_path != 0) {
12✔
497
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
498
         trusted_roots.push_back(trusted_from_path.get());
2✔
499
      }
500

501
      if(trusted_len > 0) {
12✔
502
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
18✔
503
         for(size_t i = 0; i != trusted_len; ++i) {
18✔
504
            trusted_extra->add_certificate(safe_get(trusted[i]));
9✔
505
         }
506
         trusted_roots.push_back(trusted_extra.get());
9✔
507
      }
508

509
      if(crls_len > 0) {
12✔
510
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
10✔
511
         for(size_t i = 0; i != crls_len; ++i) {
13✔
512
            trusted_crls->add_crl(safe_get(crls[i]));
8✔
513
         }
514
         trusted_roots.push_back(trusted_crls.get());
5✔
515
      }
516

517
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
24✔
518

519
      auto validation_result =
12✔
520
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
12✔
521

522
      if(result_code != nullptr) {
12✔
523
         *result_code = static_cast<int>(validation_result.result());
12✔
524
      }
525

526
      if(validation_result.successful_validation()) {
12✔
527
         return 0;
528
      } else {
529
         return 1;
8✔
530
      }
531
   });
14✔
532
#else
533
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
534
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
535
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
536
#endif
537
}
538
}
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