Botan 3.5.0
Crypto and TLS for C&
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
11#include <botan/ber_dec.h>
12#include <botan/bigint.h>
13#include <botan/hash.h>
14#include <botan/hex.h>
15#include <botan/pk_keys.h>
16#include <botan/x509_ext.h>
17#include <botan/x509_key.h>
18#include <botan/internal/parsing.h>
19#include <algorithm>
20#include <sstream>
21
22namespace Botan {
23
24struct X509_Certificate_Data {
25 std::vector<uint8_t> m_serial;
26 AlgorithmIdentifier m_sig_algo_inner;
27 X509_DN m_issuer_dn;
28 X509_DN m_subject_dn;
29 std::vector<uint8_t> m_issuer_dn_bits;
30 std::vector<uint8_t> m_subject_dn_bits;
31 X509_Time m_not_before;
32 X509_Time m_not_after;
33 std::vector<uint8_t> m_subject_public_key_bits;
34 std::vector<uint8_t> m_subject_public_key_bits_seq;
35 std::vector<uint8_t> m_subject_public_key_bitstring;
36 std::vector<uint8_t> m_subject_public_key_bitstring_sha1;
37 AlgorithmIdentifier m_subject_public_key_algid;
38
39 std::vector<uint8_t> m_v2_issuer_key_id;
40 std::vector<uint8_t> m_v2_subject_key_id;
41 Extensions m_v3_extensions;
42
43 std::vector<OID> m_extended_key_usage;
44 std::vector<uint8_t> m_authority_key_id;
45 std::vector<uint8_t> m_subject_key_id;
46 std::vector<OID> m_cert_policies;
47
48 std::vector<std::string> m_crl_distribution_points;
49 std::string m_ocsp_responder;
50 std::vector<std::string> m_ca_issuers;
51
52 std::vector<uint8_t> m_issuer_dn_bits_sha256;
53 std::vector<uint8_t> m_subject_dn_bits_sha256;
54
55 std::string m_fingerprint_sha1;
56 std::string m_fingerprint_sha256;
57
58 AlternativeName m_subject_alt_name;
59 AlternativeName m_issuer_alt_name;
60 NameConstraints m_name_constraints;
61
62 size_t m_version = 0;
63 size_t m_path_len_constraint = 0;
64 Key_Constraints m_key_constraints;
65 bool m_self_signed = false;
66 bool m_is_ca_certificate = false;
67 bool m_serial_negative = false;
68 bool m_subject_alt_name_exists = false;
69};
70
71std::string X509_Certificate::PEM_label() const {
72 return "CERTIFICATE";
73}
74
75std::vector<std::string> X509_Certificate::alternate_PEM_labels() const {
76 return {"X509 CERTIFICATE"};
77}
78
82
83X509_Certificate::X509_Certificate(const std::vector<uint8_t>& vec) {
84 DataSource_Memory src(vec.data(), vec.size());
85 load_data(src);
86}
87
88X509_Certificate::X509_Certificate(const uint8_t data[], size_t len) {
89 DataSource_Memory src(data, len);
90 load_data(src);
91}
92
93#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
94X509_Certificate::X509_Certificate(std::string_view fsname) {
95 DataSource_Stream src(fsname, true);
96 load_data(src);
97}
98#endif
99
100namespace {
101
102std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& obj) {
103 auto data = std::make_unique<X509_Certificate_Data>();
104
105 BigInt serial_bn;
106 BER_Object public_key;
107 BER_Object v3_exts_data;
108
109 BER_Decoder(obj.signed_body())
110 .decode_optional(data->m_version, ASN1_Type(0), ASN1_Class::Constructed | ASN1_Class::ContextSpecific)
111 .decode(serial_bn)
112 .decode(data->m_sig_algo_inner)
113 .decode(data->m_issuer_dn)
114 .start_sequence()
115 .decode(data->m_not_before)
116 .decode(data->m_not_after)
117 .end_cons()
118 .decode(data->m_subject_dn)
119 .get_next(public_key)
120 .decode_optional_string(data->m_v2_issuer_key_id, ASN1_Type::BitString, 1)
121 .decode_optional_string(data->m_v2_subject_key_id, ASN1_Type::BitString, 2)
122 .get_next(v3_exts_data)
123 .verify_end("TBSCertificate has extra data after extensions block");
124
125 if(data->m_version > 2) {
126 throw Decoding_Error("Unknown X.509 cert version " + std::to_string(data->m_version));
127 }
128 if(obj.signature_algorithm() != data->m_sig_algo_inner) {
129 throw Decoding_Error("X.509 Certificate had differing algorithm identifers in inner and outer ID fields");
130 }
131
132 public_key.assert_is_a(ASN1_Type::Sequence, ASN1_Class::Constructed, "X.509 certificate public key");
133
134 // for general sanity convert wire version (0 based) to standards version (v1 .. v3)
135 data->m_version += 1;
136
137 data->m_serial = serial_bn.serialize();
138 // crude method to save the serial's sign; will get lost during decoding, otherwise
139 data->m_serial_negative = serial_bn.is_negative();
140 data->m_subject_dn_bits = ASN1::put_in_sequence(data->m_subject_dn.get_bits());
141 data->m_issuer_dn_bits = ASN1::put_in_sequence(data->m_issuer_dn.get_bits());
142
143 data->m_subject_public_key_bits.assign(public_key.bits(), public_key.bits() + public_key.length());
144
145 data->m_subject_public_key_bits_seq = ASN1::put_in_sequence(data->m_subject_public_key_bits);
146
147 BER_Decoder(data->m_subject_public_key_bits)
148 .decode(data->m_subject_public_key_algid)
149 .decode(data->m_subject_public_key_bitstring, ASN1_Type::BitString);
150
151 if(v3_exts_data.is_a(3, ASN1_Class::Constructed | ASN1_Class::ContextSpecific)) {
152 // Path validation will reject a v1/v2 cert with v3 extensions
153 BER_Decoder(v3_exts_data).decode(data->m_v3_extensions).verify_end();
154 } else if(v3_exts_data.is_set()) {
155 throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.tagging());
156 }
157
158 // Now cache some fields from the extensions
159 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Key_Usage>()) {
160 data->m_key_constraints = ext->get_constraints();
161 /*
162 RFC 5280: When the keyUsage extension appears in a certificate,
163 at least one of the bits MUST be set to 1.
164 */
165 if(data->m_key_constraints.empty()) {
166 throw Decoding_Error("Certificate has invalid encoding for KeyUsage");
167 }
168 }
169
170 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Key_ID>()) {
171 data->m_subject_key_id = ext->get_key_id();
172 }
173
174 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>()) {
175 data->m_authority_key_id = ext->get_key_id();
176 }
177
178 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Name_Constraints>()) {
179 data->m_name_constraints = ext->get_name_constraints();
180 }
181
182 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Extended_Key_Usage>()) {
183 data->m_extended_key_usage = ext->object_identifiers();
184 }
185
186 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
187 if(ext->get_is_ca() == true) {
188 /*
189 * RFC 5280 section 4.2.1.3 requires that CAs include KeyUsage in all
190 * intermediate CA certificates they issue. Currently we accept it being
191 * missing, as do most other implementations. But it may be worth
192 * removing this entirely, or alternately adding a warning level
193 * validation failure for it.
194 */
195 const bool allowed_by_ku =
196 data->m_key_constraints.includes(Key_Constraints::KeyCertSign) || data->m_key_constraints.empty();
197
198 /*
199 * If the extended key usages are set then we must restrict the
200 * usage in accordance with it as well.
201 *
202 * RFC 5280 does not define any extended key usages compatible
203 * with certificate signing, but some CAs seem to use serverAuth
204 * or clientAuth here.
205 */
206 const bool allowed_by_ext_ku = [](const std::vector<OID>& ext_ku) -> bool {
207 if(ext_ku.empty()) {
208 return true;
209 }
210
211 const auto server_auth = OID::from_name("PKIX.ServerAuth");
212 const auto client_auth = OID::from_name("PKIX.ClientAuth");
213 const auto ocsp_sign = OID::from_name("PKIX.OCSPSigning");
214
215 for(const auto& oid : ext_ku) {
216 if(oid == server_auth || oid == client_auth || oid == ocsp_sign) {
217 return true;
218 }
219 }
220
221 return false;
222 }(data->m_extended_key_usage);
223
224 if(allowed_by_ku && allowed_by_ext_ku) {
225 data->m_is_ca_certificate = true;
226 data->m_path_len_constraint = ext->get_path_limit();
227 }
228 }
229 }
230
231 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Issuer_Alternative_Name>()) {
232 data->m_issuer_alt_name = ext->get_alt_name();
233 }
234
235 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
236 data->m_subject_alt_name = ext->get_alt_name();
237 }
238
239 // This will be set even if SAN parsing failed entirely eg due to a decoding error
240 // or if the SAN is empty. This is used to guard against using the CN for domain
241 // name checking.
242 const auto san_oid = OID::from_string("X509v3.SubjectAlternativeName");
243 data->m_subject_alt_name_exists = data->m_v3_extensions.extension_set(san_oid);
244
245 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Certificate_Policies>()) {
246 data->m_cert_policies = ext->get_policy_oids();
247 }
248
249 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>()) {
250 data->m_ocsp_responder = ext->ocsp_responder();
251 data->m_ca_issuers = ext->ca_issuers();
252 }
253
254 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>()) {
255 data->m_crl_distribution_points = ext->crl_distribution_urls();
256 }
257
258 // Check for self-signed vs self-issued certificates
259 if(data->m_subject_dn == data->m_issuer_dn) {
260 if(data->m_subject_key_id.empty() == false && data->m_authority_key_id.empty() == false) {
261 data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
262 } else {
263 /*
264 If a parse error or unknown algorithm is encountered, default
265 to assuming it is self signed. We have no way of being certain but
266 that is usually the default case (self-issued is rare in practice).
267 */
268 data->m_self_signed = true;
269
270 try {
271 auto pub_key = X509::load_key(data->m_subject_public_key_bits_seq);
272
273 const auto sig_status = obj.verify_signature(*pub_key);
274
275 if(sig_status.first == Certificate_Status_Code::OK ||
277 data->m_self_signed = true;
278 } else {
279 data->m_self_signed = false;
280 }
281 } catch(...) {
282 // ignore errors here to allow parsing to continue
283 }
284 }
285 }
286
287 const std::vector<uint8_t> full_encoding = obj.BER_encode();
288
289 if(auto sha1 = HashFunction::create("SHA-1")) {
290 sha1->update(data->m_subject_public_key_bitstring);
291 data->m_subject_public_key_bitstring_sha1 = sha1->final_stdvec();
292 // otherwise left as empty, and we will throw if subject_public_key_bitstring_sha1 is called
293
294 data->m_fingerprint_sha1 = create_hex_fingerprint(full_encoding, "SHA-1");
295 }
296
297 if(auto sha256 = HashFunction::create("SHA-256")) {
298 sha256->update(data->m_issuer_dn_bits);
299 data->m_issuer_dn_bits_sha256 = sha256->final_stdvec();
300
301 sha256->update(data->m_subject_dn_bits);
302 data->m_subject_dn_bits_sha256 = sha256->final_stdvec();
303
304 data->m_fingerprint_sha256 = create_hex_fingerprint(full_encoding, "SHA-256");
305 }
306
307 return data;
308}
309
310} // namespace
311
312/*
313* Decode the TBSCertificate data
314*/
315void X509_Certificate::force_decode() {
316 m_data.reset();
317 m_data = parse_x509_cert_body(*this);
318}
319
320const X509_Certificate_Data& X509_Certificate::data() const {
321 if(m_data == nullptr) {
322 throw Invalid_State("X509_Certificate uninitialized");
323 }
324 return *m_data;
325}
326
328 return static_cast<uint32_t>(data().m_version);
329}
330
332 return data().m_self_signed;
333}
334
336 return data().m_not_before;
337}
338
340 return data().m_not_after;
341}
342
344 return data().m_subject_public_key_algid;
345}
346
347const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const {
348 return data().m_v2_issuer_key_id;
349}
350
351const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const {
352 return data().m_v2_subject_key_id;
353}
354
355const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const {
356 return data().m_subject_public_key_bits;
357}
358
359const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const {
360 return data().m_subject_public_key_bits_seq;
361}
362
363const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const {
364 return data().m_subject_public_key_bitstring;
365}
366
367const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const {
368 if(data().m_subject_public_key_bitstring_sha1.empty()) {
369 throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");
370 }
371
372 return data().m_subject_public_key_bitstring_sha1;
373}
374
375const std::vector<uint8_t>& X509_Certificate::authority_key_id() const {
376 return data().m_authority_key_id;
377}
378
379const std::vector<uint8_t>& X509_Certificate::subject_key_id() const {
380 return data().m_subject_key_id;
381}
382
383const std::vector<uint8_t>& X509_Certificate::serial_number() const {
384 return data().m_serial;
385}
386
388 return data().m_serial_negative;
389}
390
392 return data().m_issuer_dn;
393}
394
396 return data().m_subject_dn;
397}
398
399const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const {
400 return data().m_issuer_dn_bits;
401}
402
403const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const {
404 return data().m_subject_dn_bits;
405}
406
408 if(data().m_version < 3 && data().m_self_signed) {
409 return true;
410 }
411
412 return data().m_is_ca_certificate;
413}
414
416 if(data().m_version < 3 && data().m_self_signed) {
417 return 32; // in theory infinite, but this is more than enough
418 }
419
420 return static_cast<uint32_t>(data().m_path_len_constraint);
421}
422
424 return data().m_key_constraints;
425}
426
427const std::vector<OID>& X509_Certificate::extended_key_usage() const {
428 return data().m_extended_key_usage;
429}
430
431const std::vector<OID>& X509_Certificate::certificate_policy_oids() const {
432 return data().m_cert_policies;
433}
434
436 return data().m_name_constraints;
437}
438
440 return data().m_v3_extensions;
441}
442
444 // Unlike allowed_usage, returns false if constraints was not set
445 return constraints().includes(usage);
446}
447
449 if(constraints().empty()) {
450 return true;
451 }
452 return constraints().includes(usage);
453}
454
455bool X509_Certificate::allowed_extended_usage(std::string_view usage) const {
457}
458
460 const std::vector<OID>& ex = extended_key_usage();
461 if(ex.empty()) {
462 return true;
463 }
464
465 if(std::find(ex.begin(), ex.end(), usage) != ex.end()) {
466 return true;
467 }
468
469 return false;
470}
471
501
502bool X509_Certificate::has_ex_constraint(std::string_view ex_constraint) const {
503 return has_ex_constraint(OID::from_string(ex_constraint));
504}
505
506bool X509_Certificate::has_ex_constraint(const OID& usage) const {
507 const std::vector<OID>& ex = extended_key_usage();
508 return (std::find(ex.begin(), ex.end(), usage) != ex.end());
509}
510
511/*
512* Return if a certificate extension is marked critical
513*/
514bool X509_Certificate::is_critical(std::string_view ex_name) const {
516}
517
519 return data().m_ocsp_responder;
520}
521
522std::vector<std::string> X509_Certificate::ca_issuers() const {
523 return data().m_ca_issuers;
524}
525
526std::vector<std::string> X509_Certificate::crl_distribution_points() const {
527 return data().m_crl_distribution_points;
528}
529
531 // just returns the first (arbitrarily)
532 if(!data().m_crl_distribution_points.empty()) {
533 return data().m_crl_distribution_points[0];
534 }
535 return "";
536}
537
539 return data().m_subject_alt_name;
540}
541
543 return data().m_issuer_alt_name;
544}
545
546namespace {
547
548std::vector<std::string> get_cert_user_info(std::string_view req, const X509_DN& dn, const AlternativeName& alt_name) {
549 auto set_to_vector = [](const std::set<std::string>& s) -> std::vector<std::string> { return {s.begin(), s.end()}; };
550
551 if(dn.has_field(req)) {
552 return dn.get_attribute(req);
553 } else if(req == "RFC822" || req == "Email") {
554 return set_to_vector(alt_name.email());
555 } else if(req == "DNS") {
556 return set_to_vector(alt_name.dns());
557 } else if(req == "URI") {
558 return set_to_vector(alt_name.uris());
559 } else if(req == "IP") {
560 std::vector<std::string> ip_str;
561 for(uint32_t ipv4 : alt_name.ipv4_address()) {
562 ip_str.push_back(ipv4_to_string(ipv4));
563 }
564 return ip_str;
565 } else {
566 return {};
567 }
568}
569
570} // namespace
571
572/*
573* Return information about the subject
574*/
575std::vector<std::string> X509_Certificate::subject_info(std::string_view req) const {
576 return get_cert_user_info(req, subject_dn(), subject_alt_name());
577}
578
579/*
580* Return information about the issuer
581*/
582std::vector<std::string> X509_Certificate::issuer_info(std::string_view req) const {
583 return get_cert_user_info(req, issuer_dn(), issuer_alt_name());
584}
585
586/*
587* Return the public key in this certificate
588*/
589std::unique_ptr<Public_Key> X509_Certificate::subject_public_key() const {
590 try {
591 return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
592 } catch(std::exception& e) {
593 throw Decoding_Error("X509_Certificate::subject_public_key", e);
594 }
595}
596
597std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const {
598 return this->subject_public_key();
599}
600
601std::vector<uint8_t> X509_Certificate::raw_issuer_dn_sha256() const {
602 if(data().m_issuer_dn_bits_sha256.empty()) {
603 throw Encoding_Error("X509_Certificate::raw_issuer_dn_sha256 called but SHA-256 disabled in build");
604 }
605 return data().m_issuer_dn_bits_sha256;
606}
607
608std::vector<uint8_t> X509_Certificate::raw_subject_dn_sha256() const {
609 if(data().m_subject_dn_bits_sha256.empty()) {
610 throw Encoding_Error("X509_Certificate::raw_subject_dn_sha256 called but SHA-256 disabled in build");
611 }
612 return data().m_subject_dn_bits_sha256;
613}
614
615std::string X509_Certificate::fingerprint(std::string_view hash_name) const {
616 /*
617 * The SHA-1 and SHA-256 fingerprints are precomputed since these
618 * are the most commonly used. Especially, SHA-256 fingerprints are
619 * used for cycle detection during path construction.
620 *
621 * If SHA-1 or SHA-256 was missing at parsing time the vectors are
622 * left empty in which case we fall back to create_hex_fingerprint
623 * which will throw if the hash is unavailable.
624 */
625 if(hash_name == "SHA-256" && !data().m_fingerprint_sha256.empty()) {
626 return data().m_fingerprint_sha256;
627 } else if(hash_name == "SHA-1" && !data().m_fingerprint_sha1.empty()) {
628 return data().m_fingerprint_sha1;
629 } else {
630 return create_hex_fingerprint(this->BER_encode(), hash_name);
631 }
632}
633
634bool X509_Certificate::matches_dns_name(std::string_view name) const {
635 if(name.empty()) {
636 return false;
637 }
638
639 if(auto req_ipv4 = string_to_ipv4(name)) {
640 const auto& ipv4_names = subject_alt_name().ipv4_address();
641 return ipv4_names.contains(req_ipv4.value());
642 } else {
643 auto issued_names = subject_info("DNS");
644
645 // Fall back to CN only if no SAN is included
646 if(!data().m_subject_alt_name_exists) {
647 issued_names = subject_info("Name");
648 }
649
650 for(const auto& issued_name : issued_names) {
651 if(host_wildcard_match(issued_name, name)) {
652 return true;
653 }
654 }
655 }
656
657 return false;
658}
659
660/*
661* Compare two certificates for equality
662*/
664 return (this->signature() == other.signature() && this->signature_algorithm() == other.signature_algorithm() &&
665 this->signed_body() == other.signed_body());
666}
667
669 /* If signature values are not equal, sort by lexicographic ordering of that */
670 if(this->signature() != other.signature()) {
671 return (this->signature() < other.signature());
672 }
673
674 // Then compare the signed contents
675 return this->signed_body() < other.signed_body();
676}
677
678/*
679* X.509 Certificate Comparison
680*/
681bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) {
682 return !(cert1 == cert2);
683}
684
685std::string X509_Certificate::to_string() const {
686 std::ostringstream out;
687
688 out << "Version: " << this->x509_version() << "\n";
689 out << "Subject: " << subject_dn() << "\n";
690 out << "Issuer: " << issuer_dn() << "\n";
691 out << "Issued: " << this->not_before().readable_string() << "\n";
692 out << "Expires: " << this->not_after().readable_string() << "\n";
693
694 out << "Constraints:\n";
696 if(constraints.empty()) {
697 out << " None\n";
698 } else {
700 out << " Digital Signature\n";
701 }
703 out << " Non-Repudiation\n";
704 }
706 out << " Key Encipherment\n";
707 }
709 out << " Data Encipherment\n";
710 }
712 out << " Key Agreement\n";
713 }
715 out << " Cert Sign\n";
716 }
718 out << " CRL Sign\n";
719 }
721 out << " Encipher Only\n";
722 }
724 out << " Decipher Only\n";
725 }
726 }
727
728 const std::vector<OID>& policies = this->certificate_policy_oids();
729 if(!policies.empty()) {
730 out << "Policies: "
731 << "\n";
732 for(const auto& oid : policies) {
733 out << " " << oid.to_string() << "\n";
734 }
735 }
736
737 const std::vector<OID>& ex_constraints = this->extended_key_usage();
738 if(!ex_constraints.empty()) {
739 out << "Extended Constraints:\n";
740 for(auto&& oid : ex_constraints) {
741 out << " " << oid.to_formatted_string() << "\n";
742 }
743 }
744
746
747 if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty()) {
748 out << "Name Constraints:\n";
749
750 if(!name_constraints.permitted().empty()) {
751 out << " Permit";
752 for(const auto& st : name_constraints.permitted()) {
753 out << " " << st.base();
754 }
755 out << "\n";
756 }
757
758 if(!name_constraints.excluded().empty()) {
759 out << " Exclude";
760 for(const auto& st : name_constraints.excluded()) {
761 out << " " << st.base();
762 }
763 out << "\n";
764 }
765 }
766
767 if(!ocsp_responder().empty()) {
768 out << "OCSP responder " << ocsp_responder() << "\n";
769 }
770
771 const std::vector<std::string> ca_issuers = this->ca_issuers();
772 if(!ca_issuers.empty()) {
773 out << "CA Issuers:\n";
774 for(const auto& ca_issuer : ca_issuers) {
775 out << " URI: " << ca_issuer << "\n";
776 }
777 }
778
779 for(const auto& cdp : crl_distribution_points()) {
780 out << "CRL " << cdp << "\n";
781 }
782
783 out << "Signature algorithm: " << this->signature_algorithm().oid().to_formatted_string() << "\n";
784
785 out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
786
787 if(!this->authority_key_id().empty()) {
788 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
789 }
790
791 if(!this->subject_key_id().empty()) {
792 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
793 }
794
795 try {
796 auto pubkey = this->subject_public_key();
797 out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
798 out << X509::PEM_encode(*pubkey);
799 } catch(Decoding_Error&) {
800 const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
801 out << "Failed to decode key with oid " << alg_id.oid().to_string() << "\n";
802 }
803
804 return out.str();
805}
806
807} // namespace Botan
std::vector< uint8_t > BER_encode() const
Definition asn1_obj.cpp:19
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
Definition asn1_time.cpp:92
const OID & oid() const
Definition asn1_obj.h:464
const std::set< uint32_t > & ipv4_address() const
Return the set of IPv4 addresses included in this alternative name.
Definition pkix_types.h:155
const std::set< std::string > & uris() const
Return the set of URIs included in this alternative name.
Definition pkix_types.h:146
const std::set< std::string > & dns() const
Return the set of DNS names included in this alternative name.
Definition pkix_types.h:152
const std::set< std::string > & email() const
Return the set of email addresses included in this alternative name.
Definition pkix_types.h:149
bool critical_extension_set(const OID &oid) const
Definition x509_ext.cpp:191
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:107
bool includes(Key_Constraints::Bits other) const
Definition pkix_enums.h:160
Name Constraints.
Definition pkix_types.h:358
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:376
const std::vector< GeneralSubtree > & excluded() const
Definition pkix_types.h:383
std::string to_formatted_string() const
Definition asn1_oid.cpp:139
static std::optional< OID > from_name(std::string_view name)
Definition asn1_oid.cpp:72
std::string to_string() const
Definition asn1_oid.cpp:125
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
const std::vector< OID > & extended_key_usage() const
Definition x509cert.cpp:427
bool is_CA_cert() const
Definition x509cert.cpp:407
Key_Constraints constraints() const
Definition x509cert.cpp:423
bool operator==(const X509_Certificate &other) const
Definition x509cert.cpp:663
const NameConstraints & name_constraints() const
Definition x509cert.cpp:435
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:514
const std::vector< uint8_t > & serial_number() const
Definition x509cert.cpp:383
std::string fingerprint(std::string_view hash_name="SHA-1") const
Definition x509cert.cpp:615
const X509_DN & subject_dn() const
Definition x509cert.cpp:395
std::vector< uint8_t > raw_subject_dn_sha256() const
Definition x509cert.cpp:608
uint32_t path_limit() const
Definition x509cert.cpp:415
const X509_Time & not_after() const
Definition x509cert.cpp:339
const std::vector< uint8_t > & authority_key_id() const
Definition x509cert.cpp:375
bool allowed_extended_usage(std::string_view usage) const
Definition x509cert.cpp:455
const AlternativeName & issuer_alt_name() const
Definition x509cert.cpp:542
const std::vector< uint8_t > & raw_subject_dn() const
Definition x509cert.cpp:403
const std::vector< uint8_t > & subject_key_id() const
Definition x509cert.cpp:379
const std::vector< uint8_t > & subject_public_key_bits() const
Definition x509cert.cpp:355
bool has_constraints(Key_Constraints constraints) const
Definition x509cert.cpp:443
const Extensions & v3_extensions() const
Definition x509cert.cpp:439
bool has_ex_constraint(std::string_view ex_constraint) const
Definition x509cert.cpp:502
std::vector< std::string > crl_distribution_points() const
Definition x509cert.cpp:526
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition x509cert.cpp:367
bool allowed_usage(Key_Constraints usage) const
Definition x509cert.cpp:448
const X509_DN & issuer_dn() const
Definition x509cert.cpp:391
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition x509cert.cpp:347
std::string ocsp_responder() const
Definition x509cert.cpp:518
bool matches_dns_name(std::string_view name) const
Definition x509cert.cpp:634
std::vector< std::string > subject_info(std::string_view name) const
Definition x509cert.cpp:575
uint32_t x509_version() const
Definition x509cert.cpp:327
std::string crl_distribution_point() const
Definition x509cert.cpp:530
const std::vector< OID > & certificate_policy_oids() const
Definition x509cert.cpp:431
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition x509cert.cpp:597
bool is_self_signed() const
Definition x509cert.cpp:331
const std::vector< uint8_t > & raw_issuer_dn() const
Definition x509cert.cpp:399
bool operator<(const X509_Certificate &other) const
Definition x509cert.cpp:668
const AlgorithmIdentifier & subject_public_key_algo() const
Definition x509cert.cpp:343
const AlternativeName & subject_alt_name() const
Definition x509cert.cpp:538
std::vector< std::string > ca_issuers() const
Definition x509cert.cpp:522
const std::vector< uint8_t > & subject_public_key_info() const
Definition x509cert.cpp:359
std::vector< uint8_t > raw_issuer_dn_sha256() const
Definition x509cert.cpp:601
bool is_serial_negative() const
Definition x509cert.cpp:387
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition x509cert.cpp:363
std::unique_ptr< Public_Key > subject_public_key() const
Definition x509cert.cpp:589
const std::vector< uint8_t > & v2_subject_key_id() const
Definition x509cert.cpp:351
const X509_Time & not_before() const
Definition x509cert.cpp:335
std::vector< std::string > issuer_info(std::string_view name) const
Definition x509cert.cpp:582
std::string to_string() const
Definition x509cert.cpp:685
bool has_field(const OID &oid) const
Definition x509_dn.cpp:144
std::vector< std::string > get_attribute(std::string_view attr) const
Definition x509_dn.cpp:172
const std::vector< uint8_t > & signed_body() const
Definition x509_obj.h:42
const AlgorithmIdentifier & signature_algorithm() const
Definition x509_obj.h:47
const std::vector< uint8_t > & signature() const
Definition x509_obj.h:37
void load_data(DataSource &src)
Definition x509_obj.cpp:24
std::string name
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition asn1_obj.cpp:172
std::unique_ptr< Public_Key > load_key(DataSource &source)
Definition x509_key.cpp:28
std::string PEM_encode(const Public_Key &key)
Definition x509_key.cpp:21
ASN1_Time X509_Time
Definition asn1_obj.h:409
ASN1_Type
Definition asn1_obj.h:44
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition alg_id.cpp:69
bool host_wildcard_match(std::string_view issued_, std::string_view host_)
Definition parsing.cpp:252
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition hex.cpp:33
std::string create_hex_fingerprint(const uint8_t bits[], size_t bits_len, std::string_view hash_name)
Definition pk_keys.cpp:30
Usage_Type
Definition x509cert.h:22
std::optional< uint32_t > string_to_ipv4(std::string_view str)
Definition parsing.cpp:156
std::string ipv4_to_string(uint32_t ip)
Definition parsing.cpp:225