Botan  2.11.0
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  std::vector<std::string> public_key_info =
151  split_on(OIDS::oid2str(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  {
503  return allowed_extended_usage(OIDS::str2oid(usage));
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  }
539 
540  return false;
541  }
542 
544  {
545  if(this->constraints() == NO_CONSTRAINTS)
546  {
547  return false;
548  }
549 
550  return ((this->constraints() & constraints) != 0);
551  }
552 
553 bool X509_Certificate::has_ex_constraint(const std::string& ex_constraint) const
554  {
555  return has_ex_constraint(OIDS::str2oid(ex_constraint));
556  }
557 
558 bool X509_Certificate::has_ex_constraint(const OID& usage) const
559  {
560  const std::vector<OID>& ex = extended_key_usage();
561  return (std::find(ex.begin(), ex.end(), usage) != ex.end());
562  }
563 
564 /*
565 * Return if a certificate extension is marked critical
566 */
567 bool X509_Certificate::is_critical(const std::string& ex_name) const
568  {
570  }
571 
573  {
574  return data().m_ocsp_responder;
575  }
576 
577 std::vector<std::string> X509_Certificate::ca_issuers() const
578  {
579  return data().m_ca_issuers;
580  }
581 
583  {
584  // just returns the first (arbitrarily)
585  if(data().m_crl_distribution_points.size() > 0)
586  return data().m_crl_distribution_points[0];
587  return "";
588  }
589 
591  {
592  return data().m_subject_alt_name;
593  }
594 
596  {
597  return data().m_issuer_alt_name;
598  }
599 
600 /*
601 * Return information about the subject
602 */
603 std::vector<std::string>
604 X509_Certificate::subject_info(const std::string& req) const
605  {
606  if(req == "Email")
607  return this->subject_info("RFC822");
608 
609  if(subject_dn().has_field(req))
610  return subject_dn().get_attribute(req);
611 
612  if(subject_alt_name().has_field(req))
613  return subject_alt_name().get_attribute(req);
614 
615  // These will be removed later:
616  if(req == "X509.Certificate.v2.key_id")
617  return {hex_encode(this->v2_subject_key_id())};
618  if(req == "X509v3.SubjectKeyIdentifier")
619  return {hex_encode(this->subject_key_id())};
620  if(req == "X509.Certificate.dn_bits")
621  return {hex_encode(this->raw_subject_dn())};
622  if(req == "X509.Certificate.start")
623  return {not_before().to_string()};
624  if(req == "X509.Certificate.end")
625  return {not_after().to_string()};
626 
627  if(req == "X509.Certificate.version")
628  return {std::to_string(x509_version())};
629  if(req == "X509.Certificate.serial")
630  return {hex_encode(serial_number())};
631 
632  return data().m_subject_ds.get(req);
633  }
634 
635 /*
636 * Return information about the issuer
637 */
638 std::vector<std::string>
639 X509_Certificate::issuer_info(const std::string& req) const
640  {
641  if(issuer_dn().has_field(req))
642  return issuer_dn().get_attribute(req);
643 
644  if(issuer_alt_name().has_field(req))
645  return issuer_alt_name().get_attribute(req);
646 
647  // These will be removed later:
648  if(req == "X509.Certificate.v2.key_id")
649  return {hex_encode(this->v2_issuer_key_id())};
650  if(req == "X509v3.AuthorityKeyIdentifier")
651  return {hex_encode(this->authority_key_id())};
652  if(req == "X509.Certificate.dn_bits")
653  return {hex_encode(this->raw_issuer_dn())};
654 
655  return data().m_issuer_ds.get(req);
656  }
657 
658 /*
659 * Return the public key in this certificate
660 */
661 std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const
662  {
663  try
664  {
665  return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
666  }
667  catch(std::exception& e)
668  {
669  throw Decoding_Error("X509_Certificate::load_subject_public_key", e);
670  }
671  }
672 
673 std::vector<uint8_t> X509_Certificate::raw_issuer_dn_sha256() const
674  {
675  std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw("SHA-256"));
676  hash->update(raw_issuer_dn());
677  return hash->final_stdvec();
678  }
679 
680 std::vector<uint8_t> X509_Certificate::raw_subject_dn_sha256() const
681  {
682  std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-256"));
683  hash->update(raw_subject_dn());
684  return hash->final_stdvec();
685  }
686 
687 namespace {
688 
689 /*
690 * Lookup each OID in the vector
691 */
692 std::vector<std::string> lookup_oids(const std::vector<OID>& oids)
693  {
694  std::vector<std::string> out;
695 
696  for(const OID& oid : oids)
697  {
698  out.push_back(OIDS::oid2str(oid));
699  }
700  return out;
701  }
702 
703 }
704 
705 /*
706 * Return the list of extended key usage OIDs
707 */
708 std::vector<std::string> X509_Certificate::ex_constraints() const
709  {
710  return lookup_oids(extended_key_usage());
711  }
712 
713 /*
714 * Return the list of certificate policies
715 */
716 std::vector<std::string> X509_Certificate::policies() const
717  {
718  return lookup_oids(certificate_policy_oids());
719  }
720 
721 std::string X509_Certificate::fingerprint(const std::string& hash_name) const
722  {
723  return create_hex_fingerprint(this->BER_encode(), hash_name);
724  }
725 
726 bool X509_Certificate::matches_dns_name(const std::string& name) const
727  {
728  if(name.empty())
729  return false;
730 
731  std::vector<std::string> issued_names = subject_info("DNS");
732 
733  // Fall back to CN only if no DNS names are set (RFC 6125 sec 6.4.4)
734  if(issued_names.empty())
735  issued_names = subject_info("Name");
736 
737  for(size_t i = 0; i != issued_names.size(); ++i)
738  {
739  if(host_wildcard_match(issued_names[i], name))
740  return true;
741  }
742 
743  return false;
744  }
745 
746 /*
747 * Compare two certificates for equality
748 */
750  {
751  return (this->signature() == other.signature() &&
752  this->signature_algorithm() == other.signature_algorithm() &&
753  this->signed_body() == other.signed_body());
754  }
755 
757  {
758  /* If signature values are not equal, sort by lexicographic ordering of that */
759  if(this->signature() != other.signature())
760  {
761  return (this->signature() < other.signature());
762  }
763 
764  // Then compare the signed contents
765  return this->signed_body() < other.signed_body();
766  }
767 
768 /*
769 * X.509 Certificate Comparison
770 */
771 bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
772  {
773  return !(cert1 == cert2);
774  }
775 
776 std::string X509_Certificate::to_string() const
777  {
778  std::ostringstream out;
779 
780  out << "Version: " << this->x509_version() << "\n";
781  out << "Subject: " << subject_dn() << "\n";
782  out << "Issuer: " << issuer_dn() << "\n";
783  out << "Issued: " << this->not_before().readable_string() << "\n";
784  out << "Expires: " << this->not_after().readable_string() << "\n";
785 
786  out << "Constraints:\n";
788  if(constraints == NO_CONSTRAINTS)
789  out << " None\n";
790  else
791  {
793  out << " Digital Signature\n";
795  out << " Non-Repudiation\n";
797  out << " Key Encipherment\n";
799  out << " Data Encipherment\n";
801  out << " Key Agreement\n";
803  out << " Cert Sign\n";
804  if(constraints & CRL_SIGN)
805  out << " CRL Sign\n";
807  out << " Encipher Only\n";
809  out << " Decipher Only\n";
810  }
811 
812  const std::vector<OID>& policies = this->certificate_policy_oids();
813  if(!policies.empty())
814  {
815  out << "Policies: " << "\n";
816  for(auto oid : policies)
817  out << " " << oid.to_string() << "\n";
818  }
819 
820  const std::vector<OID>& ex_constraints = this->extended_key_usage();
821  if(!ex_constraints.empty())
822  {
823  out << "Extended Constraints:\n";
824  for(auto&& oid : ex_constraints)
825  {
826  const std::string oid_str = OIDS::oid2str(oid);
827 
828  if(oid_str.empty())
829  out << " " << oid.to_string() << "\n";
830  else
831  out << " " << oid_str << "\n";
832  }
833  }
834 
836 
837  if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty())
838  {
839  out << "Name Constraints:\n";
840 
841  if(!name_constraints.permitted().empty())
842  {
843  out << " Permit";
844  for(auto st: name_constraints.permitted())
845  {
846  out << " " << st.base();
847  }
848  out << "\n";
849  }
850 
851  if(!name_constraints.excluded().empty())
852  {
853  out << " Exclude";
854  for(auto st: name_constraints.excluded())
855  {
856  out << " " << st.base();
857  }
858  out << "\n";
859  }
860  }
861 
862  if(!ocsp_responder().empty())
863  out << "OCSP responder " << ocsp_responder() << "\n";
864 
865  const std::vector<std::string> ca_issuers = this->ca_issuers();
866  if(!ca_issuers.empty())
867  {
868  out << "CA Issuers:\n";
869  for(size_t i = 0; i != ca_issuers.size(); i++)
870  out << " URI: " << ca_issuers[i] << "\n";
871  }
872 
873  if(!crl_distribution_point().empty())
874  out << "CRL " << crl_distribution_point() << "\n";
875 
876  out << "Signature algorithm: " <<
877  OIDS::oid2str(this->signature_algorithm().get_oid()) << "\n";
878 
879  out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
880 
881  if(this->authority_key_id().size())
882  out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
883 
884  if(this->subject_key_id().size())
885  out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
886 
887  try
888  {
889  std::unique_ptr<Public_Key> pubkey(this->subject_public_key());
890  out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
891  out << X509::PEM_encode(*pubkey);
892  }
893  catch(Decoding_Error&)
894  {
895  const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
896  out << "Failed to decode key with oid " << alg_id.get_oid().to_string() << "\n";
897  }
898 
899  return out.str();
900  }
901 
902 }
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:90
std::vector< std::string > ex_constraints() const
Definition: x509cert.cpp:708
bool is_critical(const std::string &ex_name) const
Definition: x509cert.cpp:567
bool is_self_signed() const
Definition: x509cert.cpp:359
std::vector< uint8_t > raw_issuer_dn_sha256() const
Definition: x509cert.cpp:673
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:359
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:144
std::string crl_distribution_point() const
Definition: x509cert.cpp:582
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:768
std::vector< std::string > issuer_info(const std::string &name) const
Definition: x509cert.cpp:639
std::vector< uint8_t > BER_encode() const
Definition: asn1_obj.cpp:16
Public_Key * subject_public_key() const
Definition: x509cert.h:49
const std::vector< OID > & certificate_policy_oids() const
Definition: x509cert.cpp:479
bool critical_extension_set(const OID &oid) const
Definition: x509_ext.cpp:166
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:776
bool matches_dns_name(const std::string &name) const
Definition: x509cert.cpp:726
const std::vector< uint8_t > & subject_key_id() const
Definition: x509cert.cpp:417
std::string ocsp_responder() const
Definition: x509cert.cpp:572
Key_Constraints constraints() const
Definition: x509cert.cpp:469
bool operator<(const X509_Certificate &other) const
Definition: x509cert.cpp:756
const AlternativeName & issuer_alt_name() const
Definition: x509cert.cpp:595
bool is_CA_cert() const
Definition: x509cert.cpp:453
std::string to_string() const
Definition: asn1_oid.cpp:50
OID str2oid(const std::string &name)
Definition: oids.h:53
bool host_wildcard_match(const std::string &issued_, const std::string &host_)
Definition: parsing.cpp:359
bool has_ex_constraint(const std::string &ex_constraint) const
Definition: x509cert.cpp:553
bool has_constraints(Key_Constraints constraints) const
Definition: x509cert.cpp:543
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:110
std::vector< std::string > policies() const
Definition: x509cert.cpp:716
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:53
std::string fingerprint(const std::string &hash_name="SHA-1") const
Definition: x509cert.cpp:721
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:577
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 oid2str(const OID &oid)
Definition: oids.h:48
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:661
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:749
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:604
MechanismType hash
Usage_Type
Definition: x509cert.h:25
const AlternativeName & subject_alt_name() const
Definition: x509cert.cpp:590
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:680