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

randombit / botan / 20295000893

17 Dec 2025 07:24AM UTC coverage: 90.52% (+0.2%) from 90.36%
20295000893

Pull #5167

github

web-flow
Merge 70b91cb18 into 3d96b675e
Pull Request #5167: Changes to reduce unnecessary inclusions

101154 of 111748 relevant lines covered (90.52%)

12785105.95 hits per line

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

93.51
/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/x509_time.h>
17
   #include <botan/x509cert.h>
18
   #include <botan/x509path.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);
24✔
28

29
#endif
30

31
int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path) {
23✔
32
   if(cert_obj == nullptr || cert_path == nullptr) {
23✔
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 {
23✔
39
      auto c = std::make_unique<Botan::X509_Certificate>(cert_path);
23✔
40
      return ffi_new_object(cert_obj, std::move(c));
23✔
41
   });
46✔
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_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) {
2✔
84
   if(key == nullptr) {
2✔
85
      return BOTAN_FFI_ERROR_NULL_POINTER;
86
   }
87

88
   *key = nullptr;
2✔
89

90
#if defined(BOTAN_HAS_X509_CERTIFICATES)
91
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
92
      auto public_key = safe_get(cert).subject_public_key();
2✔
93
      return ffi_new_object(key, std::move(public_key));
2✔
94
   });
4✔
95
#else
96
   BOTAN_UNUSED(cert);
97
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
98
#endif
99
}
100

101
int botan_x509_cert_get_issuer_dn(
8✔
102
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
103
#if defined(BOTAN_HAS_X509_CERTIFICATES)
104
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
105
      auto issuer_info = c.issuer_info(key);
106
      if(index < issuer_info.size()) {
107
         // TODO(Botan4) change the type of out and remove this cast
108
         return write_str_output(reinterpret_cast<char*>(out), out_len, c.issuer_info(key).at(index));
109
      } else {
110
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
111
      }
112
   });
113
#else
114
   BOTAN_UNUSED(cert, key, index, out, out_len);
115
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
116
#endif
117
}
118

119
int botan_x509_cert_get_subject_dn(
8✔
120
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
121
#if defined(BOTAN_HAS_X509_CERTIFICATES)
122
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
16✔
123
      auto subject_info = c.subject_info(key);
124
      if(index < subject_info.size()) {
125
         // TODO(Botan4) change the type of out and remove this cast
126
         return write_str_output(reinterpret_cast<char*>(out), out_len, c.subject_info(key).at(index));
127
      } else {
128
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
129
      }
130
   });
131
#else
132
   BOTAN_UNUSED(cert, key, index, out, out_len);
133
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
134
#endif
135
}
136

137
int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
138
   return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert);
2✔
139
}
140

141
int botan_x509_cert_view_as_string(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) {
3✔
142
#if defined(BOTAN_HAS_X509_CERTIFICATES)
143
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return invoke_view_callback(view, ctx, c.to_string()); });
9✔
144
#else
145
   BOTAN_UNUSED(cert, ctx, view);
146
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
147
#endif
148
}
149

150
int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage) {
7✔
151
#if defined(BOTAN_HAS_X509_CERTIFICATES)
152
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
14✔
153
      const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
154
      if(c.allowed_usage(k)) {
155
         return BOTAN_FFI_SUCCESS;
156
      }
157
      return 1;
158
   });
159
#else
160
   BOTAN_UNUSED(cert, key_usage);
161
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
162
#endif
163
}
164

165
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
24✔
166
#if defined(BOTAN_HAS_X509_CERTIFICATES)
167
   return BOTAN_FFI_CHECKED_DELETE(cert);
24✔
168
#else
169
   BOTAN_UNUSED(cert);
170
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
171
#endif
172
}
173

174
int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len) {
3✔
175
#if defined(BOTAN_HAS_X509_CERTIFICATES)
176
   return BOTAN_FFI_VISIT(cert,
6✔
177
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_before().to_string()); });
178
#else
179
   BOTAN_UNUSED(cert, out, out_len);
180
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
181
#endif
182
}
183

184
int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
185
#if defined(BOTAN_HAS_X509_CERTIFICATES)
186
   return BOTAN_FFI_VISIT(cert,
4✔
187
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); });
188
#else
189
   BOTAN_UNUSED(cert, out, out_len);
190
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
191
#endif
192
}
193

194
int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
195
#if defined(BOTAN_HAS_X509_CERTIFICATES)
196
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_before().time_since_epoch(); });
4✔
197
#else
198
   BOTAN_UNUSED(cert, time_since_epoch);
199
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
200
#endif
201
}
202

203
int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
204
#if defined(BOTAN_HAS_X509_CERTIFICATES)
205
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); });
4✔
206
#else
207
   BOTAN_UNUSED(cert, time_since_epoch);
208
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
209
#endif
210
}
211

212
int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
213
#if defined(BOTAN_HAS_X509_CERTIFICATES)
214
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); });
6✔
215
#else
216
   BOTAN_UNUSED(cert, out, out_len);
217
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
218
#endif
219
}
220

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

225
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) {
6✔
226
      return write_str_output(reinterpret_cast<char*>(out), out_len, c.fingerprint(hash));
227
   });
228
#else
229
   BOTAN_UNUSED(cert, hash, out, out_len);
230
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
231
#endif
232
}
233

234
int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
1✔
235
#if defined(BOTAN_HAS_X509_CERTIFICATES)
236
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); });
2✔
237
#else
238
   BOTAN_UNUSED(cert, out, out_len);
239
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
240
#endif
241
}
242

243
int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
244
#if defined(BOTAN_HAS_X509_CERTIFICATES)
245
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
6✔
246
#else
247
   BOTAN_UNUSED(cert, out, out_len);
248
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
249
#endif
250
}
251

252
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
253
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
254
}
255

256
int botan_x509_cert_view_public_key_bits(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
257
#if defined(BOTAN_HAS_X509_CERTIFICATES)
258
   return BOTAN_FFI_VISIT(cert,
6✔
259
                          [=](const auto& c) { return invoke_view_callback(view, ctx, c.subject_public_key_bits()); });
260
#else
261
   BOTAN_UNUSED(cert, ctx, view);
262
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
263
#endif
264
}
265

266
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
6✔
267
   if(hostname == nullptr) {
6✔
268
      return BOTAN_FFI_ERROR_NULL_POINTER;
269
   }
270

271
#if defined(BOTAN_HAS_X509_CERTIFICATES)
272
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
12✔
273
#else
274
   BOTAN_UNUSED(cert);
275
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
276
#endif
277
}
278

279
int botan_x509_cert_verify(int* result_code,
4✔
280
                           botan_x509_cert_t cert,
281
                           const botan_x509_cert_t* intermediates,
282
                           size_t intermediates_len,
283
                           const botan_x509_cert_t* trusted,
284
                           size_t trusted_len,
285
                           const char* trusted_path,
286
                           size_t required_strength,
287
                           const char* hostname_cstr,
288
                           uint64_t reference_time) {
289
   if(required_strength == 0) {
4✔
290
      required_strength = 110;
3✔
291
   }
292

293
#if defined(BOTAN_HAS_X509_CERTIFICATES)
294
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
295
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
4✔
296
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
4✔
297
      const auto validation_time = reference_time == 0
4✔
298
                                      ? std::chrono::system_clock::now()
4✔
299
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
×
300

301
      std::vector<Botan::X509_Certificate> end_certs;
4✔
302
      end_certs.push_back(safe_get(cert));
4✔
303
      for(size_t i = 0; i != intermediates_len; ++i) {
9✔
304
         end_certs.push_back(safe_get(intermediates[i]));
5✔
305
      }
306

307
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
4✔
308
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
4✔
309
      std::vector<Botan::Certificate_Store*> trusted_roots;
4✔
310

311
      if(trusted_path != nullptr && *trusted_path != 0) {
4✔
312
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
313
         trusted_roots.push_back(trusted_from_path.get());
×
314
      }
315

316
      if(trusted_len > 0) {
4✔
317
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
8✔
318
         for(size_t i = 0; i != trusted_len; ++i) {
8✔
319
            trusted_extra->add_certificate(safe_get(trusted[i]));
4✔
320
         }
321
         trusted_roots.push_back(trusted_extra.get());
4✔
322
      }
323

324
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
8✔
325

326
      auto validation_result =
4✔
327
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
4✔
328

329
      if(result_code != nullptr) {
4✔
330
         *result_code = static_cast<int>(validation_result.result());
4✔
331
      }
332

333
      if(validation_result.successful_validation()) {
4✔
334
         return 0;
335
      } else {
336
         return 1;
3✔
337
      }
338
   });
4✔
339
#else
340
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
341
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
342
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
343
#endif
344
}
345

346
const char* botan_x509_cert_validation_status(int code) {
11✔
347
   if(code < 0) {
11✔
348
      return nullptr;
349
   }
350

351
#if defined(BOTAN_HAS_X509_CERTIFICATES)
352
   const Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
353
   return Botan::to_string(sc);
11✔
354
#else
355
   return nullptr;
356
#endif
357
}
358

359
#if defined(BOTAN_HAS_X509_CERTIFICATES)
360

361
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
7✔
362

363
#endif
364

365
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
6✔
366
   if(crl_obj == nullptr || crl_path == nullptr) {
6✔
367
      return BOTAN_FFI_ERROR_NULL_POINTER;
368
   }
369

370
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
371

372
   return ffi_guard_thunk(__func__, [=]() -> int {
6✔
373
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
6✔
374
      return ffi_new_object(crl_obj, std::move(c));
12✔
375
   });
12✔
376

377
#else
378
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
379
#endif
380
}
381

382
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
1✔
383
   if(crl_obj == nullptr || crl_bits == nullptr) {
1✔
384
      return BOTAN_FFI_ERROR_NULL_POINTER;
385
   }
386

387
#if defined(BOTAN_HAS_X509_CERTIFICATES)
388
   return ffi_guard_thunk(__func__, [=]() -> int {
1✔
389
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
1✔
390
      auto c = std::make_unique<Botan::X509_CRL>(bits);
1✔
391
      return ffi_new_object(crl_obj, std::move(c));
1✔
392
   });
3✔
393
#else
394
   BOTAN_UNUSED(crl_bits_len);
395
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
396
#endif
397
}
398

399
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
7✔
400
#if defined(BOTAN_HAS_X509_CERTIFICATES)
401
   return BOTAN_FFI_CHECKED_DELETE(crl);
7✔
402
#else
403
   BOTAN_UNUSED(crl);
404
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
405
#endif
406
}
407

408
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
409
#if defined(BOTAN_HAS_X509_CERTIFICATES)
410
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
411
#else
412
   BOTAN_UNUSED(cert);
413
   BOTAN_UNUSED(crl);
414
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
415
#endif
416
}
417

418
int botan_x509_cert_verify_with_crl(int* result_code,
12✔
419
                                    botan_x509_cert_t cert,
420
                                    const botan_x509_cert_t* intermediates,
421
                                    size_t intermediates_len,
422
                                    const botan_x509_cert_t* trusted,
423
                                    size_t trusted_len,
424
                                    const botan_x509_crl_t* crls,
425
                                    size_t crls_len,
426
                                    const char* trusted_path,
427
                                    size_t required_strength,
428
                                    const char* hostname_cstr,
429
                                    uint64_t reference_time) {
430
   if(required_strength == 0) {
12✔
431
      required_strength = 110;
2✔
432
   }
433

434
#if defined(BOTAN_HAS_X509_CERTIFICATES)
435
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
436
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
14✔
437
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
12✔
438
      const auto validation_time = reference_time == 0
12✔
439
                                      ? std::chrono::system_clock::now()
12✔
440
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
1✔
441

442
      std::vector<Botan::X509_Certificate> end_certs;
12✔
443
      end_certs.push_back(safe_get(cert));
12✔
444
      for(size_t i = 0; i != intermediates_len; ++i) {
30✔
445
         end_certs.push_back(safe_get(intermediates[i]));
18✔
446
      }
447

448
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
12✔
449
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
12✔
450
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
12✔
451
      std::vector<Botan::Certificate_Store*> trusted_roots;
12✔
452

453
      if(trusted_path != nullptr && *trusted_path != 0) {
12✔
454
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
455
         trusted_roots.push_back(trusted_from_path.get());
2✔
456
      }
457

458
      if(trusted_len > 0) {
12✔
459
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
18✔
460
         for(size_t i = 0; i != trusted_len; ++i) {
18✔
461
            trusted_extra->add_certificate(safe_get(trusted[i]));
9✔
462
         }
463
         trusted_roots.push_back(trusted_extra.get());
9✔
464
      }
465

466
      if(crls_len > 0) {
12✔
467
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
10✔
468
         for(size_t i = 0; i != crls_len; ++i) {
13✔
469
            trusted_crls->add_crl(safe_get(crls[i]));
8✔
470
         }
471
         trusted_roots.push_back(trusted_crls.get());
5✔
472
      }
473

474
      const Botan::Path_Validation_Restrictions restrictions(false, required_strength);
24✔
475

476
      auto validation_result =
12✔
477
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
12✔
478

479
      if(result_code != nullptr) {
12✔
480
         *result_code = static_cast<int>(validation_result.result());
12✔
481
      }
482

483
      if(validation_result.successful_validation()) {
12✔
484
         return 0;
485
      } else {
486
         return 1;
8✔
487
      }
488
   });
14✔
489
#else
490
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
491
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
492
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
493
#endif
494
}
495
}
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