9#include <botan/x509path.h>
11#include <botan/assert.h>
12#include <botan/ocsp.h>
13#include <botan/pk_keys.h>
14#include <botan/x509_ext.h>
15#include <botan/internal/concat_util.h>
16#include <botan/internal/x509_utils.h>
24#include <unordered_set>
27#if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
28 #include <botan/uri.h>
29 #include <botan/internal/http_util.h>
37constexpr size_t PathBuildingDfsBudget = 300;
38constexpr size_t PathBuildingMaximumChainLength = 16;
39constexpr size_t PathBuildingVerificationBudget = 200;
40constexpr size_t PathBuildingMaxPathsExamined = 50;
42struct CrlApplicability {
99 return {
false,
false};
104 return {
true, match.any_with_absent_reasons};
108 const bool basicConstraints_isCa = [&]() {
110 return ext->get_is_ca();
117 if(idp->only_contains_user_certs() && basicConstraints_isCa) {
118 return {
false,
false};
122 if(idp->only_contains_ca_certs() && !basicConstraints_isCa) {
123 return {
false,
false};
127 if(idp->only_contains_attribute_certs()) {
128 return {
false,
false};
139 if(idp->indirect_crl()) {
140 return {
false,
false};
151 const bool full = match.any_with_absent_reasons && !only_some_reasons;
172class CertificatePathBuilder final {
174 CertificatePathBuilder(
const std::vector<Certificate_Store*>& trusted_certstores,
175 const X509_Certificate& end_entity,
176 std::span<const X509_Certificate> end_entity_extra,
178 bool require_self_signed) :
179 m_trusted_certstores(trusted_certstores),
180 m_require_self_signed(require_self_signed),
181 m_dfs_budget(dfs_budget) {
184 if(std::ranges::any_of(trusted_certstores, [](
auto* ptr) {
return ptr ==
nullptr; })) {
185 throw Invalid_Argument(
"Certificate store list must not contain nullptr");
188 for(
const auto& cert : end_entity_extra) {
189 if(!cert_in_any_trusted_store(cert)) {
190 m_ee_extras.add_certificate(cert);
194 m_stack.push_back({end_entity, cert_in_any_trusted_store(end_entity)});
197 std::optional<std::vector<X509_Certificate>> next() {
198 while(!m_stack.empty()) {
199 if(m_dfs_budget == 0) {
208 auto [last, trusted] = std::move(m_stack.back());
212 if(!last.has_value()) {
213 m_certs_seen.erase(m_path_so_far.back().tag());
214 m_path_so_far.pop_back();
219 const auto tag = last->tag();
220 if(m_certs_seen.contains(tag)) {
221 if(!m_error.has_value()) {
232 auto path = m_path_so_far;
233 path.push_back(*last);
236 if(!m_require_self_signed || last->is_self_signed()) {
249 if(last->is_self_signed()) {
250 if(!m_error.has_value()) {
268 if(m_error.has_value()) {
271 return m_error.value();
278 bool cert_in_any_trusted_store(
const X509_Certificate& cert)
const {
279 return std::ranges::any_of(m_trusted_certstores,
280 [&](
const Certificate_Store* store) {
return store->contains(cert); });
283 void push_issuers(
const X509_Certificate& cert) {
284 const X509_DN& issuer_dn = cert.issuer_dn();
285 const std::vector<uint8_t>& auth_key_id = cert.authority_key_id();
289 std::vector<X509_Certificate> trusted_issuers;
290 for(
const Certificate_Store* store : m_trusted_certstores) {
291 auto new_issuers = store->find_all_certs(issuer_dn, auth_key_id);
292 if(trusted_issuers.empty()) {
293 trusted_issuers = std::move(new_issuers);
295 trusted_issuers.insert(trusted_issuers.end(),
296 std::make_move_iterator(new_issuers.begin()),
297 std::make_move_iterator(new_issuers.end()));
302 const std::vector<X509_Certificate> misc_issuers = m_ee_extras.find_all_certs(issuer_dn, auth_key_id);
305 if(trusted_issuers.empty() && misc_issuers.empty()) {
306 if(!m_error.has_value()) {
312 m_path_so_far.push_back(cert);
313 m_certs_seen.emplace(cert.tag());
316 m_stack.push_back({std::nullopt,
false});
321 for(
const auto& misc : misc_issuers) {
322 m_stack.push_back({misc,
false});
324 for(
const auto& trusted_cert : trusted_issuers) {
325 m_stack.push_back({trusted_cert,
true});
329 const std::vector<Certificate_Store*> m_trusted_certstores;
330 const bool m_require_self_signed;
331 Certificate_Store_In_Memory m_ee_extras;
332 std::vector<std::pair<std::optional<X509_Certificate>,
bool>> m_stack;
333 std::vector<X509_Certificate> m_path_so_far;
334 std::unordered_set<X509_Certificate::Tag, X509_Certificate::TagHash> m_certs_seen;
335 std::optional<Certificate_Status_Code> m_error;
336 size_t m_dfs_budget = 0;
345 std::chrono::system_clock::time_point ref_time,
346 std::string_view hostname,
349 if(cert_path.empty()) {
353 const bool is_end_entity_trust_anchor = (cert_path.size() == 1);
355 const X509_Time validation_time(ref_time);
360 for(
size_t i = 0; i != cert_path.size(); ++i) {
361 std::set<Certificate_Status_Code>& status = cert_status.at(i);
363 const bool at_trust_anchor = (i == cert_path.size() - 1);
374 const X509_Certificate& issuer = cert_path[at_trust_anchor ? (i) : (i + 1)];
380 std::unique_ptr<Public_Key> issuer_key;
395 status.insert(sig_status.first);
398 const std::string hash_used_for_signature = sig_status.second;
403 if(!trusted_hashes.empty() && !at_trust_anchor) {
404 if(!trusted_hashes.contains(hash_used_for_signature)) {
419 for(
size_t i = 0; i != cert_path.size(); ++i) {
420 for(
auto status : cert_status.at(i)) {
423 if(
static_cast<uint32_t
>(status) >= 5000) {
429 if(!hostname.empty() && !cert_path[0].matches_dns_name(hostname)) {
433 if(!cert_path[0].allowed_usage(usage)) {
452 for(
size_t i = 0; i != cert_path.size(); ++i) {
453 std::set<Certificate_Status_Code>& status = cert_status.at(i);
455 const bool at_trust_anchor = (i == cert_path.size() - 1);
458 const auto issuer = [&]() -> std::optional<X509_Certificate> {
459 if(!at_trust_anchor) {
460 return cert_path[i + 1];
473 if(issuer.has_value() && subject.
issuer_dn() != issuer->subject_dn()) {
485 for(
const auto& ava : rdn) {
487 if(dn_ub > 0 && ava.second.size() > dn_ub) {
498 if(enforce_validity_period) {
505 if(validation_time > subject.
not_after()) {
506 if(enforce_validity_period) {
514 if(issuer.has_value() && !issuer->is_CA_cert() && !is_end_entity_trust_anchor) {
531 extensions.
validate(subject, issuer, cert_path, cert_status, i);
535 size_t max_path_length = cert_path.size();
536 for(
size_t i = cert_path.size() - 1; i > 0; --i) {
537 std::set<Certificate_Status_Code>& status = cert_status.at(i);
545 if(max_path_length > 0) {
546 max_path_length -= 1;
557 max_path_length = std::min(max_path_length, *path_len_constraint);
568 const std::vector<X509_Certificate>& extra_certs,
569 const std::vector<Certificate_Store*>& certstores,
570 std::chrono::system_clock::time_point ref_time,
580 if(trusted_responders->contains(signing_cert)) {
589 if(signing_cert == ca) {
618 if(!aki.empty() && !ski.empty() && aki != ski) {
651 const auto ocsp_timeout = std::chrono::milliseconds::zero();
652 const auto relaxed_restrictions =
657 std::chrono::seconds(0),
664 relaxed_restrictions,
671 return validation_result.
result();
674std::set<Certificate_Status_Code> evaluate_ocsp_response(
const OCSP::Response& ocsp_response,
677 const std::vector<X509_Certificate>& cert_path,
678 const std::vector<Certificate_Store*>& certstores,
679 std::chrono::system_clock::time_point ref_time,
682 if(
auto dummy_status = ocsp_response.dummy_status()) {
683 return {dummy_status.value()};
687 auto signing_cert = ocsp_response.find_signing_certificate(ca, restrictions.trusted_ocsp_responders());
693 auto cert_status = verify_ocsp_signing_cert(
694 signing_cert.value(), ca,
concat(ocsp_response.certificates(), cert_path), certstores, ref_time, restrictions);
700 auto sig_status = ocsp_response.verify_signature(signing_cert.value(), restrictions);
706 return {ocsp_response.status_for(ca, subject, ref_time, restrictions.max_ocsp_age())};
712 const std::vector<std::optional<OCSP::Response>>& ocsp_responses,
713 const std::vector<Certificate_Store*>& certstores,
714 std::chrono::system_clock::time_point ref_time,
716 if(cert_path.empty()) {
722 for(
size_t i = 0; i != cert_path.size() - 1; ++i) {
730 if(i < ocsp_responses.size() && ocsp_responses.at(i).has_value() &&
733 cert_status.at(i) = evaluate_ocsp_response(
734 ocsp_responses.at(i).value(), subject, ca, cert_path, certstores, ref_time, restrictions);
745 const std::vector<std::optional<X509_CRL>>& crls,
746 std::chrono::system_clock::time_point ref_time) {
747 if(cert_path.empty()) {
752 const X509_Time validation_time(ref_time);
754 for(
size_t i = 0; i != cert_path.size() - 1; ++i) {
755 std::set<Certificate_Status_Code>& status = cert_status.at(i);
757 if(cert_path.at(i).skip_revocation_check()) {
761 if(i < crls.size() && crls[i].has_value()) {
770 const auto applic = crl_applicability_for(*crls[i], subject);
779 if(validation_time < crls[i]->this_update()) {
783 if(crls[i]->next_update().time_is_set() && validation_time > crls[i]->next_update()) {
788 if(crls[i]->check_signature(*ca_key) ==
false) {
800 const bool crl_is_not_usable = crls[i]->has_unknown_critical_extension();
802 if(crl_is_not_usable) {
804 }
else if(crls[i]->is_revoked(subject)) {
810 }
else if(applic.full_coverage) {
823 while(!cert_status.empty() && cert_status.back().empty()) {
824 cert_status.pop_back();
831 const std::vector<Certificate_Store*>& certstores,
832 std::chrono::system_clock::time_point ref_time) {
833 if(cert_path.empty()) {
837 if(certstores.empty()) {
841 std::vector<std::optional<X509_CRL>> crls(cert_path.size());
843 for(
size_t i = 0; i != cert_path.size(); ++i) {
844 if(cert_path[i].skip_revocation_check()) {
847 for(
auto* certstore : certstores) {
848 crls[i] = certstore->find_crl_for(cert_path[i]);
858#if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
861 const std::vector<Certificate_Store*>& trusted_certstores,
862 std::chrono::system_clock::time_point ref_time,
863 std::chrono::milliseconds timeout,
865 if(cert_path.empty()) {
869 std::vector<std::future<std::optional<OCSP::Response>>> ocsp_response_futures;
874 to_ocsp = cert_path.size() - 1;
876 if(cert_path.size() == 1) {
880 for(
size_t i = 0; i < to_ocsp; ++i) {
881 const auto& subject = cert_path.at(i);
882 const auto& issuer = cert_path.at(i + 1);
884 if(subject.skip_revocation_check()) {
885 ocsp_response_futures.emplace_back(
886 std::async(std::launch::deferred, []() -> std::optional<OCSP::Response> {
return std::nullopt; }));
890 if(ocsp_urls.empty()) {
891 ocsp_response_futures.emplace_back(std::async(std::launch::deferred, []() -> std::optional<OCSP::Response> {
896 ocsp_response_futures.emplace_back(
897 std::async(std::launch::async, [ocsp_urls, ocsp_req, timeout]() -> std::optional<OCSP::Response> {
901 "application/ocsp-request",
902 ocsp_req.BER_encode(),
905 if(http.status_code() != 200) {
922 }
catch(std::exception&) {
930 std::vector<std::optional<OCSP::Response>> ocsp_responses;
931 ocsp_responses.reserve(ocsp_response_futures.size());
933 for(
auto& ocsp_response_future : ocsp_response_futures) {
934 ocsp_responses.push_back(ocsp_response_future.get());
937 return PKIX::check_ocsp(cert_path, ocsp_responses, trusted_certstores, ref_time, restrictions);
941 const std::vector<Certificate_Store*>& certstores,
943 std::chrono::system_clock::time_point ref_time,
944 std::chrono::milliseconds timeout) {
945 if(cert_path.empty()) {
948 if(certstores.empty()) {
952 std::vector<std::future<std::optional<X509_CRL>>> future_crls;
953 std::vector<std::optional<X509_CRL>> crls(cert_path.size());
955 for(
size_t i = 0; i != cert_path.size(); ++i) {
956 const auto& cert = cert_path.at(i);
958 if(cert.skip_revocation_check()) {
959 future_crls.emplace_back(
960 std::async(std::launch::deferred, []() -> std::optional<X509_CRL> {
return std::nullopt; }));
964 for(
auto* certstore : certstores) {
965 crls[i] = certstore->find_crl_for(cert);
966 if(crls[i].has_value()) {
979 future_crls.emplace_back(std::future<std::optional<X509_CRL>>());
983 if(cdp_uris.empty()) {
984 future_crls.emplace_back(std::async(std::launch::deferred, []() -> std::optional<X509_CRL> {
985 throw Not_Implemented(
"No CRL distribution point for this certificate");
988 future_crls.emplace_back(std::async(std::launch::async, [cdp_uris, timeout]() -> std::optional<X509_CRL> {
990 cdp_uris[0],
HTTP::RequestLimits().set_timeout(timeout).set_max_body_size(32 * 1024 * 1024));
992 http.throw_unless_ok();
1000 for(
size_t i = 0; i != future_crls.size(); ++i) {
1001 if(future_crls[i].valid()) {
1003 crls[i] = future_crls[i].get();
1004 }
catch(std::exception&) {
1013 if(crl_store !=
nullptr) {
1014 for(
size_t i = 0; i != crl_status.size(); ++i) {
1018 crl_store->add_crl(*crls[i]);
1029 const std::vector<Certificate_Store*>& trusted_certstores,
1031 const std::vector<X509_Certificate>& end_entity_extra,
1032 std::optional<size_t> max_paths) {
1033 if(max_paths.has_value() && max_paths.value() == 0) {
1037 CertificatePathBuilder builder(
1038 trusted_certstores, end_entity, end_entity_extra, PathBuildingDfsBudget,
false);
1040 std::vector<X509_Certificate> first_path;
1041 size_t paths_examined = 0;
1043 while(
auto path = builder.next()) {
1046 if(max_paths.has_value() && paths_examined >= max_paths.value()) {
1049 paths_examined += 1;
1052 if(path->back().is_self_signed()) {
1053 cert_path.insert(cert_path.end(), path->begin(), path->end());
1058 if(first_path.empty()) {
1059 first_path = std::move(*path);
1063 if(!first_path.empty()) {
1065 cert_path.insert(cert_path.end(), first_path.begin(), first_path.end());
1070 return builder.error();
1074 const std::vector<Certificate_Store*>& trusted_certstores,
1076 const std::vector<X509_Certificate>& end_entity_extra,
1077 std::optional<size_t> max_paths) {
1078 if(!cert_paths_out.empty()) {
1079 throw Invalid_Argument(
"PKIX::build_all_certificate_paths: cert_paths_out must be empty");
1081 CertificatePathBuilder builder(
1082 trusted_certstores, end_entity, end_entity_extra, PathBuildingDfsBudget,
false);
1084 while(
auto path = builder.next()) {
1086 if(max_paths.has_value() && cert_paths_out.size() >= max_paths.value()) {
1090 cert_paths_out.push_back(std::move(*path));
1093 if(!cert_paths_out.empty()) {
1098 return builder.error();
1106 if(chain_status.empty()) {
1107 throw Invalid_Argument(
"PKIX::merge_revocation_status chain_status was empty");
1110 for(
size_t i = 0; i != chain_status.size() - 1; ++i) {
1111 bool had_crl =
false;
1112 bool had_ocsp =
false;
1119 if(i < crl_status.size() && !crl_status[i].empty()) {
1120 for(
auto&& code : crl_status[i]) {
1124 chain_status[i].insert(code);
1128 if(i < ocsp_status.size() && !ocsp_status[i].empty()) {
1129 for(
auto&& code : ocsp_status[i]) {
1130 const bool was_definitive =
1139 if(was_definitive || accepted_softfail) {
1143 chain_status[i].insert(code);
1147 if(had_crl ==
false && had_ocsp ==
false) {
1157 if(cert_status.empty()) {
1164 for(
const std::set<Certificate_Status_Code>& s : cert_status) {
1166 auto worst = *s.rbegin();
1178 const std::vector<Certificate_Store*>& trusted_roots,
1179 std::string_view hostname,
1181 std::chrono::system_clock::time_point ref_time,
1182 std::chrono::milliseconds ocsp_timeout,
1183 const std::vector<std::optional<OCSP::Response>>& ocsp_resp) {
1184 if(end_certs.empty()) {
1189 const auto end_entity_extra = std::span<const X509_Certificate>(end_certs).subspan(1);
1193 CertificatePathBuilder builder(
1194 trusted_roots, end_entity, end_entity_extra, PathBuildingDfsBudget, require_self_signed);
1196 std::optional<Path_Validation_Result> first_path_error;
1197 size_t paths_checked = 0;
1198 size_t certs_checked = 0;
1200 while(
auto cert_path = builder.next()) {
1203 if(cert_path->size() > PathBuildingMaximumChainLength) {
1208 certs_checked += cert_path->size();
1209 if(paths_checked > PathBuildingMaxPathsExamined || certs_checked > PathBuildingVerificationBudget) {
1222 if(!ocsp_resp.empty()) {
1223 ocsp_status =
PKIX::check_ocsp(*cert_path, ocsp_resp, trusted_roots, ref_time, restrictions);
1226 if(ocsp_timeout != std::chrono::milliseconds(0)) {
1228 bool need_online =
false;
1229 for(
size_t i = 0; i < to_online; ++i) {
1230 if((*cert_path)[i].skip_revocation_check()) {
1233 if(i >= ocsp_status.size() || ocsp_status[i].empty()) {
1240#if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_HTTP_UTIL)
1241 auto online_status =
1242 PKIX::check_ocsp_online(*cert_path, trusted_roots, ref_time, ocsp_timeout, restrictions);
1243 if(ocsp_status.size() < online_status.size()) {
1244 ocsp_status.resize(online_status.size());
1246 for(
size_t i = 0; i < online_status.size(); ++i) {
1247 if(ocsp_status[i].empty()) {
1248 ocsp_status[i] = std::move(online_status[i]);
1252 if(ocsp_status.size() < to_online) {
1253 ocsp_status.resize(to_online);
1255 for(
size_t i = 0; i < to_online; ++i) {
1256 if(ocsp_status[i].empty()) {
1268 for(
size_t i = 0; i + 1 < cert_path->size() && i < status.size(); ++i) {
1269 if((*cert_path)[i].skip_revocation_check()) {
1278 }
else if(!first_path_error.has_value()) {
1280 first_path_error = std::move(pvd);
1284 if(first_path_error.has_value()) {
1287 return first_path_error.value();
1296 const std::vector<Certificate_Store*>& trusted_roots,
1297 std::string_view hostname,
1299 std::chrono::system_clock::time_point when,
1300 std::chrono::milliseconds ocsp_timeout,
1301 const std::vector<std::optional<OCSP::Response>>& ocsp_resp) {
1302 std::vector<X509_Certificate> certs;
1303 certs.push_back(end_cert);
1304 return x509_path_validate(certs, restrictions, trusted_roots, hostname, usage, when, ocsp_timeout, ocsp_resp);
1310 std::string_view hostname,
1312 std::chrono::system_clock::time_point when,
1313 std::chrono::milliseconds ocsp_timeout,
1314 const std::vector<std::optional<OCSP::Response>>& ocsp_resp) {
1315 std::vector<Certificate_Store*> trusted_roots;
1318 return x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, when, ocsp_timeout, ocsp_resp);
1324 std::string_view hostname,
1326 std::chrono::system_clock::time_point when,
1327 std::chrono::milliseconds ocsp_timeout,
1328 const std::vector<std::optional<OCSP::Response>>& ocsp_resp) {
1329 std::vector<X509_Certificate> certs;
1330 certs.push_back(end_cert);
1332 std::vector<Certificate_Store*> trusted_roots;
1335 return x509_path_validate(certs, restrictions, trusted_roots, hostname, usage, when, ocsp_timeout, ocsp_resp);
1339 size_t key_strength,
1340 bool ocsp_intermediates,
1346 m_require_revocation_information(require_rev),
1347 m_ocsp_all_intermediates(ocsp_intermediates),
1348 m_minimum_key_strength(key_strength),
1354 if(key_strength <= 80) {
1355 m_trusted_hashes.insert(
"SHA-1");
1358 m_trusted_hashes.insert(
"SHA-224");
1359 m_trusted_hashes.insert(
"SHA-256");
1360 m_trusted_hashes.insert(
"SHA-384");
1361 m_trusted_hashes.insert(
"SHA-512");
1362 m_trusted_hashes.insert(
"SHAKE-256(512)");
1363 m_trusted_hashes.insert(
"SHAKE-256(912)");
1366 m_trusted_hashes.insert(
"SHAKE-256(240)");
1367 m_trusted_hashes.insert(
"SHAKE-256(272)");
1368 m_trusted_hashes.insert(
"SHAKE-256(312)");
1369 m_trusted_hashes.insert(
"SHAKE-256(336)");
1370 m_trusted_hashes.insert(
"SHAKE-256(376)");
1371 m_trusted_hashes.insert(
"SHAKE-256(392)");
1377 for(
const auto& status_set_i : all_statuses) {
1378 std::set<Certificate_Status_Code> warning_set_i;
1379 for(
const auto& code : status_set_i) {
1382 warning_set_i.insert(code);
1385 warnings.push_back(warning_set_i);
1392 std::vector<X509_Certificate>&& cert_chain) :
1393 m_all_status(std::move(status)),
1394 m_warnings(find_warnings(m_all_status)),
1395 m_cert_path(std::move(cert_chain)),
1396 m_overall(
PKIX::overall_status(m_all_status)) {}
1399 if(m_cert_path.empty()) {
1400 throw Invalid_State(
"Path_Validation_Result::trust_root no path set");
1403 throw Invalid_State(
"Path_Validation_Result::trust_root meaningless with invalid status");
1406 return m_cert_path[m_cert_path.size() - 1];
1415 for(
const auto& status_set_i : m_warnings) {
1416 if(!status_set_i.empty()) {
1436 return "Unknown error";
1440 const std::string sep(
", ");
1441 std::ostringstream oss;
1442 for(
size_t i = 0; i < m_warnings.size(); i++) {
1443 for(
auto code : m_warnings[i]) {
1444 oss <<
"[" << std::to_string(i) <<
"] " <<
status_string(code) << sep;
1448 std::string res = oss.str();
1450 if(res.size() >= sep.size()) {
1451 res = res.substr(0, res.size() - sep.size());
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ARG_CHECK(expr, msg)
const std::optional< ReasonFlags > & only_some_reasons() const
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const
const std::vector< OID > & get_extension_oids() const
RequestLimits & set_timeout(std::chrono::milliseconds t)
RequestLimits & set_max_body_size(size_t n)
static Response dummy_server_not_available_response()
static Response dummy_no_revocation_url_response()
bool registered_oid() const
BOTAN_FUTURE_EXPLICIT Path_Validation_Restrictions(bool require_rev=false, size_t minimum_key_strength=110, bool ocsp_all_intermediates=false, std::chrono::seconds max_ocsp_age=std::chrono::hours(24 *7), std::unique_ptr< Certificate_Store > trusted_ocsp_responders=nullptr, bool ignore_trusted_root_time_range=false, bool require_self_signed_trust_anchors=true, bool accept_ocsp_softfail=false)
bool require_revocation_information() const
bool ocsp_all_intermediates() const
const std::set< std::string > & trusted_hashes() const
bool accept_ocsp_softfail() const
std::chrono::seconds max_ocsp_age() const
bool ignore_trusted_root_time_range() const
bool require_self_signed_trust_anchors() const
size_t minimum_key_strength() const
const Certificate_Store * trusted_ocsp_responders() const
Certificate_Status_Code result() const
Path_Validation_Result(CertificatePathStatusCodes status, std::vector< X509_Certificate > &&cert_chain)
bool successful_validation() const
static const char * status_string(Certificate_Status_Code code)
const X509_Certificate & trust_root() const
std::string result_string() const
std::string warnings_string() const
CertificatePathStatusCodes warnings() const
static std::vector< URI > filter_scheme(std::string_view scheme, std::span< const URI > uris)
const X509_DN & subject_dn() const
bool skip_revocation_check() const
const X509_Serial_Number & serial() const
const X509_Time & not_after() const
const std::vector< uint8_t > & authority_key_id() const
const std::vector< uint8_t > & subject_key_id() const
std::optional< size_t > path_length_constraint() const
const Extensions & v3_extensions() const
bool allowed_usage(Key_Constraints usage) const
const X509_DN & issuer_dn() const
const std::vector< uint8_t > & v2_issuer_key_id() const
uint32_t x509_version() const
bool is_self_signed() const
std::unique_ptr< Public_Key > subject_public_key() const
const std::vector< uint8_t > & v2_subject_key_id() const
const X509_Time & not_before() const
const std::vector< std::vector< std::pair< OID, ASN1_String > > > & rdns() const
static size_t lookup_ub(const OID &oid)
const AlgorithmIdentifier & signature_algorithm() const
std::pair< Certificate_Status_Code, std::string > verify_signature(const Public_Key &key) const
bool check_signature(const Public_Key &key) const
Response GET_sync(const URI &uri, const RequestLimits &limits)
Response POST_sync(const URI &uri, std::string_view content_type, const std::vector< uint8_t > &body, const RequestLimits &limits)
void merge_revocation_status(CertificatePathStatusCodes &chain_status, const CertificatePathStatusCodes &crl_status, const CertificatePathStatusCodes &ocsp_status, const Path_Validation_Restrictions &restrictions)
Certificate_Status_Code build_certificate_path(std::vector< X509_Certificate > &cert_path_out, const std::vector< Certificate_Store * > &trusted_certstores, const X509_Certificate &end_entity, const std::vector< X509_Certificate > &end_entity_extra, std::optional< size_t > max_paths=std::nullopt)
Certificate_Status_Code build_all_certificate_paths(std::vector< std::vector< X509_Certificate > > &cert_paths, const std::vector< Certificate_Store * > &trusted_certstores, const X509_Certificate &end_entity, const std::vector< X509_Certificate > &end_entity_extra, std::optional< size_t > max_paths=std::nullopt)
Certificate_Status_Code overall_status(const CertificatePathStatusCodes &cert_status)
CertificatePathStatusCodes check_ocsp(const std::vector< X509_Certificate > &cert_path, const std::vector< std::optional< OCSP::Response > > &ocsp_responses, const std::vector< Certificate_Store * > &certstores, std::chrono::system_clock::time_point ref_time, const Path_Validation_Restrictions &restrictions)
CertificatePathStatusCodes check_chain(const std::vector< X509_Certificate > &cert_path, std::chrono::system_clock::time_point ref_time, std::string_view hostname, Usage_Type usage, const Path_Validation_Restrictions &restrictions)
CertificatePathStatusCodes check_crl(const std::vector< X509_Certificate > &cert_path, const std::vector< std::optional< X509_CRL > > &crls, std::chrono::system_clock::time_point ref_time)
std::vector< std::set< Certificate_Status_Code > > CertificatePathStatusCodes
@ TRUSTED_CERT_NOT_YET_VALID
@ OCSP_RESPONSE_MISSING_KEYUSAGE
@ TRUSTED_CERT_HAS_EXPIRED
@ OCSP_ISSUER_NOT_TRUSTED
@ CRL_HAS_UNKNOWN_CRITICAL_EXTENSION
@ CA_CERT_NOT_FOR_CRL_ISSUER
@ CA_CERT_NOT_FOR_CERT_ISSUER
@ FIRST_ERROR_STATUS_TO_SKIP_REVOCATION
@ OCSP_SERVER_NOT_AVAILABLE
@ V2_IDENTIFIERS_IN_V1_CERT
@ SIGNATURE_METHOD_TOO_WEAK
DistributionPointMatch distribution_point_match(const X509_CRL &crl, const X509_Certificate &cert)
Path_Validation_Result x509_path_validate(const std::vector< X509_Certificate > &end_certs, const Path_Validation_Restrictions &restrictions, const std::vector< Certificate_Store * > &trusted_roots, std::string_view hostname, Usage_Type usage, std::chrono::system_clock::time_point ref_time, std::chrono::milliseconds ocsp_timeout, const std::vector< std::optional< OCSP::Response > > &ocsp_resp)
constexpr auto concat(Rs &&... ranges)
std::string to_string(ErrorType type)
Convert an ErrorType to string.