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