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

randombit / botan / 20455383939

23 Dec 2025 08:17AM UTC coverage: 90.37% (-0.02%) from 90.386%
20455383939

Pull #5188

github

web-flow
Merge f81c4fba0 into 39c4f3b00
Pull Request #5188: FFI: Generic getter(s) for X.509 objects

101359 of 112160 relevant lines covered (90.37%)

12753922.21 hits per line

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

80.69
/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/loadstor.h>
19
   #include <botan/internal/stl_util.h>
20
#endif
21

22
extern "C" {
23

24
using namespace Botan_FFI;
25

26
#if defined(BOTAN_HAS_X509_CERTIFICATES)
27

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

30
#endif
31

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

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

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

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

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

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

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

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

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

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

84
int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) {
2✔
85
   if(key == nullptr) {
2✔
86
      return BOTAN_FFI_ERROR_NULL_POINTER;
87
   }
88

89
   *key = nullptr;
2✔
90

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

360
#if defined(BOTAN_HAS_X509_CERTIFICATES)
361

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

364
#endif
365

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

497
int botan_x509_view_binary_value(botan_x509_object_t object,
5✔
498
                                 botan_x509_value_type value_type,
499
                                 botan_view_ctx ctx,
500
                                 botan_view_bin_fn view_fn) {
501
#if defined(BOTAN_HAS_X509_CERTIFICATES)
502
   auto view = [=](std::span<const uint8_t> value) { return invoke_view_callback(view_fn, ctx, value); };
3✔
503

504
   auto handle_x509_object_fields = [=](const Botan::X509_Object& x509) -> int {
5✔
505
      switch(value_type) {
×
506
         case BOTAN_X509_TBS_DATA_BITS:
×
507
            return view(x509.tbs_data());
×
508
         case BOTAN_X509_SIGNATURE_SCHEME_BITS:
×
509
            return view(x509.signature_algorithm().BER_encode());
×
510
         case BOTAN_X509_SIGNATURE_BITS:
×
511
            return view(x509.signature());
×
512
         case BOTAN_X509_DER_ENCODING:
×
513
            return view(x509.BER_encode());
×
514
         default:
515
            return BOTAN_FFI_ERROR_INTERNAL_ERROR; /* lambda called with unexpected value_type */
516
      }
517
   };
5✔
518

519
   auto handler = Botan::overloaded{
5✔
520
      [=](const Botan::X509_Certificate& cert) -> int {
3✔
521
         switch(value_type) {
3✔
522
            case BOTAN_X509_SERIAL_NUMBER:
1✔
523
               return view(cert.serial_number());
1✔
524
            case BOTAN_X509_SUBJECT_DN_BITS:
×
525
               return view(cert.subject_dn().get_bits());
×
526
            case BOTAN_X509_ISSUER_DN_BITS:
×
527
               return view(cert.issuer_dn().get_bits());
×
528
            case BOTAN_X509_SUBJECT_KEY_IDENTIFIER:
1✔
529
               return cert.subject_key_id().empty() ? BOTAN_FFI_ERROR_NO_VALUE : view(cert.subject_key_id());
1✔
530
            case BOTAN_X509_AUTHORITY_KEY_IDENTIFIER:
1✔
531
               return cert.authority_key_id().empty() ? BOTAN_FFI_ERROR_NO_VALUE : view(cert.authority_key_id());
1✔
532
            case BOTAN_X509_PUBLIC_KEY_BITS:
×
533
               return view(cert.subject_public_key_info());
×
534

535
            case BOTAN_X509_TBS_DATA_BITS:
×
536
            case BOTAN_X509_SIGNATURE_SCHEME_BITS:
×
537
            case BOTAN_X509_SIGNATURE_BITS:
×
538
            case BOTAN_X509_DER_ENCODING:
×
539
               return handle_x509_object_fields(cert);
×
540
         }
541

542
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
543
      },
544
      [=](const Botan::X509_CRL& crl) -> int {
2✔
545
         switch(value_type) {
2✔
546
            case BOTAN_X509_SERIAL_NUMBER:
×
547
               return view(Botan::store_be(crl.crl_number()));
×
548
            case BOTAN_X509_ISSUER_DN_BITS:
×
549
               return view(crl.issuer_dn().get_bits());
×
550
            case BOTAN_X509_AUTHORITY_KEY_IDENTIFIER:
1✔
551
               return crl.authority_key_id().empty() ? BOTAN_FFI_ERROR_NO_VALUE : view(crl.authority_key_id());
1✔
552

553
            case BOTAN_X509_TBS_DATA_BITS:
×
554
            case BOTAN_X509_SIGNATURE_SCHEME_BITS:
×
555
            case BOTAN_X509_SIGNATURE_BITS:
×
556
            case BOTAN_X509_DER_ENCODING:
×
557
               return handle_x509_object_fields(crl);
×
558

559
            case BOTAN_X509_SUBJECT_DN_BITS:
560
            case BOTAN_X509_SUBJECT_KEY_IDENTIFIER:
561
            case BOTAN_X509_PUBLIC_KEY_BITS:
562
               return BOTAN_FFI_ERROR_NO_VALUE;
563
         }
564

565
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
566
      },
567
   };
5✔
568

569
   return BOTAN_FFI_VISIT_VARIANT(object, handler, botan_x509_cert_t, botan_x509_crl_t);
5✔
570
#else
571
   BOTAN_UNUSED(object, value_type, ctx, view);
572
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
573
#endif
574
}
575
}
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