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

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 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

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

37
   return ffi_guard_thunk(__func__, [=]() -> int {
46✔
38
      auto c = std::make_unique<Botan::X509_Certificate>(cert_path);
23✔
39
      *cert_obj = new botan_x509_cert_struct(std::move(c));
23✔
40
      return BOTAN_FFI_SUCCESS;
23✔
41
   });
23✔
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) {
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 {
2✔
56
      auto c = std::make_unique<Botan::X509_Certificate>(safe_get(cert));
1✔
57
      *cert_obj = new botan_x509_cert_struct(std::move(c));
1✔
58
      return BOTAN_FFI_SUCCESS;
1✔
59
   });
1✔
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 || !cert_bits) {
×
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
      *cert_obj = new botan_x509_cert_struct(std::move(c));
×
77
      return BOTAN_FFI_SUCCESS;
×
78
   });
×
79
#else
80
   BOTAN_UNUSED(cert_bits_len);
81
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
82
#endif
83
}
84

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

90
   *key = nullptr;
2✔
91

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

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

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

126
int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) {
2✔
127
   return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert);
2✔
128
}
129

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

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

153
int botan_x509_cert_destroy(botan_x509_cert_t cert) {
24✔
154
#if defined(BOTAN_HAS_X509_CERTIFICATES)
155
   return BOTAN_FFI_CHECKED_DELETE(cert);
24✔
156
#else
157
   BOTAN_UNUSED(cert);
158
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
159
#endif
160
}
161

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

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

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

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

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

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

218
int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
3✔
219
#if defined(BOTAN_HAS_X509_CERTIFICATES)
220
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); });
6✔
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_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
228
#if defined(BOTAN_HAS_X509_CERTIFICATES)
229
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); });
4✔
230
#else
231
   BOTAN_UNUSED(cert, out, out_len);
232
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
233
#endif
234
}
235

236
int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) {
2✔
237
   return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert);
2✔
238
}
239

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

250
int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) {
8✔
251
   if(hostname == nullptr) {
8✔
252
      return BOTAN_FFI_ERROR_NULL_POINTER;
253
   }
254

255
#if defined(BOTAN_HAS_X509_CERTIFICATES)
256
   return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; });
16✔
257
#else
258
   BOTAN_UNUSED(cert);
259
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
260
#endif
261
}
262

263
int botan_x509_cert_verify(int* result_code,
4✔
264
                           botan_x509_cert_t cert,
265
                           const botan_x509_cert_t* intermediates,
266
                           size_t intermediates_len,
267
                           const botan_x509_cert_t* trusted,
268
                           size_t trusted_len,
269
                           const char* trusted_path,
270
                           size_t required_strength,
271
                           const char* hostname_cstr,
272
                           uint64_t reference_time) {
273
   if(required_strength == 0) {
4✔
274
      required_strength = 110;
3✔
275
   }
276

277
#if defined(BOTAN_HAS_X509_CERTIFICATES)
278
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
279
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
4✔
280
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
4✔
281
      const auto validation_time = reference_time == 0
4✔
282
                                      ? std::chrono::system_clock::now()
4✔
283
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
4✔
284

285
      std::vector<Botan::X509_Certificate> end_certs;
4✔
286
      end_certs.push_back(safe_get(cert));
4✔
287
      for(size_t i = 0; i != intermediates_len; ++i) {
9✔
288
         end_certs.push_back(safe_get(intermediates[i]));
5✔
289
      }
290

291
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
4✔
292
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
4✔
293
      std::vector<Botan::Certificate_Store*> trusted_roots;
4✔
294

295
      if(trusted_path && *trusted_path) {
4✔
296
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
×
297
         trusted_roots.push_back(trusted_from_path.get());
×
298
      }
299

300
      if(trusted_len > 0) {
4✔
301
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
8✔
302
         for(size_t i = 0; i != trusted_len; ++i) {
8✔
303
            trusted_extra->add_certificate(safe_get(trusted[i]));
4✔
304
         }
305
         trusted_roots.push_back(trusted_extra.get());
4✔
306
      }
307

308
      Botan::Path_Validation_Restrictions restrictions(false, required_strength);
8✔
309

310
      auto validation_result =
4✔
311
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
4✔
312

313
      if(result_code) {
4✔
314
         *result_code = static_cast<int>(validation_result.result());
4✔
315
      }
316

317
      if(validation_result.successful_validation()) {
4✔
318
         return 0;
319
      } else {
320
         return 1;
3✔
321
      }
322
   });
12✔
323
#else
324
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
325
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
326
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
327
#endif
328
}
329

330
const char* botan_x509_cert_validation_status(int code) {
11✔
331
   if(code < 0) {
11✔
332
      return nullptr;
333
   }
334

335
#if defined(BOTAN_HAS_X509_CERTIFICATES)
336
   Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
11✔
337
   return Botan::to_string(sc);
11✔
338
#else
339
   return nullptr;
340
#endif
341
}
342

343
#if defined(BOTAN_HAS_X509_CERTIFICATES)
344

345
BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
14✔
346

347
#endif
348

349
int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) {
6✔
350
   if(!crl_obj || !crl_path) {
6✔
351
      return BOTAN_FFI_ERROR_NULL_POINTER;
352
   }
353

354
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
355

356
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
357
      auto c = std::make_unique<Botan::X509_CRL>(crl_path);
6✔
358
      *crl_obj = new botan_x509_crl_struct(std::move(c));
6✔
359
      return BOTAN_FFI_SUCCESS;
6✔
360
   });
6✔
361

362
#else
363
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
364
#endif
365
}
366

367
int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) {
1✔
368
   if(!crl_obj || !crl_bits) {
1✔
369
      return BOTAN_FFI_ERROR_NULL_POINTER;
370
   }
371

372
#if defined(BOTAN_HAS_X509_CERTIFICATES)
373
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
374
      Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
1✔
375
      auto c = std::make_unique<Botan::X509_CRL>(bits);
1✔
376
      *crl_obj = new botan_x509_crl_struct(std::move(c));
1✔
377
      return BOTAN_FFI_SUCCESS;
2✔
378
   });
2✔
379
#else
380
   BOTAN_UNUSED(crl_bits_len);
381
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
382
#endif
383
}
384

385
int botan_x509_crl_destroy(botan_x509_crl_t crl) {
7✔
386
#if defined(BOTAN_HAS_X509_CERTIFICATES)
387
   return BOTAN_FFI_CHECKED_DELETE(crl);
7✔
388
#else
389
   BOTAN_UNUSED(crl);
390
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
391
#endif
392
}
393

394
int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) {
6✔
395
#if defined(BOTAN_HAS_X509_CERTIFICATES)
396
   return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; });
12✔
397
#else
398
   BOTAN_UNUSED(cert);
399
   BOTAN_UNUSED(crl);
400
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
401
#endif
402
}
403

404
int botan_x509_cert_verify_with_crl(int* result_code,
12✔
405
                                    botan_x509_cert_t cert,
406
                                    const botan_x509_cert_t* intermediates,
407
                                    size_t intermediates_len,
408
                                    const botan_x509_cert_t* trusted,
409
                                    size_t trusted_len,
410
                                    const botan_x509_crl_t* crls,
411
                                    size_t crls_len,
412
                                    const char* trusted_path,
413
                                    size_t required_strength,
414
                                    const char* hostname_cstr,
415
                                    uint64_t reference_time) {
416
   if(required_strength == 0) {
12✔
417
      required_strength = 110;
2✔
418
   }
419

420
#if defined(BOTAN_HAS_X509_CERTIFICATES)
421
   return ffi_guard_thunk(__func__, [=]() -> int {
12✔
422
      const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
14✔
423
      const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
12✔
424
      const auto validation_time = reference_time == 0
12✔
425
                                      ? std::chrono::system_clock::now()
11✔
426
                                      : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
12✔
427

428
      std::vector<Botan::X509_Certificate> end_certs;
12✔
429
      end_certs.push_back(safe_get(cert));
12✔
430
      for(size_t i = 0; i != intermediates_len; ++i) {
30✔
431
         end_certs.push_back(safe_get(intermediates[i]));
18✔
432
      }
433

434
      std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
12✔
435
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
12✔
436
      std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
12✔
437
      std::vector<Botan::Certificate_Store*> trusted_roots;
12✔
438

439
      if(trusted_path && *trusted_path) {
12✔
440
         trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path);
2✔
441
         trusted_roots.push_back(trusted_from_path.get());
2✔
442
      }
443

444
      if(trusted_len > 0) {
12✔
445
         trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>();
18✔
446
         for(size_t i = 0; i != trusted_len; ++i) {
18✔
447
            trusted_extra->add_certificate(safe_get(trusted[i]));
9✔
448
         }
449
         trusted_roots.push_back(trusted_extra.get());
9✔
450
      }
451

452
      if(crls_len > 0) {
12✔
453
         trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>();
10✔
454
         for(size_t i = 0; i != crls_len; ++i) {
13✔
455
            trusted_crls->add_crl(safe_get(crls[i]));
8✔
456
         }
457
         trusted_roots.push_back(trusted_crls.get());
5✔
458
      }
459

460
      Botan::Path_Validation_Restrictions restrictions(false, required_strength);
24✔
461

462
      auto validation_result =
12✔
463
         Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time);
12✔
464

465
      if(result_code) {
12✔
466
         *result_code = static_cast<int>(validation_result.result());
12✔
467
      }
468

469
      if(validation_result.successful_validation()) {
12✔
470
         return 0;
471
      } else {
472
         return 1;
8✔
473
      }
474
   });
37✔
475
#else
476
   BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
477
   BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
478
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
479
#endif
480
}
481
}
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