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