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

randombit / botan / 20897916272

11 Jan 2026 03:58PM UTC coverage: 90.428% (+0.008%) from 90.42%
20897916272

push

github

web-flow
Merge pull request #5221 from Rohde-Schwarz/feature/ffi_query_cert_constraints

FFI: Allow querying more X.509 Certificate Constraints

101769 of 112541 relevant lines covered (90.43%)

12793144.85 hits per line

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

93.98
/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
   #include <botan/internal/ffi_oid.h>
19
#endif
20

21
extern "C" {
22

23
using namespace Botan_FFI;
24

25
#if defined(BOTAN_HAS_X509_CERTIFICATES)
26

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

29
#endif
30

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

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

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

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

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

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

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

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

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

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

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

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

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

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

117
   *key = nullptr;
2✔
118

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

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

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

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

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

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

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

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

209
int botan_x509_cert_allowed_extended_usage_oid(botan_x509_cert_t cert, botan_asn1_oid_t oid) {
4✔
210
#if defined(BOTAN_HAS_X509_CERTIFICATES)
211
   return BOTAN_FFI_VISIT(
8✔
212
      cert, [=](const auto& c) -> int { return c.has_ex_constraint(safe_get(oid)) ? BOTAN_FFI_SUCCESS : 1; });
213
#else
214
   BOTAN_UNUSED(cert, oid);
215
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
216
#endif
217
}
218

219
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
27✔
220
#if defined(BOTAN_HAS_X509_CERTIFICATES)
221
   return BOTAN_FFI_CHECKED_DELETE(cert);
27✔
222
#else
223
   BOTAN_UNUSED(cert);
224
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
225
#endif
226
}
227

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

238
int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
239
#if defined(BOTAN_HAS_X509_CERTIFICATES)
240
   return BOTAN_FFI_VISIT(cert,
4✔
241
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); });
242
#else
243
   BOTAN_UNUSED(cert, out, out_len);
244
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
245
#endif
246
}
247

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

257
int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
258
#if defined(BOTAN_HAS_X509_CERTIFICATES)
259
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); });
4✔
260
#else
261
   BOTAN_UNUSED(cert, time_since_epoch);
262
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
263
#endif
264
}
265

266
int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
267
#if defined(BOTAN_HAS_X509_CERTIFICATES)
268
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); });
6✔
269
#else
270
   BOTAN_UNUSED(cert, out, out_len);
271
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
272
#endif
273
}
274

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

279
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) {
6✔
280
      return write_str_output(reinterpret_cast<char*>(out), out_len, c.fingerprint(hash));
281
   });
282
#else
283
   BOTAN_UNUSED(cert, hash, out, out_len);
284
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
285
#endif
286
}
287

288
int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
1✔
289
#if defined(BOTAN_HAS_X509_CERTIFICATES)
290
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); });
2✔
291
#else
292
   BOTAN_UNUSED(cert, out, out_len);
293
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
294
#endif
295
}
296

297
int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
298
#if defined(BOTAN_HAS_X509_CERTIFICATES)
299
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
6✔
300
#else
301
   BOTAN_UNUSED(cert, out, out_len);
302
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
303
#endif
304
}
305

306
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
307
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
308
}
309

310
int botan_x509_cert_view_public_key_bits(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
311
#if defined(BOTAN_HAS_X509_CERTIFICATES)
312
   return BOTAN_FFI_VISIT(cert,
6✔
313
                          [=](const auto& c) { return invoke_view_callback(view, ctx, c.subject_public_key_bits()); });
314
#else
315
   BOTAN_UNUSED(cert, ctx, view);
316
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
317
#endif
318
}
319

320
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
6✔
321
   if(hostname == nullptr) {
6✔
322
      return BOTAN_FFI_ERROR_NULL_POINTER;
323
   }
324

325
#if defined(BOTAN_HAS_X509_CERTIFICATES)
326
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
12✔
327
#else
328
   BOTAN_UNUSED(cert);
329
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
330
#endif
331
}
332

333
int botan_x509_cert_verify(int* result_code,
4✔
334
                           botan_x509_cert_t cert,
335
                           const botan_x509_cert_t* intermediates,
336
                           size_t intermediates_len,
337
                           const botan_x509_cert_t* trusted,
338
                           size_t trusted_len,
339
                           const char* trusted_path,
340
                           size_t required_strength,
341
                           const char* hostname_cstr,
342
                           uint64_t reference_time) {
343
   if(required_strength == 0) {
4✔
344
      required_strength = 110;
3✔
345
   }
346

347
#if defined(BOTAN_HAS_X509_CERTIFICATES)
348
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
349
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
4✔
350
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
4✔
351
      const auto validation_time = reference_time == 0
4✔
352
                                      ? std::chrono::system_clock::now()
4✔
353
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
×
354

355
      std::vector<Botan::X509_Certificate> end_certs;
4✔
356
      end_certs.push_back(safe_get(cert));
4✔
357
      for(size_t i = 0; i != intermediates_len; ++i) {
9✔
358
         end_certs.push_back(safe_get(intermediates[i]));
5✔
359
      }
360

361
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
4✔
362
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
4✔
363
      std::vector<Botan::Certificate_Store*> trusted_roots;
4✔
364

365
      if(trusted_path != nullptr && *trusted_path != 0) {
4✔
366
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
367
         trusted_roots.push_back(trusted_from_path.get());
×
368
      }
369

370
      if(trusted_len > 0) {
4✔
371
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
8✔
372
         for(size_t i = 0; i != trusted_len; ++i) {
8✔
373
            trusted_extra->add_certificate(safe_get(trusted[i]));
4✔
374
         }
375
         trusted_roots.push_back(trusted_extra.get());
4✔
376
      }
377

378
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
8✔
379

380
      auto validation_result =
4✔
381
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
4✔
382

383
      if(result_code != nullptr) {
4✔
384
         *result_code = static_cast<int>(validation_result.result());
4✔
385
      }
386

387
      if(validation_result.successful_validation()) {
4✔
388
         return 0;
389
      } else {
390
         return 1;
3✔
391
      }
392
   });
4✔
393
#else
394
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
395
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
396
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
397
#endif
398
}
399

400
const char* botan_x509_cert_validation_status(int code) {
11✔
401
   if(code < 0) {
11✔
402
      return nullptr;
403
   }
404

405
#if defined(BOTAN_HAS_X509_CERTIFICATES)
406
   const Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
407
   return Botan::to_string(sc);
11✔
408
#else
409
   return nullptr;
410
#endif
411
}
412

413
#if defined(BOTAN_HAS_X509_CERTIFICATES)
414

415
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
8✔
416

417
#endif
418

419
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
7✔
420
   if(crl_obj == nullptr || crl_path == nullptr) {
7✔
421
      return BOTAN_FFI_ERROR_NULL_POINTER;
422
   }
423

424
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
425

426
   return ffi_guard_thunk(__func__, [=]() -> int {
7✔
427
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
7✔
428
      return ffi_new_object(crl_obj, std::move(c));
14✔
429
   });
14✔
430

431
#else
432
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
433
#endif
434
}
435

436
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
1✔
437
   if(crl_obj == nullptr || crl_bits == nullptr) {
1✔
438
      return BOTAN_FFI_ERROR_NULL_POINTER;
439
   }
440

441
#if defined(BOTAN_HAS_X509_CERTIFICATES)
442
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
443
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
1✔
444
      auto c = std::make_unique<Botan::X509_CRL>(bits);
1✔
445
      return ffi_new_object(crl_obj, std::move(c));
1✔
446
   });
3✔
447
#else
448
   BOTAN_UNUSED(crl_bits_len);
449
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
450
#endif
451
}
452

453
int botan_x509_crl_this_update(botan_x509_crl_t crl, uint64_t* time_since_epoch) {
2✔
454
#if defined(BOTAN_HAS_X509_CERTIFICATES)
455
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) {
4✔
456
      if(Botan::any_null_pointers(time_since_epoch)) {
457
         return BOTAN_FFI_ERROR_NULL_POINTER;
458
      }
459
      *time_since_epoch = c.this_update().time_since_epoch();
460
      return BOTAN_FFI_SUCCESS;
461
   });
462
#else
463
   BOTAN_UNUSED(crl, time_since_epoch);
464
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
465
#endif
466
}
467

468
int botan_x509_crl_next_update(botan_x509_crl_t crl, uint64_t* time_since_epoch) {
4✔
469
#if defined(BOTAN_HAS_X509_CERTIFICATES)
470
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) {
8✔
471
      const auto& time = c.next_update();
472
      if(!time.time_is_set()) {
473
         return BOTAN_FFI_ERROR_NO_VALUE;
474
      }
475

476
      if(Botan::any_null_pointers(time_since_epoch)) {
477
         return BOTAN_FFI_ERROR_NULL_POINTER;
478
      }
479

480
      *time_since_epoch = c.next_update().time_since_epoch();
481
      return BOTAN_FFI_SUCCESS;
482
   });
483
#else
484
   BOTAN_UNUSED(crl, time_since_epoch);
485
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
486
#endif
487
}
488

489
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
8✔
490
#if defined(BOTAN_HAS_X509_CERTIFICATES)
491
   return BOTAN_FFI_CHECKED_DELETE(crl);
8✔
492
#else
493
   BOTAN_UNUSED(crl);
494
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
495
#endif
496
}
497

498
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
499
#if defined(BOTAN_HAS_X509_CERTIFICATES)
500
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
501
#else
502
   BOTAN_UNUSED(cert);
503
   BOTAN_UNUSED(crl);
504
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
505
#endif
506
}
507

508
int botan_x509_cert_verify_with_crl(int* result_code,
12✔
509
                                    botan_x509_cert_t cert,
510
                                    const botan_x509_cert_t* intermediates,
511
                                    size_t intermediates_len,
512
                                    const botan_x509_cert_t* trusted,
513
                                    size_t trusted_len,
514
                                    const botan_x509_crl_t* crls,
515
                                    size_t crls_len,
516
                                    const char* trusted_path,
517
                                    size_t required_strength,
518
                                    const char* hostname_cstr,
519
                                    uint64_t reference_time) {
520
   if(required_strength == 0) {
12✔
521
      required_strength = 110;
2✔
522
   }
523

524
#if defined(BOTAN_HAS_X509_CERTIFICATES)
525
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
526
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
14✔
527
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
12✔
528
      const auto validation_time = reference_time == 0
12✔
529
                                      ? std::chrono::system_clock::now()
12✔
530
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
1✔
531

532
      std::vector<Botan::X509_Certificate> end_certs;
12✔
533
      end_certs.push_back(safe_get(cert));
12✔
534
      for(size_t i = 0; i != intermediates_len; ++i) {
30✔
535
         end_certs.push_back(safe_get(intermediates[i]));
18✔
536
      }
537

538
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
12✔
539
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
12✔
540
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
12✔
541
      std::vector<Botan::Certificate_Store*> trusted_roots;
12✔
542

543
      if(trusted_path != nullptr && *trusted_path != 0) {
12✔
544
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
545
         trusted_roots.push_back(trusted_from_path.get());
2✔
546
      }
547

548
      if(trusted_len > 0) {
12✔
549
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
18✔
550
         for(size_t i = 0; i != trusted_len; ++i) {
18✔
551
            trusted_extra->add_certificate(safe_get(trusted[i]));
9✔
552
         }
553
         trusted_roots.push_back(trusted_extra.get());
9✔
554
      }
555

556
      if(crls_len > 0) {
12✔
557
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
10✔
558
         for(size_t i = 0; i != crls_len; ++i) {
13✔
559
            trusted_crls->add_crl(safe_get(crls[i]));
8✔
560
         }
561
         trusted_roots.push_back(trusted_crls.get());
5✔
562
      }
563

564
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
24✔
565

566
      auto validation_result =
12✔
567
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
12✔
568

569
      if(result_code != nullptr) {
12✔
570
         *result_code = static_cast<int>(validation_result.result());
12✔
571
      }
572

573
      if(validation_result.successful_validation()) {
12✔
574
         return 0;
575
      } else {
576
         return 1;
8✔
577
      }
578
   });
14✔
579
#else
580
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
581
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
582
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
583
#endif
584
}
585
}
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