Botan  2.1.0
Crypto and TLS for C++11
x509path.cpp
Go to the documentation of this file.
1 /*
2 * X.509 Certificate Path Validation
3 * (C) 2010,2011,2012,2014,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/x509path.h>
9 #include <botan/ocsp.h>
10 #include <botan/parsing.h>
11 #include <botan/pubkey.h>
12 #include <botan/oids.h>
13 #include <algorithm>
14 #include <chrono>
15 #include <vector>
16 #include <set>
17 
18 #if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
19  #include <future>
20  #include <botan/http_util.h>
21 #endif
22 
23 namespace Botan {
24 
25 /*
26 * PKIX path validation
27 */
29 PKIX::check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
30  std::chrono::system_clock::time_point ref_time,
31  const std::string& hostname,
32  Usage_Type usage,
33  size_t min_signature_algo_strength,
34  const std::set<std::string>& trusted_hashes)
35  {
36  if(cert_path.empty())
37  throw Invalid_Argument("PKIX::check_chain cert_path empty");
38 
39  const bool self_signed_ee_cert = (cert_path.size() == 1);
40 
41  X509_Time validation_time(ref_time);
42 
43  CertificatePathStatusCodes cert_status(cert_path.size());
44 
45  if(!hostname.empty() && !cert_path[0]->matches_dns_name(hostname))
46  cert_status[0].insert(Certificate_Status_Code::CERT_NAME_NOMATCH);
47 
48  if(!cert_path[0]->allowed_usage(usage))
49  cert_status[0].insert(Certificate_Status_Code::INVALID_USAGE);
50 
51  for(size_t i = 0; i != cert_path.size(); ++i)
52  {
53  std::set<Certificate_Status_Code>& status = cert_status.at(i);
54 
55  const bool at_self_signed_root = (i == cert_path.size() - 1);
56 
57  const std::shared_ptr<const X509_Certificate>& subject = cert_path[i];
58 
59  const std::shared_ptr<const X509_Certificate>& issuer = cert_path[at_self_signed_root ? (i) : (i + 1)];
60 
61  if(at_self_signed_root && (issuer->is_self_signed() == false))
62  {
64  }
65 
66  if(subject->issuer_dn() != issuer->subject_dn())
67  {
69  }
70 
71  // Check all certs for valid time range
72  if(validation_time < X509_Time(subject->start_time(), ASN1_Tag::UTC_OR_GENERALIZED_TIME))
74 
75  if(validation_time > X509_Time(subject->end_time(), ASN1_Tag::UTC_OR_GENERALIZED_TIME))
77 
78  // Check issuer constraints
79 
80  if(!issuer->is_CA_cert() && !self_signed_ee_cert)
82 
83  if(issuer->path_limit() < i)
85 
86  std::unique_ptr<Public_Key> issuer_key(issuer->subject_public_key());
87 
88  if(!issuer_key)
89  {
91  }
92  else
93  {
94  if(subject->check_signature(*issuer_key) == false)
95  {
97  }
98 
99  if(issuer_key->estimated_strength() < min_signature_algo_strength)
101  }
102 
103  // Ignore untrusted hashes on self-signed roots
104  if(trusted_hashes.size() > 0 && !at_self_signed_root)
105  {
106  if(trusted_hashes.count(subject->hash_used_for_signature()) == 0)
108  }
109 
110  // Check cert extensions
111  Extensions extensions = subject->v3_extensions();
112  for(auto& extension : extensions.extensions())
113  {
114  extension.first->validate(*subject, *issuer, cert_path, cert_status, i);
115  }
116  }
117 
118  return cert_status;
119  }
120 
122 PKIX::check_ocsp(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
123  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
124  const std::vector<Certificate_Store*>& trusted_certstores,
125  std::chrono::system_clock::time_point ref_time)
126  {
127  if(cert_path.empty())
128  throw Invalid_Argument("PKIX::check_ocsp cert_path empty");
129 
130  CertificatePathStatusCodes cert_status(cert_path.size() - 1);
131 
132  for(size_t i = 0; i != cert_path.size() - 1; ++i)
133  {
134  std::set<Certificate_Status_Code>& status = cert_status.at(i);
135 
136  std::shared_ptr<const X509_Certificate> subject = cert_path.at(i);
137  std::shared_ptr<const X509_Certificate> ca = cert_path.at(i+1);
138 
139  if(i < ocsp_responses.size() && (ocsp_responses.at(i) != nullptr))
140  {
141  try
142  {
143  Certificate_Status_Code ocsp_signature_status = ocsp_responses.at(i)->check_signature(trusted_certstores, cert_path);
144 
145  if(ocsp_signature_status == Certificate_Status_Code::OCSP_SIGNATURE_OK)
146  {
147  // Signature ok, so check the claimed status
148  Certificate_Status_Code ocsp_status = ocsp_responses.at(i)->status_for(*ca, *subject, ref_time);
149  status.insert(ocsp_status);
150  }
151  else
152  {
153  // Some signature problem
154  status.insert(ocsp_signature_status);
155  }
156  }
157  catch(Exception& e)
158  {
160  }
161  }
162  }
163 
164  while(cert_status.size() > 0 && cert_status.back().empty())
165  cert_status.pop_back();
166 
167  return cert_status;
168  }
169 
171 PKIX::check_crl(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
172  const std::vector<std::shared_ptr<const X509_CRL>>& crls,
173  std::chrono::system_clock::time_point ref_time)
174  {
175  if(cert_path.empty())
176  throw Invalid_Argument("PKIX::check_crl cert_path empty");
177 
178  CertificatePathStatusCodes cert_status(cert_path.size());
179  const X509_Time validation_time(ref_time);
180 
181  for(size_t i = 0; i != cert_path.size() - 1; ++i)
182  {
183  std::set<Certificate_Status_Code>& status = cert_status.at(i);
184 
185  if(i < crls.size() && crls.at(i))
186  {
187  std::shared_ptr<const X509_Certificate> subject = cert_path.at(i);
188  std::shared_ptr<const X509_Certificate> ca = cert_path.at(i+1);
189 
190  if(!ca->allowed_usage(CRL_SIGN))
192 
193  if(validation_time < X509_Time(crls[i]->this_update()))
195 
196  if(validation_time > X509_Time(crls[i]->next_update()))
198 
199  if(crls[i]->check_signature(ca->subject_public_key()) == false)
201 
203 
204  if(crls[i]->is_revoked(*subject))
206  }
207  }
208 
209  while(cert_status.size() > 0 && cert_status.back().empty())
210  cert_status.pop_back();
211 
212  return cert_status;
213  }
214 
216 PKIX::check_crl(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
217  const std::vector<Certificate_Store*>& certstores,
218  std::chrono::system_clock::time_point ref_time)
219  {
220  if(cert_path.empty())
221  throw Invalid_Argument("PKIX::check_crl cert_path empty");
222 
223  if(certstores.empty())
224  throw Invalid_Argument("PKIX::check_crl certstores empty");
225 
226  std::vector<std::shared_ptr<const X509_CRL>> crls(cert_path.size());
227 
228  for(size_t i = 0; i != cert_path.size(); ++i)
229  {
230  BOTAN_ASSERT_NONNULL(cert_path[i]);
231  for(size_t c = 0; c != certstores.size(); ++c)
232  {
233  crls[i] = certstores[c]->find_crl_for(*cert_path[i]);
234  if(crls[i])
235  break;
236  }
237  }
238 
239  return PKIX::check_crl(cert_path, crls, ref_time);
240  }
241 
242 #if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
243 
245 PKIX::check_ocsp_online(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
246  const std::vector<Certificate_Store*>& trusted_certstores,
247  std::chrono::system_clock::time_point ref_time,
248  std::chrono::milliseconds timeout,
249  bool ocsp_check_intermediate_CAs)
250  {
251  if(cert_path.empty())
252  throw Invalid_Argument("PKIX::check_ocsp_online cert_path empty");
253 
254  std::vector<std::future<std::shared_ptr<const OCSP::Response>>> ocsp_response_futures;
255 
256  size_t to_ocsp = 1;
257 
258  if(ocsp_check_intermediate_CAs)
259  to_ocsp = cert_path.size() - 1;
260  if(cert_path.size() == 1)
261  to_ocsp = 0;
262 
263  for(size_t i = 0; i < to_ocsp; ++i)
264  {
265  const std::shared_ptr<const X509_Certificate>& subject = cert_path.at(i);
266  const std::shared_ptr<const X509_Certificate>& issuer = cert_path.at(i+1);
267 
268  if(subject->ocsp_responder() == "")
269  {
270  ocsp_response_futures.emplace_back(std::async(std::launch::deferred, [&]() -> std::shared_ptr<const OCSP::Response> {
271  throw Exception("No OCSP responder URL set for this certificate");
272  }));
273  }
274  else
275  {
276  ocsp_response_futures.emplace_back(std::async(std::launch::async, [&]() -> std::shared_ptr<const OCSP::Response> {
277  OCSP::Request req(*issuer, BigInt::decode(subject->serial_number()));
278 
279  auto http = HTTP::POST_sync(subject->ocsp_responder(),
280  "application/ocsp-request",
281  req.BER_encode());
282 
283  http.throw_unless_ok();
284  // Check the MIME type?
285 
286  return std::make_shared<const OCSP::Response>(http.body());
287  }));
288  }
289  }
290 
291  std::vector<std::shared_ptr<const OCSP::Response>> ocsp_responses(ocsp_response_futures.size());
292 
293  for(size_t pass = 1; pass < 3; ++pass)
294  {
295  for(size_t i = 0; i < ocsp_response_futures.size(); ++i)
296  {
297  try
298  {
299  if(ocsp_responses[i] == nullptr && ocsp_response_futures[i].valid())
300  {
301  std::future_status status = ocsp_response_futures[i].wait_for(timeout);
302 
303  if(status == std::future_status::ready ||
304  status == std::future_status::deferred)
305  {
306  ocsp_responses[i] = ocsp_response_futures[i].get();
307  }
308  }
309  }
310  catch(std::exception&)
311  {
312  // value is default initialized to null, no need to do anything
313  }
314  }
315  }
316 
317  return PKIX::check_ocsp(cert_path, ocsp_responses, trusted_certstores, ref_time);
318  }
319 
321 PKIX::check_crl_online(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
322  const std::vector<Certificate_Store*>& certstores,
323  Certificate_Store_In_Memory* crl_store,
324  std::chrono::system_clock::time_point ref_time,
325  std::chrono::milliseconds timeout)
326  {
327  if(cert_path.empty())
328  throw Invalid_Argument("PKIX::check_crl_online cert_path empty");
329  if(certstores.empty())
330  throw Invalid_Argument("PKIX::check_crl_online certstores empty");
331 
332  std::vector<std::future<std::shared_ptr<const X509_CRL>>> future_crls;
333  std::vector<std::shared_ptr<const X509_CRL>> crls(cert_path.size());
334 
335  for(size_t i = 0; i != cert_path.size(); ++i)
336  {
337  for(size_t c = 0; c != certstores.size(); ++i)
338  {
339  crls[i] = certstores[i]->find_crl_for(*cert_path[i]);
340  if(crls[i])
341  break;
342  }
343 
344  // TODO: check if CRL is expired and re-request?
345 
346  // Only request if we don't already have a CRL
347  if(crls[i])
348  {
349  /*
350  We already have a CRL, so just insert this empty one to hold a place in the vector
351  so that indexes match up
352  */
353  future_crls.emplace_back(std::future<std::shared_ptr<const X509_CRL>>());
354  }
355  else if(cert_path[i]->crl_distribution_point() == "")
356  {
357  // Avoid creating a thread for this case
358  future_crls.emplace_back(std::async(std::launch::deferred, [&]() -> std::shared_ptr<const X509_CRL> {
359  throw Exception("No CRL distribution point for this certificate");
360  }));
361  }
362  else
363  {
364  future_crls.emplace_back(std::async(std::launch::async, [&]() -> std::shared_ptr<const X509_CRL> {
365  auto http = HTTP::GET_sync(cert_path[i]->crl_distribution_point());
366  http.throw_unless_ok();
367  // check the mime type?
368  return std::make_shared<const X509_CRL>(http.body());
369  }));
370  }
371  }
372 
373  for(size_t i = 0; i != future_crls.size(); ++i)
374  {
375  if(future_crls[i].valid())
376  {
377  try
378  {
379  std::future_status status = future_crls[i].wait_for(timeout);
380 
381  if(status == std::future_status::ready)
382  {
383  crls[i] = future_crls[i].get();
384  }
385  }
386  catch(std::exception& e)
387  {
388  // crls[i] left null
389  }
390  }
391  }
392 
393  const CertificatePathStatusCodes crl_status = PKIX::check_crl(cert_path, crls, ref_time);
394 
395  if(crl_store)
396  {
397  for(size_t i = 0; i != crl_status.size(); ++i)
398  {
399  if(crl_status[i].count(Certificate_Status_Code::VALID_CRL_CHECKED))
400  {
401  // better be non-null, we supposedly validated it
402  BOTAN_ASSERT_NONNULL(crls[i]);
403  crl_store->add_crl(crls[i]);
404  }
405  }
406  }
407 
408  return crl_status;
409  }
410 
411 #endif
412 
414 PKIX::build_certificate_path(std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
415  const std::vector<Certificate_Store*>& trusted_certstores,
416  const std::shared_ptr<const X509_Certificate>& end_entity,
417  const std::vector<std::shared_ptr<const X509_Certificate>>& end_entity_extra)
418  {
419  if(end_entity->is_self_signed())
420  {
422  }
423 
424  /*
425  * This is an inelegant but functional way of preventing path loops
426  * (where C1 -> C2 -> C3 -> C1). We store a set of all the certificate
427  * fingerprints in the path. If there is a duplicate, we error out.
428  * TODO: save fingerprints in result struct? Maybe useful for blacklists, etc.
429  */
430  std::set<std::string> certs_seen;
431 
432  cert_path.push_back(end_entity);
433  certs_seen.insert(end_entity->fingerprint("SHA-256"));
434 
435  Certificate_Store_In_Memory ee_extras;
436  for(size_t i = 0; i != end_entity_extra.size(); ++i)
437  ee_extras.add_certificate(end_entity_extra[i]);
438 
439  // iterate until we reach a root or cannot find the issuer
440  for(;;)
441  {
442  const X509_Certificate& last = *cert_path.back();
443  const X509_DN issuer_dn = last.issuer_dn();
444  const std::vector<uint8_t> auth_key_id = last.authority_key_id();
445 
446  std::shared_ptr<const X509_Certificate> issuer;
447  bool trusted_issuer = false;
448 
449  for(Certificate_Store* store : trusted_certstores)
450  {
451  issuer = store->find_cert(issuer_dn, auth_key_id);
452  if(issuer)
453  {
454  trusted_issuer = true;
455  break;
456  }
457  }
458 
459  if(!issuer)
460  {
461  // fall back to searching supplemental certs
462  issuer = ee_extras.find_cert(issuer_dn, auth_key_id);
463  }
464 
465  if(!issuer)
467 
468  const std::string fprint = issuer->fingerprint("SHA-256");
469 
470  if(certs_seen.count(fprint) > 0) // already seen?
472 
473  certs_seen.insert(fprint);
474  cert_path.push_back(issuer);
475 
476  if(issuer->is_self_signed())
477  {
478  if(trusted_issuer)
479  {
481  }
482  else
483  {
485  }
486  }
487  }
488  }
489 
491  const CertificatePathStatusCodes& crl,
492  const CertificatePathStatusCodes& ocsp,
493  bool require_rev_on_end_entity,
494  bool require_rev_on_intermediates)
495  {
496  if(chain_status.empty())
497  throw Invalid_Argument("PKIX::merge_revocation_status chain_status was empty");
498 
499  for(size_t i = 0; i != chain_status.size() - 1; ++i)
500  {
501  bool had_crl = false, had_ocsp = false;
502 
503  if(i < crl.size() && crl[i].size() > 0)
504  {
505  for(auto&& code : crl[i])
506  {
508  {
509  had_crl = true;
510  }
511  chain_status[i].insert(code);
512  }
513  }
514 
515  if(i < ocsp.size() && ocsp[i].size() > 0)
516  {
517  for(auto&& code : ocsp[i])
518  {
520  {
521  had_ocsp = true;
522  }
523 
524  chain_status[i].insert(code);
525  }
526  }
527 
528  if(had_crl == false && had_ocsp == false)
529  {
530  if((require_rev_on_end_entity && i == 0) ||
531  (require_rev_on_intermediates && i > 0))
532  {
533  chain_status[i].insert(Certificate_Status_Code::NO_REVOCATION_DATA);
534  }
535  }
536  }
537  }
538 
540  {
541  if(cert_status.empty())
542  throw Invalid_Argument("PKIX::overall_status empty cert status");
543 
545 
546  // take the "worst" error as overall
547  for(const std::set<Certificate_Status_Code>& s : cert_status)
548  {
549  if(!s.empty())
550  {
551  auto worst = *s.rbegin();
552  // Leave informative OCSP/CRL confirmations on cert-level status only
553  if(worst >= Certificate_Status_Code::FIRST_ERROR_STATUS && worst > overall_status)
554  {
555  overall_status = worst;
556  }
557  }
558  }
559  return overall_status;
560  }
561 
563  const std::vector<X509_Certificate>& end_certs,
564  const Path_Validation_Restrictions& restrictions,
565  const std::vector<Certificate_Store*>& trusted_roots,
566  const std::string& hostname,
567  Usage_Type usage,
568  std::chrono::system_clock::time_point ref_time,
569  std::chrono::milliseconds ocsp_timeout,
570  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp)
571  {
572  if(end_certs.empty())
573  throw Invalid_Argument("x509_path_validate called with no subjects");
574 
575  std::shared_ptr<const X509_Certificate> end_entity(std::make_shared<const X509_Certificate>(end_certs[0]));
576  std::vector<std::shared_ptr<const X509_Certificate>> end_entity_extra;
577  for(size_t i = 1; i < end_certs.size(); ++i)
578  {
579  end_entity_extra.push_back(std::make_shared<const X509_Certificate>(end_certs[i]));
580  }
581 
582  std::vector<std::shared_ptr<const X509_Certificate>> cert_path;
583  Certificate_Status_Code path_building_result =
584  PKIX::build_certificate_path(cert_path, trusted_roots, end_entity, end_entity_extra);
585 
586  // If we cannot successfully build a chain to a trusted self-signed root, stop now
587  if(path_building_result != Certificate_Status_Code::OK)
588  {
589  return Path_Validation_Result(path_building_result);
590  }
591 
593  PKIX::check_chain(cert_path, ref_time,
594  hostname, usage,
595  restrictions.minimum_key_strength(),
596  restrictions.trusted_hashes());
597 
598  CertificatePathStatusCodes crl_status =
599  PKIX::check_crl(cert_path, trusted_roots, ref_time);
600 
601  CertificatePathStatusCodes ocsp_status;
602 
603  if(ocsp_resp.size() > 0)
604  {
605  ocsp_status = PKIX::check_ocsp(cert_path, ocsp_resp, trusted_roots, ref_time);
606  }
607 
608  if(ocsp_status.empty() && ocsp_timeout != std::chrono::milliseconds(0))
609  {
610 #if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_HTTP_UTIL)
611  ocsp_status = PKIX::check_ocsp_online(cert_path, trusted_roots, ref_time,
612  ocsp_timeout, restrictions.ocsp_all_intermediates());
613 #else
614  ocsp_status.resize(1);
615  ocsp_status[0].insert(Certificate_Status_Code::OCSP_NO_HTTP);
616 #endif
617  }
618 
619  PKIX::merge_revocation_status(status, crl_status, ocsp_status,
620  restrictions.require_revocation_information(),
621  restrictions.ocsp_all_intermediates());
622 
623  return Path_Validation_Result(status, std::move(cert_path));
624  }
625 
627  const X509_Certificate& end_cert,
628  const Path_Validation_Restrictions& restrictions,
629  const std::vector<Certificate_Store*>& trusted_roots,
630  const std::string& hostname,
631  Usage_Type usage,
632  std::chrono::system_clock::time_point when,
633  std::chrono::milliseconds ocsp_timeout,
634  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp)
635  {
636  std::vector<X509_Certificate> certs;
637  certs.push_back(end_cert);
638  return x509_path_validate(certs, restrictions, trusted_roots, hostname, usage, when, ocsp_timeout, ocsp_resp);
639  }
640 
642  const std::vector<X509_Certificate>& end_certs,
643  const Path_Validation_Restrictions& restrictions,
644  const Certificate_Store& store,
645  const std::string& hostname,
646  Usage_Type usage,
647  std::chrono::system_clock::time_point when,
648  std::chrono::milliseconds ocsp_timeout,
649  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp)
650  {
651  std::vector<Certificate_Store*> trusted_roots;
652  trusted_roots.push_back(const_cast<Certificate_Store*>(&store));
653 
654  return x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, when, ocsp_timeout, ocsp_resp);
655  }
656 
658  const X509_Certificate& end_cert,
659  const Path_Validation_Restrictions& restrictions,
660  const Certificate_Store& store,
661  const std::string& hostname,
662  Usage_Type usage,
663  std::chrono::system_clock::time_point when,
664  std::chrono::milliseconds ocsp_timeout,
665  const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_resp)
666  {
667  std::vector<X509_Certificate> certs;
668  certs.push_back(end_cert);
669 
670  std::vector<Certificate_Store*> trusted_roots;
671  trusted_roots.push_back(const_cast<Certificate_Store*>(&store));
672 
673  return x509_path_validate(certs, restrictions, trusted_roots, hostname, usage, when, ocsp_timeout, ocsp_resp);
674  }
675 
677  size_t key_strength,
678  bool ocsp_intermediates) :
679  m_require_revocation_information(require_rev),
680  m_ocsp_all_intermediates(ocsp_intermediates),
681  m_minimum_key_strength(key_strength)
682  {
683  if(key_strength <= 80)
684  m_trusted_hashes.insert("SHA-160");
685 
686  m_trusted_hashes.insert("SHA-224");
687  m_trusted_hashes.insert("SHA-256");
688  m_trusted_hashes.insert("SHA-384");
689  m_trusted_hashes.insert("SHA-512");
690  }
691 
693  std::vector<std::shared_ptr<const X509_Certificate>>&& cert_chain) :
694  m_all_status(status),
695  m_cert_path(cert_chain),
696  m_overall(PKIX::overall_status(m_all_status))
697  {
698  }
699 
701  {
702  if(m_cert_path.empty())
703  throw Exception("Path_Validation_Result::trust_root no path set");
705  throw Exception("Path_Validation_Result::trust_root meaningless with invalid status");
706 
707  return *m_cert_path[m_cert_path.size()-1];
708  }
709 
710 std::set<std::string> Path_Validation_Result::trusted_hashes() const
711  {
712  std::set<std::string> hashes;
713  for(size_t i = 0; i != m_cert_path.size(); ++i)
714  hashes.insert(m_cert_path[i]->hash_used_for_signature());
715  return hashes;
716  }
717 
719  {
723  }
724 
726  {
727  return status_string(result());
728  }
729 
731  {
732  if(const char* s = to_string(code))
733  return s;
734 
735  return "Unknown error";
736  }
737 
738 }
CertificatePathStatusCodes BOTAN_DLL check_chain(const std::vector< std::shared_ptr< const X509_Certificate >> &cert_path, std::chrono::system_clock::time_point ref_time, const std::string &hostname, Usage_Type usage, size_t min_signature_algo_strength, const std::set< std::string > &trusted_hashes)
Definition: x509path.cpp:29
Path_Validation_Result(CertificatePathStatusCodes status, std::vector< std::shared_ptr< const X509_Certificate >> &&cert_chain)
Definition: x509path.cpp:692
CertificatePathStatusCodes BOTAN_DLL check_ocsp(const std::vector< std::shared_ptr< const X509_Certificate >> &cert_path, const std::vector< std::shared_ptr< const OCSP::Response >> &ocsp_responses, const std::vector< Certificate_Store * > &certstores, std::chrono::system_clock::time_point ref_time)
Definition: x509path.cpp:122
Certificate_Status_Code BOTAN_DLL overall_status(const CertificatePathStatusCodes &cert_status)
Definition: x509path.cpp:539
std::shared_ptr< const X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
Definition: certstor.cpp:46
std::vector< std::pair< std::unique_ptr< Certificate_Extension >, bool > > extensions() const
Definition: x509_ext.cpp:139
void BOTAN_DLL merge_revocation_status(CertificatePathStatusCodes &chain_status, const CertificatePathStatusCodes &crl_status, const CertificatePathStatusCodes &ocsp_status, bool require_rev_on_end_entity, bool require_rev_on_intermediates)
Definition: x509path.cpp:490
bool require_revocation_information() const
Definition: x509path.h:78
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:79
Certificate_Status_Code result() const
Definition: x509path.h:141
CertificatePathStatusCodes BOTAN_DLL check_crl(const std::vector< std::shared_ptr< const X509_Certificate >> &cert_path, const std::vector< std::shared_ptr< const X509_CRL >> &crls, std::chrono::system_clock::time_point ref_time)
Definition: x509path.cpp:171
Response POST_sync(const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
Definition: http_util.cpp:294
Definition: alg_id.cpp:13
bool ocsp_all_intermediates() const
Definition: x509path.h:85
void add_certificate(const X509_Certificate &cert)
Definition: certstor.cpp:19
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, const std::string &hostname, Usage_Type usage, std::chrono::system_clock::time_point ref_time, std::chrono::milliseconds ocsp_timeout, const std::vector< std::shared_ptr< const OCSP::Response >> &ocsp_resp)
Definition: x509path.cpp:562
std::set< std::string > trusted_hashes() const
Definition: x509path.cpp:710
std::string result_string() const
Definition: x509path.cpp:725
const std::set< std::string > & trusted_hashes() const
Definition: x509path.h:91
Certificate_Status_Code BOTAN_DLL build_certificate_path(std::vector< std::shared_ptr< const X509_Certificate >> &cert_path_out, const std::vector< Certificate_Store * > &trusted_certstores, const std::shared_ptr< const X509_Certificate > &end_entity, const std::vector< std::shared_ptr< const X509_Certificate >> &end_entity_extra)
Definition: x509path.cpp:414
std::string to_string(const secure_vector< uint8_t > &bytes)
Definition: stl_util.h:25
static const char * status_string(Certificate_Status_Code code)
Definition: x509path.cpp:730
Path_Validation_Restrictions(bool require_rev=false, size_t minimum_key_strength=110, bool ocsp_all_intermediates=false)
Definition: x509path.cpp:676
std::vector< std::set< Certificate_Status_Code > > CertificatePathStatusCodes
Definition: x509path.h:29
X509_DN issuer_dn() const
Definition: x509cert.cpp:432
Response GET_sync(const std::string &url, size_t allowable_redirects)
Definition: http_util.cpp:289
Certificate_Status_Code
Definition: cert_status.h:18
bool successful_validation() const
Definition: x509path.cpp:718
size_t minimum_key_strength() const
Definition: x509path.h:97
std::vector< uint8_t > authority_key_id() const
Definition: x509cert.cpp:411
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
Definition: big_code.cpp:114
Usage_Type
Definition: x509cert.h:24
const X509_Certificate & trust_root() const
Definition: x509path.cpp:700