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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 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);
24✔
27

28
#endif
29

30
int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path) {
23✔
31
   if(!cert_obj || !cert_path)
23✔
32
      return BOTAN_FFI_ERROR_NULL_POINTER;
33

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

36
   return ffi_guard_thunk(__func__, [=]() -> int {
46✔
37
      auto c = std::make_unique<Botan::X509_Certificate>(cert_path);
23✔
38
      *cert_obj = new botan_x509_cert_struct(std::move(c));
23✔
39
      return BOTAN_FFI_SUCCESS;
23✔
40
   });
23✔
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)
1✔
49
      return BOTAN_FFI_ERROR_NULL_POINTER;
50

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

53
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
54
      auto c = std::make_unique<Botan::X509_Certificate>(safe_get(cert));
1✔
55
      *cert_obj = new botan_x509_cert_struct(std::move(c));
1✔
56
      return BOTAN_FFI_SUCCESS;
1✔
57
   });
1✔
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 || !cert_bits)
×
67
      return BOTAN_FFI_ERROR_NULL_POINTER;
68

69
#if defined(BOTAN_HAS_X509_CERTIFICATES)
70
   return ffi_guard_thunk(__func__, [=]() -> int {
×
71
      Botan::DataSource_Memory bits(cert_bits, cert_bits_len);
×
72
      auto c = std::make_unique<Botan::X509_Certificate>(bits);
×
73
      *cert_obj = new botan_x509_cert_struct(std::move(c));
×
74
      return BOTAN_FFI_SUCCESS;
×
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_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) {
2✔
83
   if(key == nullptr)
2✔
84
      return BOTAN_FFI_ERROR_NULL_POINTER;
85

86
   *key = nullptr;
2✔
87

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

100
int botan_x509_cert_get_issuer_dn(
10✔
101
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
102
#if defined(BOTAN_HAS_X509_CERTIFICATES)
103
   return BOTAN_FFI_VISIT(cert,
20✔
104
                          [=](const auto& c) { return write_str_output(out, out_len, c.issuer_info(key).at(index)); });
105
#else
106
   BOTAN_UNUSED(cert, key, index, out, out_len);
107
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
108
#endif
109
}
110

111
int botan_x509_cert_get_subject_dn(
12✔
112
   botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) {
113
#if defined(BOTAN_HAS_X509_CERTIFICATES)
114
   return BOTAN_FFI_VISIT(cert,
24✔
115
                          [=](const auto& c) { return write_str_output(out, out_len, c.subject_info(key).at(index)); });
116
#else
117
   BOTAN_UNUSED(cert, key, index, out, out_len);
118
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
119
#endif
120
}
121

122
int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
123
   return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert);
2✔
124
}
125

126
int botan_x509_cert_view_as_string(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) {
3✔
127
#if defined(BOTAN_HAS_X509_CERTIFICATES)
128
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return invoke_view_callback(view, ctx, c.to_string()); });
9✔
129
#else
130
   BOTAN_UNUSED(cert, ctx, view);
131
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
132
#endif
133
}
134

135
int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage) {
7✔
136
#if defined(BOTAN_HAS_X509_CERTIFICATES)
137
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int {
14✔
138
      const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
139
      if(c.allowed_usage(k))
140
         return BOTAN_FFI_SUCCESS;
141
      return 1;
142
   });
143
#else
144
   BOTAN_UNUSED(cert, key_usage);
145
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
146
#endif
147
}
148

149
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
24✔
150
#if defined(BOTAN_HAS_X509_CERTIFICATES)
151
   return BOTAN_FFI_CHECKED_DELETE(cert);
24✔
152
#else
153
   BOTAN_UNUSED(cert);
154
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
155
#endif
156
}
157

158
int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len) {
3✔
159
#if defined(BOTAN_HAS_X509_CERTIFICATES)
160
   return BOTAN_FFI_VISIT(cert,
6✔
161
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_before().to_string()); });
162
#else
163
   BOTAN_UNUSED(cert, out, out_len);
164
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
165
#endif
166
}
167

168
int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
169
#if defined(BOTAN_HAS_X509_CERTIFICATES)
170
   return BOTAN_FFI_VISIT(cert,
4✔
171
                          [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); });
172
#else
173
   BOTAN_UNUSED(cert, out, out_len);
174
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
175
#endif
176
}
177

178
int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
179
#if defined(BOTAN_HAS_X509_CERTIFICATES)
180
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_before().time_since_epoch(); });
4✔
181
#else
182
   BOTAN_UNUSED(cert, time_since_epoch);
183
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
184
#endif
185
}
186

187
int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) {
2✔
188
#if defined(BOTAN_HAS_X509_CERTIFICATES)
189
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); });
4✔
190
#else
191
   BOTAN_UNUSED(cert, time_since_epoch);
192
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
193
#endif
194
}
195

196
int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
197
#if defined(BOTAN_HAS_X509_CERTIFICATES)
198
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); });
6✔
199
#else
200
   BOTAN_UNUSED(cert, out, out_len);
201
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
202
#endif
203
}
204

205
int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len) {
3✔
206
#if defined(BOTAN_HAS_X509_CERTIFICATES)
207
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_str_output(out, out_len, c.fingerprint(hash)); });
9✔
208
#else
209
   BOTAN_UNUSED(cert, hash, out, out_len);
210
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
211
#endif
212
}
213

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

223
int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
224
#if defined(BOTAN_HAS_X509_CERTIFICATES)
225
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
4✔
226
#else
227
   BOTAN_UNUSED(cert, out, out_len);
228
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
229
#endif
230
}
231

232
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
233
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
234
}
235

236
int botan_x509_cert_view_public_key_bits(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
237
#if defined(BOTAN_HAS_X509_CERTIFICATES)
238
   return BOTAN_FFI_VISIT(cert,
6✔
239
                          [=](const auto& c) { return invoke_view_callback(view, ctx, c.subject_public_key_bits()); });
240
#else
241
   BOTAN_UNUSED(cert, ctx, view);
242
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
243
#endif
244
}
245

246
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
8✔
247
   if(hostname == nullptr)
8✔
248
      return BOTAN_FFI_ERROR_NULL_POINTER;
249

250
#if defined(BOTAN_HAS_X509_CERTIFICATES)
251
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
16✔
252
#else
253
   BOTAN_UNUSED(cert);
254
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
255
#endif
256
}
257

258
int botan_x509_cert_verify(int* result_code,
4✔
259
                           botan_x509_cert_t cert,
260
                           const botan_x509_cert_t* intermediates,
261
                           size_t intermediates_len,
262
                           const botan_x509_cert_t* trusted,
263
                           size_t trusted_len,
264
                           const char* trusted_path,
265
                           size_t required_strength,
266
                           const char* hostname_cstr,
267
                           uint64_t reference_time) {
268
   if(required_strength == 0)
4✔
269
      required_strength = 110;
3✔
270

271
#if defined(BOTAN_HAS_X509_CERTIFICATES)
272
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
273
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
4✔
274
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
4✔
275
      const auto validation_time = reference_time == 0
4✔
276
                                      ? std::chrono::system_clock::now()
4✔
277
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
4✔
278

279
      std::vector<Botan::X509_Certificate> end_certs;
4✔
280
      end_certs.push_back(safe_get(cert));
4✔
281
      for(size_t i = 0; i != intermediates_len; ++i)
9✔
282
         end_certs.push_back(safe_get(intermediates[i]));
5✔
283

284
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
4✔
285
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
4✔
286
      std::vector<Botan::Certificate_Store*> trusted_roots;
4✔
287

288
      if(trusted_path && *trusted_path) {
4✔
289
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
290
         trusted_roots.push_back(trusted_from_path.get());
×
291
      }
292

293
      if(trusted_len > 0) {
4✔
294
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
8✔
295
         for(size_t i = 0; i != trusted_len; ++i) {
8✔
296
            trusted_extra->add_certificate(safe_get(trusted[i]));
4✔
297
         }
298
         trusted_roots.push_back(trusted_extra.get());
4✔
299
      }
300

301
      Botan::Path_Validation_Restrictions restrictions(false, required_strength);
8✔
302

303
      auto validation_result =
4✔
304
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
4✔
305

306
      if(result_code)
4✔
307
         *result_code = static_cast<int>(validation_result.result());
4✔
308

309
      if(validation_result.successful_validation())
4✔
310
         return 0;
311
      else
312
         return 1;
3✔
313
   });
12✔
314
#else
315
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
316
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
317
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
318
#endif
319
}
320

321
const char* botan_x509_cert_validation_status(int code) {
11✔
322
   if(code < 0)
11✔
323
      return nullptr;
324

325
#if defined(BOTAN_HAS_X509_CERTIFICATES)
326
   Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
327
   return Botan::to_string(sc);
11✔
328
#else
329
   return nullptr;
330
#endif
331
}
332

333
#if defined(BOTAN_HAS_X509_CERTIFICATES)
334

335
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
14✔
336

337
#endif
338

339
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
6✔
340
   if(!crl_obj || !crl_path)
6✔
341
      return BOTAN_FFI_ERROR_NULL_POINTER;
342

343
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
344

345
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
346
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
6✔
347
      *crl_obj = new botan_x509_crl_struct(std::move(c));
6✔
348
      return BOTAN_FFI_SUCCESS;
6✔
349
   });
6✔
350

351
#else
352
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
353
#endif
354
}
355

356
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
1✔
357
   if(!crl_obj || !crl_bits)
1✔
358
      return BOTAN_FFI_ERROR_NULL_POINTER;
359

360
#if defined(BOTAN_HAS_X509_CERTIFICATES)
361
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
362
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
1✔
363
      auto c = std::make_unique<Botan::X509_CRL>(bits);
1✔
364
      *crl_obj = new botan_x509_crl_struct(std::move(c));
1✔
365
      return BOTAN_FFI_SUCCESS;
2✔
366
   });
2✔
367
#else
368
   BOTAN_UNUSED(crl_bits_len);
369
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
370
#endif
371
}
372

373
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
7✔
374
#if defined(BOTAN_HAS_X509_CERTIFICATES)
375
   return BOTAN_FFI_CHECKED_DELETE(crl);
7✔
376
#else
377
   BOTAN_UNUSED(crl);
378
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
379
#endif
380
}
381

382
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
383
#if defined(BOTAN_HAS_X509_CERTIFICATES)
384
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
385
#else
386
   BOTAN_UNUSED(cert);
387
   BOTAN_UNUSED(crl);
388
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
389
#endif
390
}
391

392
int botan_x509_cert_verify_with_crl(int* result_code,
12✔
393
                                    botan_x509_cert_t cert,
394
                                    const botan_x509_cert_t* intermediates,
395
                                    size_t intermediates_len,
396
                                    const botan_x509_cert_t* trusted,
397
                                    size_t trusted_len,
398
                                    const botan_x509_crl_t* crls,
399
                                    size_t crls_len,
400
                                    const char* trusted_path,
401
                                    size_t required_strength,
402
                                    const char* hostname_cstr,
403
                                    uint64_t reference_time) {
404
   if(required_strength == 0)
12✔
405
      required_strength = 110;
2✔
406

407
#if defined(BOTAN_HAS_X509_CERTIFICATES)
408
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
409
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
14✔
410
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
12✔
411
      const auto validation_time = reference_time == 0
12✔
412
                                      ? std::chrono::system_clock::now()
11✔
413
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
12✔
414

415
      std::vector<Botan::X509_Certificate> end_certs;
12✔
416
      end_certs.push_back(safe_get(cert));
12✔
417
      for(size_t i = 0; i != intermediates_len; ++i)
30✔
418
         end_certs.push_back(safe_get(intermediates[i]));
18✔
419

420
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
12✔
421
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
12✔
422
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
12✔
423
      std::vector<Botan::Certificate_Store*> trusted_roots;
12✔
424

425
      if(trusted_path && *trusted_path) {
12✔
426
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
427
         trusted_roots.push_back(trusted_from_path.get());
2✔
428
      }
429

430
      if(trusted_len > 0) {
12✔
431
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
18✔
432
         for(size_t i = 0; i != trusted_len; ++i) {
18✔
433
            trusted_extra->add_certificate(safe_get(trusted[i]));
9✔
434
         }
435
         trusted_roots.push_back(trusted_extra.get());
9✔
436
      }
437

438
      if(crls_len > 0) {
12✔
439
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
10✔
440
         for(size_t i = 0; i != crls_len; ++i) {
13✔
441
            trusted_crls->add_crl(safe_get(crls[i]));
8✔
442
         }
443
         trusted_roots.push_back(trusted_crls.get());
5✔
444
      }
445

446
      Botan::Path_Validation_Restrictions restrictions(false, required_strength);
24✔
447

448
      auto validation_result =
12✔
449
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
12✔
450

451
      if(result_code)
12✔
452
         *result_code = static_cast<int>(validation_result.result());
12✔
453

454
      if(validation_result.successful_validation())
12✔
455
         return 0;
456
      else
457
         return 1;
8✔
458
   });
37✔
459
#else
460
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
461
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
462
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
463
#endif
464
}
465
}
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