Botan  2.12.1
Crypto and TLS for C++11
x509cert.cpp
Go to the documentation of this file.
1 /*
2 * X.509 Certificates
3 * (C) 1999-2010,2015,2017 Jack Lloyd
4 * (C) 2016 RenĂ© Korthaus, Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/x509cert.h>
10 #include <botan/datastor.h>
11 #include <botan/pk_keys.h>
12 #include <botan/x509_ext.h>
13 #include <botan/ber_dec.h>
14 #include <botan/parsing.h>
15 #include <botan/bigint.h>
16 #include <botan/oids.h>
17 #include <botan/hash.h>
18 #include <botan/hex.h>
19 #include <algorithm>
20 #include <sstream>
21 
22 namespace Botan {
23 
24 struct X509_Certificate_Data
25  {
26  std::vector<uint8_t> m_serial;
27  AlgorithmIdentifier m_sig_algo_inner;
28  X509_DN m_issuer_dn;
29  X509_DN m_subject_dn;
30  std::vector<uint8_t> m_issuer_dn_bits;
31  std::vector<uint8_t> m_subject_dn_bits;
32  X509_Time m_not_before;
33  X509_Time m_not_after;
34  std::vector<uint8_t> m_subject_public_key_bits;
35  std::vector<uint8_t> m_subject_public_key_bits_seq;
36  std::vector<uint8_t> m_subject_public_key_bitstring;
37  std::vector<uint8_t> m_subject_public_key_bitstring_sha1;
38  AlgorithmIdentifier m_subject_public_key_algid;
39 
40  std::vector<uint8_t> m_v2_issuer_key_id;
41  std::vector<uint8_t> m_v2_subject_key_id;
42  Extensions m_v3_extensions;
43 
44  std::vector<OID> m_extended_key_usage;
45  std::vector<uint8_t> m_authority_key_id;
46  std::vector<uint8_t> m_subject_key_id;
47  std::vector<OID> m_cert_policies;
48 
49  std::vector<std::string> m_crl_distribution_points;
50  std::string m_ocsp_responder;
51  std::vector<std::string> m_ca_issuers;
52 
53  AlternativeName m_subject_alt_name;
54  AlternativeName m_issuer_alt_name;
55  NameConstraints m_name_constraints;
56 
57  Data_Store m_subject_ds;
58  Data_Store m_issuer_ds;
59 
60  size_t m_version = 0;
61  size_t m_path_len_constraint = 0;
62  Key_Constraints m_key_constraints = NO_CONSTRAINTS;
63  bool m_self_signed = false;
64  bool m_is_ca_certificate = false;
65  bool m_serial_negative = false;
66  };
67 
68 std::string X509_Certificate::PEM_label() const
69  {
70  return "CERTIFICATE";
71  }
72 
73 std::vector<std::string> X509_Certificate::alternate_PEM_labels() const
74  {
75  return { "X509 CERTIFICATE" };
76  }
77 
79  {
80  load_data(src);
81  }
82 
83 X509_Certificate::X509_Certificate(const std::vector<uint8_t>& vec)
84  {
85  DataSource_Memory src(vec.data(), vec.size());
86  load_data(src);
87  }
88 
89 X509_Certificate::X509_Certificate(const uint8_t data[], size_t len)
90  {
91  DataSource_Memory src(data, len);
92  load_data(src);
93  }
94 
95 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
96 X509_Certificate::X509_Certificate(const std::string& fsname)
97  {
98  DataSource_Stream src(fsname, true);
99  load_data(src);
100  }
101 #endif
102 
103 namespace {
104 
105 std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& obj)
106  {
107  std::unique_ptr<X509_Certificate_Data> data(new X509_Certificate_Data);
108 
109  BigInt serial_bn;
110  BER_Object public_key;
111  BER_Object v3_exts_data;
112 
113  BER_Decoder(obj.signed_body())
114  .decode_optional(data->m_version, ASN1_Tag(0), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
115  .decode(serial_bn)
116  .decode(data->m_sig_algo_inner)
117  .decode(data->m_issuer_dn)
118  .start_cons(SEQUENCE)
119  .decode(data->m_not_before)
120  .decode(data->m_not_after)
121  .end_cons()
122  .decode(data->m_subject_dn)
123  .get_next(public_key)
124  .decode_optional_string(data->m_v2_issuer_key_id, BIT_STRING, 1)
125  .decode_optional_string(data->m_v2_subject_key_id, BIT_STRING, 2)
126  .get_next(v3_exts_data)
127  .verify_end("TBSCertificate has extra data after extensions block");
128 
129  if(data->m_version > 2)
130  throw Decoding_Error("Unknown X.509 cert version " + std::to_string(data->m_version));
131  if(obj.signature_algorithm() != data->m_sig_algo_inner)
132  throw Decoding_Error("X.509 Certificate had differing algorithm identifers in inner and outer ID fields");
133 
134  public_key.assert_is_a(SEQUENCE, CONSTRUCTED, "X.509 certificate public key");
135 
136  // crude method to save the serial's sign; will get lost during decoding, otherwise
137  data->m_serial_negative = serial_bn.is_negative();
138 
139  // for general sanity convert wire version (0 based) to standards version (v1 .. v3)
140  data->m_version += 1;
141 
142  data->m_serial = BigInt::encode(serial_bn);
143  data->m_subject_dn_bits = ASN1::put_in_sequence(data->m_subject_dn.get_bits());
144  data->m_issuer_dn_bits = ASN1::put_in_sequence(data->m_issuer_dn.get_bits());
145 
146  // validate_public_key_params(public_key.value);
147  AlgorithmIdentifier public_key_alg_id;
148  BER_Decoder(public_key).decode(public_key_alg_id).discard_remaining();
149 
150  const std::vector<std::string> public_key_info =
151  split_on(OIDS::oid2str_or_empty(public_key_alg_id.get_oid()), '/');
152 
153  if(!public_key_info.empty() && public_key_info[0] == "RSA")
154  {
155  // RFC4055: If PublicKeyAlgo = PSS or OAEP: limit the use of the public key exclusively to either RSASSA - PSS or RSAES - OAEP
156  if(public_key_info.size() >= 2)
157  {
158  if(public_key_info[1] == "EMSA4")
159  {
160  /*
161  When the RSA private key owner wishes to limit the use of the public
162  key exclusively to RSASSA-PSS, then the id-RSASSA-PSS object
163  identifier MUST be used in the algorithm field within the subject
164  public key information, and, if present, the parameters field MUST
165  contain RSASSA-PSS-params.
166 
167  All parameters in the signature structure algorithm identifier MUST
168  match the parameters in the key structure algorithm identifier
169  except the saltLength field. The saltLength field in the signature parameters
170  MUST be greater or equal to that in the key parameters field.
171 
172  ToDo: Allow salt length to be greater
173  */
174  if(public_key_alg_id != obj.signature_algorithm())
175  {
176  throw Decoding_Error("Algorithm identifier mismatch");
177  }
178  }
179  }
180  else
181  {
182  // oid = rsaEncryption -> parameters field MUST contain NULL
183  if(public_key_alg_id != AlgorithmIdentifier(public_key_alg_id.get_oid(), AlgorithmIdentifier::USE_NULL_PARAM))
184  {
185  throw Decoding_Error("RSA algorithm parameters field MUST contain NULL");
186  }
187  }
188  }
189 
190  data->m_subject_public_key_bits.assign(public_key.bits(), public_key.bits() + public_key.length());
191 
192  data->m_subject_public_key_bits_seq = ASN1::put_in_sequence(data->m_subject_public_key_bits);
193 
194  BER_Decoder(data->m_subject_public_key_bits)
195  .decode(data->m_subject_public_key_algid)
196  .decode(data->m_subject_public_key_bitstring, BIT_STRING);
197 
198  if(v3_exts_data.is_a(3, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)))
199  {
200  // Path validation will reject a v1/v2 cert with v3 extensions
201  BER_Decoder(v3_exts_data).decode(data->m_v3_extensions).verify_end();
202  }
203  else if(v3_exts_data.is_set())
204  {
205  throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.tagging());
206  }
207 
208  // Now cache some fields from the extensions
209  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Key_Usage>())
210  {
211  data->m_key_constraints = ext->get_constraints();
212  }
213  else
214  {
215  data->m_key_constraints = NO_CONSTRAINTS;
216  }
217 
218  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Key_ID>())
219  {
220  data->m_subject_key_id = ext->get_key_id();
221  }
222 
223  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>())
224  {
225  data->m_authority_key_id = ext->get_key_id();
226  }
227 
228  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Name_Constraints>())
229  {
230  data->m_name_constraints = ext->get_name_constraints();
231  }
232 
233  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>())
234  {
235  if(ext->get_is_ca() == true)
236  {
237  if(data->m_key_constraints == NO_CONSTRAINTS ||
238  (data->m_key_constraints & KEY_CERT_SIGN))
239  {
240  data->m_is_ca_certificate = true;
241  data->m_path_len_constraint = ext->get_path_limit();
242  }
243  }
244  }
245 
246  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Issuer_Alternative_Name>())
247  {
248  data->m_issuer_alt_name = ext->get_alt_name();
249  }
250 
251  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>())
252  {
253  data->m_subject_alt_name = ext->get_alt_name();
254  }
255 
256  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Extended_Key_Usage>())
257  {
258  data->m_extended_key_usage = ext->get_oids();
259  }
260 
261  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Certificate_Policies>())
262  {
263  data->m_cert_policies = ext->get_policy_oids();
264  }
265 
266  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>())
267  {
268  data->m_ocsp_responder = ext->ocsp_responder();
269  data->m_ca_issuers = ext->ca_issuers();
270  }
271 
272  if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>())
273  {
274  data->m_crl_distribution_points = ext->crl_distribution_urls();
275  }
276 
277  // Check for self-signed vs self-issued certificates
278  if(data->m_subject_dn == data->m_issuer_dn)
279  {
280  if(data->m_subject_key_id.empty() == false && data->m_authority_key_id.empty() == false)
281  {
282  data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
283  }
284  else
285  {
286  /*
287  If a parse error or unknown algorithm is encountered, default
288  to assuming it is self signed. We have no way of being certain but
289  that is usually the default case (self-issued is rare in practice).
290  */
291  data->m_self_signed = true;
292 
293  try
294  {
295  std::unique_ptr<Public_Key> pub_key(X509::load_key(data->m_subject_public_key_bits_seq));
296 
297  Certificate_Status_Code sig_status = obj.verify_signature(*pub_key);
298 
299  if(sig_status == Certificate_Status_Code::OK ||
301  {
302  data->m_self_signed = true;
303  }
304  else
305  {
306  data->m_self_signed = false;
307  }
308  }
309  catch(...)
310  {
311  // ignore errors here to allow parsing to continue
312  }
313  }
314  }
315 
316  std::unique_ptr<HashFunction> sha1(HashFunction::create("SHA-1"));
317  if(sha1)
318  {
319  sha1->update(data->m_subject_public_key_bitstring);
320  data->m_subject_public_key_bitstring_sha1 = sha1->final_stdvec();
321  // otherwise left as empty, and we will throw if subject_public_key_bitstring_sha1 is called
322  }
323 
324  data->m_subject_ds.add(data->m_subject_dn.contents());
325  data->m_issuer_ds.add(data->m_issuer_dn.contents());
326  data->m_v3_extensions.contents_to(data->m_subject_ds, data->m_issuer_ds);
327 
328  return data;
329  }
330 
331 }
332 
333 /*
334 * Decode the TBSCertificate data
335 */
336 void X509_Certificate::force_decode()
337  {
338  m_data.reset();
339 
340  std::unique_ptr<X509_Certificate_Data> data = parse_x509_cert_body(*this);
341 
342  m_data.reset(data.release());
343  }
344 
345 const X509_Certificate_Data& X509_Certificate::data() const
346  {
347  if(m_data == nullptr)
348  {
349  throw Invalid_State("X509_Certificate uninitialized");
350  }
351  return *m_data.get();
352  }
353 
355  {
356  return static_cast<uint32_t>(data().m_version);
357  }
358 
360  {
361  return data().m_self_signed;
362  }
363 
365  {
366  return data().m_not_before;
367  }
368 
370  {
371  return data().m_not_after;
372  }
373 
375  {
376  return data().m_subject_public_key_algid;
377  }
378 
379 const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const
380  {
381  return data().m_v2_issuer_key_id;
382  }
383 
384 const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const
385  {
386  return data().m_v2_subject_key_id;
387  }
388 
389 const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const
390  {
391  return data().m_subject_public_key_bits;
392  }
393 
394 const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const
395  {
396  return data().m_subject_public_key_bits_seq;
397  }
398 
399 const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const
400  {
401  return data().m_subject_public_key_bitstring;
402  }
403 
404 const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const
405  {
406  if(data().m_subject_public_key_bitstring_sha1.empty())
407  throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");
408 
409  return data().m_subject_public_key_bitstring_sha1;
410  }
411 
412 const std::vector<uint8_t>& X509_Certificate::authority_key_id() const
413  {
414  return data().m_authority_key_id;
415  }
416 
417 const std::vector<uint8_t>& X509_Certificate::subject_key_id() const
418  {
419  return data().m_subject_key_id;
420  }
421 
422 const std::vector<uint8_t>& X509_Certificate::serial_number() const
423  {
424  return data().m_serial;
425  }
426 
428  {
429  return data().m_serial_negative;
430  }
431 
432 
434  {
435  return data().m_issuer_dn;
436  }
437 
439  {
440  return data().m_subject_dn;
441  }
442 
443 const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const
444  {
445  return data().m_issuer_dn_bits;
446  }
447 
448 const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const
449  {
450  return data().m_subject_dn_bits;
451  }
452 
454  {
455  if(data().m_version < 3 && data().m_self_signed)
456  return true;
457 
458  return data().m_is_ca_certificate;
459  }
460 
462  {
463  if(data().m_version < 3 && data().m_self_signed)
464  return 32; // in theory infinite, but this is more than enough
465 
466  return static_cast<uint32_t>(data().m_path_len_constraint);
467  }
468 
470  {
471  return data().m_key_constraints;
472  }
473 
474 const std::vector<OID>& X509_Certificate::extended_key_usage() const
475  {
476  return data().m_extended_key_usage;
477  }
478 
479 const std::vector<OID>& X509_Certificate::certificate_policy_oids() const
480  {
481  return data().m_cert_policies;
482  }
483 
485  {
486  return data().m_name_constraints;
487  }
488 
490  {
491  return data().m_v3_extensions;
492  }
493 
495  {
496  if(constraints() == NO_CONSTRAINTS)
497  return true;
498  return ((constraints() & usage) == usage);
499  }
500 
501 bool X509_Certificate::allowed_extended_usage(const std::string& usage) const
502  {
504  }
505 
507  {
508  const std::vector<OID>& ex = extended_key_usage();
509  if(ex.empty())
510  return true;
511 
512  if(std::find(ex.begin(), ex.end(), usage) != ex.end())
513  return true;
514 
515  return false;
516  }
517 
519  {
520  // These follow suggestions in RFC 5280 4.2.1.12
521 
522  switch(usage)
523  {
525  return true;
526 
529 
532 
535 
537  return is_CA_cert();
538 
541  }
542 
543  return false;
544  }
545 
547  {
548  if(this->constraints() == NO_CONSTRAINTS)
549  {
550  return false;
551  }
552 
553  return ((this->constraints() & constraints) != 0);
554  }
555 
556 bool X509_Certificate::has_ex_constraint(const std::string& ex_constraint) const
557  {
558  return has_ex_constraint(OID::from_string(ex_constraint));
559  }
560 
561 bool X509_Certificate::has_ex_constraint(const OID& usage) const
562  {
563  const std::vector<OID>& ex = extended_key_usage();
564  return (std::find(ex.begin(), ex.end(), usage) != ex.end());
565  }
566 
567 /*
568 * Return if a certificate extension is marked critical
569 */
570 bool X509_Certificate::is_critical(const std::string& ex_name) const
571  {
573  }
574 
576  {
577  return data().m_ocsp_responder;
578  }
579 
580 std::vector<std::string> X509_Certificate::ca_issuers() const
581  {
582  return data().m_ca_issuers;
583  }
584 
586  {
587  // just returns the first (arbitrarily)
588  if(data().m_crl_distribution_points.size() > 0)
589  return data().m_crl_distribution_points[0];
590  return "";
591  }
592 
594  {
595  return data().m_subject_alt_name;
596  }
597 
599  {
600  return data().m_issuer_alt_name;
601  }
602 
603 /*
604 * Return information about the subject
605 */
606 std::vector<std::string>
607 X509_Certificate::subject_info(const std::string& req) const
608  {
609  if(req == "Email")
610  return this->subject_info("RFC822");
611 
612  if(subject_dn().has_field(req))
613  return subject_dn().get_attribute(req);
614 
615  if(subject_alt_name().has_field(req))
616  return subject_alt_name().get_attribute(req);
617 
618  // These will be removed later:
619  if(req == "X509.Certificate.v2.key_id")
620  return {hex_encode(this->v2_subject_key_id())};
621  if(req == "X509v3.SubjectKeyIdentifier")
622  return {hex_encode(this->subject_key_id())};
623  if(req == "X509.Certificate.dn_bits")
624  return {hex_encode(this->raw_subject_dn())};
625  if(req == "X509.Certificate.start")
626  return {not_before().to_string()};
627  if(req == "X509.Certificate.end")
628  return {not_after().to_string()};
629 
630  if(req == "X509.Certificate.version")
631  return {std::to_string(x509_version())};
632  if(req == "X509.Certificate.serial")
633  return {hex_encode(serial_number())};
634 
635  return data().m_subject_ds.get(req);
636  }
637 
638 /*
639 * Return information about the issuer
640 */
641 std::vector<std::string>
642 X509_Certificate::issuer_info(const std::string& req) const
643  {
644  if(issuer_dn().has_field(req))
645  return issuer_dn().get_attribute(req);
646 
647  if(issuer_alt_name().has_field(req))
648  return issuer_alt_name().get_attribute(req);
649 
650  // These will be removed later:
651  if(req == "X509.Certificate.v2.key_id")
652  return {hex_encode(this->v2_issuer_key_id())};
653  if(req == "X509v3.AuthorityKeyIdentifier")
654  return {hex_encode(this->authority_key_id())};
655  if(req == "X509.Certificate.dn_bits")
656  return {hex_encode(this->raw_issuer_dn())};
657 
658  return data().m_issuer_ds.get(req);
659  }
660 
661 /*
662 * Return the public key in this certificate
663 */
664 std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const
665  {
666  try
667  {
668  return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
669  }
670  catch(std::exception& e)
671  {
672  throw Decoding_Error("X509_Certificate::load_subject_public_key", e);
673  }
674  }
675 
676 std::vector<uint8_t> X509_Certificate::raw_issuer_dn_sha256() const
677  {
678  std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw("SHA-256"));
679  hash->update(raw_issuer_dn());
680  return hash->final_stdvec();
681  }
682 
683 std::vector<uint8_t> X509_Certificate::raw_subject_dn_sha256() const
684  {
685  std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-256"));
686  hash->update(raw_subject_dn());
687  return hash->final_stdvec();
688  }
689 
690 namespace {
691 
692 /*
693 * Lookup each OID in the vector
694 */
695 std::vector<std::string> lookup_oids(const std::vector<OID>& oids)
696  {
697  std::vector<std::string> out;
698 
699  for(const OID& oid : oids)
700  {
701  out.push_back(oid.to_formatted_string());
702  }
703  return out;
704  }
705 
706 }
707 
708 /*
709 * Return the list of extended key usage OIDs
710 */
711 std::vector<std::string> X509_Certificate::ex_constraints() const
712  {
713  return lookup_oids(extended_key_usage());
714  }
715 
716 /*
717 * Return the list of certificate policies
718 */
719 std::vector<std::string> X509_Certificate::policies() const
720  {
721  return lookup_oids(certificate_policy_oids());
722  }
723 
724 std::string X509_Certificate::fingerprint(const std::string& hash_name) const
725  {
726  return create_hex_fingerprint(this->BER_encode(), hash_name);
727  }
728 
729 bool X509_Certificate::matches_dns_name(const std::string& name) const
730  {
731  if(name.empty())
732  return false;
733 
734  std::vector<std::string> issued_names = subject_info("DNS");
735 
736  // Fall back to CN only if no DNS names are set (RFC 6125 sec 6.4.4)
737  if(issued_names.empty())
738  issued_names = subject_info("Name");
739 
740  for(size_t i = 0; i != issued_names.size(); ++i)
741  {
742  if(host_wildcard_match(issued_names[i], name))
743  return true;
744  }
745 
746  return false;
747  }
748 
749 /*
750 * Compare two certificates for equality
751 */
753  {
754  return (this->signature() == other.signature() &&
755  this->signature_algorithm() == other.signature_algorithm() &&
756  this->signed_body() == other.signed_body());
757  }
758 
760  {
761  /* If signature values are not equal, sort by lexicographic ordering of that */
762  if(this->signature() != other.signature())
763  {
764  return (this->signature() < other.signature());
765  }
766 
767  // Then compare the signed contents
768  return this->signed_body() < other.signed_body();
769  }
770 
771 /*
772 * X.509 Certificate Comparison
773 */
774 bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
775  {
776  return !(cert1 == cert2);
777  }
778 
779 std::string X509_Certificate::to_string() const
780  {
781  std::ostringstream out;
782 
783  out << "Version: " << this->x509_version() << "\n";
784  out << "Subject: " << subject_dn() << "\n";
785  out << "Issuer: " << issuer_dn() << "\n";
786  out << "Issued: " << this->not_before().readable_string() << "\n";
787  out << "Expires: " << this->not_after().readable_string() << "\n";
788 
789  out << "Constraints:\n";
791  if(constraints == NO_CONSTRAINTS)
792  out << " None\n";
793  else
794  {
796  out << " Digital Signature\n";
798  out << " Non-Repudiation\n";
800  out << " Key Encipherment\n";
802  out << " Data Encipherment\n";
804  out << " Key Agreement\n";
806  out << " Cert Sign\n";
807  if(constraints & CRL_SIGN)
808  out << " CRL Sign\n";
810  out << " Encipher Only\n";
812  out << " Decipher Only\n";
813  }
814 
815  const std::vector<OID>& policies = this->certificate_policy_oids();
816  if(!policies.empty())
817  {
818  out << "Policies: " << "\n";
819  for(auto oid : policies)
820  out << " " << oid.to_string() << "\n";
821  }
822 
823  const std::vector<OID>& ex_constraints = this->extended_key_usage();
824  if(!ex_constraints.empty())
825  {
826  out << "Extended Constraints:\n";
827  for(auto&& oid : ex_constraints)
828  {
829  out << " " << oid.to_formatted_string() << "\n";
830  }
831  }
832 
834 
835  if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty())
836  {
837  out << "Name Constraints:\n";
838 
839  if(!name_constraints.permitted().empty())
840  {
841  out << " Permit";
842  for(auto st: name_constraints.permitted())
843  {
844  out << " " << st.base();
845  }
846  out << "\n";
847  }
848 
849  if(!name_constraints.excluded().empty())
850  {
851  out << " Exclude";
852  for(auto st: name_constraints.excluded())
853  {
854  out << " " << st.base();
855  }
856  out << "\n";
857  }
858  }
859 
860  if(!ocsp_responder().empty())
861  out << "OCSP responder " << ocsp_responder() << "\n";
862 
863  const std::vector<std::string> ca_issuers = this->ca_issuers();
864  if(!ca_issuers.empty())
865  {
866  out << "CA Issuers:\n";
867  for(size_t i = 0; i != ca_issuers.size(); i++)
868  out << " URI: " << ca_issuers[i] << "\n";
869  }
870 
871  if(!crl_distribution_point().empty())
872  out << "CRL " << crl_distribution_point() << "\n";
873 
874  out << "Signature algorithm: " << this->signature_algorithm().get_oid().to_formatted_string() << "\n";
875 
876  out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
877 
878  if(this->authority_key_id().size())
879  out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
880 
881  if(this->subject_key_id().size())
882  out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
883 
884  try
885  {
886  std::unique_ptr<Public_Key> pubkey(this->subject_public_key());
887  out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
888  out << X509::PEM_encode(*pubkey);
889  }
890  catch(Decoding_Error&)
891  {
892  const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
893  out << "Failed to decode key with oid " << alg_id.get_oid().to_string() << "\n";
894  }
895 
896  return out.str();
897  }
898 
899 }
bool allowed_usage(Key_Constraints usage) const
Definition: x509cert.cpp:494
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition: alg_id.cpp:89
std::vector< std::string > ex_constraints() const
Definition: x509cert.cpp:711
bool is_critical(const std::string &ex_name) const
Definition: x509cert.cpp:570
bool is_self_signed() const
Definition: x509cert.cpp:359
std::vector< uint8_t > raw_issuer_dn_sha256() const
Definition: x509cert.cpp:676
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:48
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:344
const std::vector< uint8_t > & raw_subject_dn() const
Definition: x509cert.cpp:448
std::string PEM_encode(const Public_Key &key)
Definition: x509_key.cpp:28
const std::vector< uint8_t > & subject_public_key_bits() const
Definition: x509cert.cpp:389
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:148
std::string crl_distribution_point() const
Definition: x509cert.cpp:585
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:763
BOTAN_UNSTABLE_API std::string oid2str_or_empty(const OID &oid)
Definition: oids.cpp:111
std::vector< std::string > issuer_info(const std::string &name) const
Definition: x509cert.cpp:642
std::vector< uint8_t > BER_encode() const
Definition: asn1_obj.cpp:16
Public_Key * subject_public_key() const
Definition: x509cert.h:50
const std::vector< OID > & certificate_policy_oids() const
Definition: x509cert.cpp:479
bool critical_extension_set(const OID &oid) const
Definition: x509_ext.cpp:182
const std::vector< GeneralSubtree > & excluded() const
const std::vector< uint8_t > & authority_key_id() const
Definition: x509cert.cpp:412
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
ASN1_Tag
Definition: asn1_obj.h:23
std::string to_string() const
Definition: x509cert.cpp:779
bool matches_dns_name(const std::string &name) const
Definition: x509cert.cpp:729
const std::vector< uint8_t > & subject_key_id() const
Definition: x509cert.cpp:417
std::string ocsp_responder() const
Definition: x509cert.cpp:575
Key_Constraints constraints() const
Definition: x509cert.cpp:469
bool operator<(const X509_Certificate &other) const
Definition: x509cert.cpp:759
const AlternativeName & issuer_alt_name() const
Definition: x509cert.cpp:598
bool is_CA_cert() const
Definition: x509cert.cpp:453
std::string to_string() const
Definition: asn1_oid.cpp:98
bool host_wildcard_match(const std::string &issued_, const std::string &host_)
Definition: parsing.cpp:342
bool has_ex_constraint(const std::string &ex_constraint) const
Definition: x509cert.cpp:556
bool has_constraints(Key_Constraints constraints) const
Definition: x509cert.cpp:546
uint32_t x509_version() const
Definition: x509cert.cpp:354
const std::vector< uint8_t > & subject_public_key_info() const
Definition: x509cert.cpp:394
std::string name
std::vector< std::string > get_attribute(const std::string &attr) const
Definition: x509_dn.cpp:109
const X509_DN & subject_dn() const
Definition: x509cert.cpp:438
const std::vector< uint8_t > & signature() const
Definition: x509_obj.h:38
const X509_Time & not_after() const
Definition: x509cert.cpp:369
const AlgorithmIdentifier & subject_public_key_algo() const
Definition: x509cert.cpp:374
bool allowed_extended_usage(const std::string &usage) const
Definition: x509cert.cpp:501
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition: x509cert.cpp:404
std::vector< std::string > get_attribute(const std::string &attr) const
bool is_serial_negative() const
Definition: x509cert.cpp:427
const std::vector< GeneralSubtree > & permitted() const
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
Definition: asn1_time.cpp:93
const Extensions & v3_extensions() const
Definition: x509cert.cpp:489
uint32_t path_limit() const
Definition: x509cert.cpp:461
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:106
std::vector< std::string > policies() const
Definition: x509cert.cpp:719
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:43
const std::vector< OID > & extended_key_usage() const
Definition: x509cert.cpp:474
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:433
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
std::string fingerprint(const std::string &hash_name="SHA-1") const
Definition: x509cert.cpp:724
Definition: alg_id.cpp:13
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition: x509cert.cpp:399
std::string to_string() const
Return an internal string representation of the time.
Definition: asn1_time.cpp:53
std::vector< std::string > ca_issuers() const
Definition: x509cert.cpp:580
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:195
std::string create_hex_fingerprint(const uint8_t bits[], size_t bits_len, const std::string &hash_name)
Definition: pk_keys.cpp:17
std::string to_formatted_string() const
Definition: asn1_oid.cpp:110
const X509_Time & not_before() const
Definition: x509cert.cpp:364
const OID & get_oid() const
Definition: alg_id.h:37
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition: x509cert.cpp:664
const NameConstraints & name_constraints() const
Definition: x509cert.cpp:484
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:422
bool operator==(const X509_Certificate &other) const
Definition: x509cert.cpp:752
Certificate_Status_Code
Definition: cert_status.h:19
const std::vector< uint8_t > & v2_subject_key_id() const
Definition: x509cert.cpp:384
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition: x509cert.cpp:379
std::vector< std::string > subject_info(const std::string &name) const
Definition: x509cert.cpp:607
MechanismType hash
Usage_Type
Definition: x509cert.h:25
const AlternativeName & subject_alt_name() const
Definition: x509cert.cpp:593
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37
const std::vector< uint8_t > & raw_issuer_dn() const
Definition: x509cert.cpp:443
Name Constraints.
std::vector< uint8_t > raw_subject_dn_sha256() const
Definition: x509cert.cpp:683
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:62