Botan 3.7.1
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 RFC 5280 section 4.2.1.12
186
187 "This extension indicates one or more purposes ..."
188
189 "If the extension is present, then the certificate MUST only be
190 used for one of the purposes indicated."
191
192 Thus we reject an EKU extension which is empty, since this indicates
193 the certificate cannot be used for any purpose.
194 */
195 if(data->m_extended_key_usage.empty()) {
196 throw Decoding_Error("Certificate has invalid empty EKU extension");
197 }
198 }
199
200 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
201 if(ext->get_is_ca() == true) {
202 /*
203 * RFC 5280 section 4.2.1.3 requires that CAs include KeyUsage in all
204 * intermediate CA certificates they issue. Currently we accept it being
205 * missing, as do most other implementations. But it may be worth
206 * removing this entirely, or alternately adding a warning level
207 * validation failure for it.
208 */
209 const bool allowed_by_ku =
210 data->m_key_constraints.includes(Key_Constraints::KeyCertSign) || data->m_key_constraints.empty();
211
212 /*
213 * If the extended key usages are set then we must restrict the
214 * usage in accordance with it as well.
215 *
216 * RFC 5280 does not define any extended key usages compatible
217 * with certificate signing, but some CAs seem to use serverAuth
218 * or clientAuth here.
219 */
220 const bool allowed_by_ext_ku = [](const std::vector<OID>& ext_ku) -> bool {
221 if(ext_ku.empty()) {
222 return true;
223 }
224
225 const auto server_auth = OID::from_name("PKIX.ServerAuth");
226 const auto client_auth = OID::from_name("PKIX.ClientAuth");
227 const auto ocsp_sign = OID::from_name("PKIX.OCSPSigning");
228
229 for(const auto& oid : ext_ku) {
230 if(oid == server_auth || oid == client_auth || oid == ocsp_sign) {
231 return true;
232 }
233 }
234
235 return false;
236 }(data->m_extended_key_usage);
237
238 if(allowed_by_ku && allowed_by_ext_ku) {
239 data->m_is_ca_certificate = true;
240 data->m_path_len_constraint = ext->get_path_limit();
241 }
242 }
243 }
244
245 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Issuer_Alternative_Name>()) {
246 data->m_issuer_alt_name = ext->get_alt_name();
247 }
248
249 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
250 data->m_subject_alt_name = ext->get_alt_name();
251 }
252
253 // This will be set even if SAN parsing failed entirely eg due to a decoding error
254 // or if the SAN is empty. This is used to guard against using the CN for domain
255 // name checking.
256 const auto san_oid = OID::from_string("X509v3.SubjectAlternativeName");
257 data->m_subject_alt_name_exists = data->m_v3_extensions.extension_set(san_oid);
258
259 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Certificate_Policies>()) {
260 data->m_cert_policies = ext->get_policy_oids();
261 }
262
263 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>()) {
264 data->m_ocsp_responder = ext->ocsp_responder();
265 data->m_ca_issuers = ext->ca_issuers();
266 }
267
268 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>()) {
269 data->m_crl_distribution_points = ext->crl_distribution_urls();
270 }
271
272 // Check for self-signed vs self-issued certificates
273 if(data->m_subject_dn == data->m_issuer_dn) {
274 if(data->m_subject_key_id.empty() == false && data->m_authority_key_id.empty() == false) {
275 data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
276 } else {
277 /*
278 If a parse error or unknown algorithm is encountered, default
279 to assuming it is self signed. We have no way of being certain but
280 that is usually the default case (self-issued is rare in practice).
281 */
282 data->m_self_signed = true;
283
284 try {
285 auto pub_key = X509::load_key(data->m_subject_public_key_bits_seq);
286
287 const auto sig_status = obj.verify_signature(*pub_key);
288
289 if(sig_status.first == Certificate_Status_Code::OK ||
291 data->m_self_signed = true;
292 } else {
293 data->m_self_signed = false;
294 }
295 } catch(...) {
296 // ignore errors here to allow parsing to continue
297 }
298 }
299 }
300
301 const std::vector<uint8_t> full_encoding = obj.BER_encode();
302
303 if(auto sha1 = HashFunction::create("SHA-1")) {
304 sha1->update(data->m_subject_public_key_bitstring);
305 data->m_subject_public_key_bitstring_sha1 = sha1->final_stdvec();
306 // otherwise left as empty, and we will throw if subject_public_key_bitstring_sha1 is called
307
308 data->m_fingerprint_sha1 = create_hex_fingerprint(full_encoding, "SHA-1");
309 }
310
311 if(auto sha256 = HashFunction::create("SHA-256")) {
312 sha256->update(data->m_issuer_dn_bits);
313 data->m_issuer_dn_bits_sha256 = sha256->final_stdvec();
314
315 sha256->update(data->m_subject_dn_bits);
316 data->m_subject_dn_bits_sha256 = sha256->final_stdvec();
317
318 data->m_fingerprint_sha256 = create_hex_fingerprint(full_encoding, "SHA-256");
319 }
320
321 return data;
322}
323
324} // namespace
325
326/*
327* Decode the TBSCertificate data
328*/
329void X509_Certificate::force_decode() {
330 m_data.reset();
331 m_data = parse_x509_cert_body(*this);
332}
333
334const X509_Certificate_Data& X509_Certificate::data() const {
335 if(m_data == nullptr) {
336 throw Invalid_State("X509_Certificate uninitialized");
337 }
338 return *m_data;
339}
340
342 return static_cast<uint32_t>(data().m_version);
343}
344
346 return data().m_self_signed;
347}
348
350 return data().m_not_before;
351}
352
354 return data().m_not_after;
355}
356
358 return data().m_subject_public_key_algid;
359}
360
361const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const {
362 return data().m_v2_issuer_key_id;
363}
364
365const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const {
366 return data().m_v2_subject_key_id;
367}
368
369const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const {
370 return data().m_subject_public_key_bits;
371}
372
373const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const {
374 return data().m_subject_public_key_bits_seq;
375}
376
377const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const {
378 return data().m_subject_public_key_bitstring;
379}
380
381const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const {
382 if(data().m_subject_public_key_bitstring_sha1.empty()) {
383 throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");
384 }
385
386 return data().m_subject_public_key_bitstring_sha1;
387}
388
389const std::vector<uint8_t>& X509_Certificate::authority_key_id() const {
390 return data().m_authority_key_id;
391}
392
393const std::vector<uint8_t>& X509_Certificate::subject_key_id() const {
394 return data().m_subject_key_id;
395}
396
397const std::vector<uint8_t>& X509_Certificate::serial_number() const {
398 return data().m_serial;
399}
400
402 return data().m_serial_negative;
403}
404
406 return data().m_issuer_dn;
407}
408
410 return data().m_subject_dn;
411}
412
413const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const {
414 return data().m_issuer_dn_bits;
415}
416
417const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const {
418 return data().m_subject_dn_bits;
419}
420
422 if(data().m_version < 3 && data().m_self_signed) {
423 return true;
424 }
425
426 return data().m_is_ca_certificate;
427}
428
430 if(data().m_version < 3 && data().m_self_signed) {
431 return 32; // in theory infinite, but this is more than enough
432 }
433
434 return static_cast<uint32_t>(data().m_path_len_constraint);
435}
436
438 return data().m_key_constraints;
439}
440
441const std::vector<OID>& X509_Certificate::extended_key_usage() const {
442 return data().m_extended_key_usage;
443}
444
445const std::vector<OID>& X509_Certificate::certificate_policy_oids() const {
446 return data().m_cert_policies;
447}
448
450 return data().m_name_constraints;
451}
452
454 return data().m_v3_extensions;
455}
456
458 // Unlike allowed_usage, returns false if constraints was not set
459 return constraints().includes(usage);
460}
461
463 if(constraints().empty()) {
464 return true;
465 }
466 return constraints().includes(usage);
467}
468
469bool X509_Certificate::allowed_extended_usage(std::string_view usage) const {
471}
472
474 const std::vector<OID>& ex = extended_key_usage();
475 if(ex.empty()) {
476 return true;
477 }
478
479 if(std::find(ex.begin(), ex.end(), usage) != ex.end()) {
480 return true;
481 }
482
483 return false;
484}
485
515
516bool X509_Certificate::has_ex_constraint(std::string_view ex_constraint) const {
517 return has_ex_constraint(OID::from_string(ex_constraint));
518}
519
520bool X509_Certificate::has_ex_constraint(const OID& usage) const {
521 const std::vector<OID>& ex = extended_key_usage();
522 return (std::find(ex.begin(), ex.end(), usage) != ex.end());
523}
524
525/*
526* Return if a certificate extension is marked critical
527*/
528bool X509_Certificate::is_critical(std::string_view ex_name) const {
530}
531
533 return data().m_ocsp_responder;
534}
535
536std::vector<std::string> X509_Certificate::ca_issuers() const {
537 return data().m_ca_issuers;
538}
539
540std::vector<std::string> X509_Certificate::crl_distribution_points() const {
541 return data().m_crl_distribution_points;
542}
543
545 // just returns the first (arbitrarily)
546 if(!data().m_crl_distribution_points.empty()) {
547 return data().m_crl_distribution_points[0];
548 }
549 return "";
550}
551
553 return data().m_subject_alt_name;
554}
555
557 return data().m_issuer_alt_name;
558}
559
560namespace {
561
562std::vector<std::string> get_cert_user_info(std::string_view req, const X509_DN& dn, const AlternativeName& alt_name) {
563 auto set_to_vector = [](const std::set<std::string>& s) -> std::vector<std::string> { return {s.begin(), s.end()}; };
564
565 if(dn.has_field(req)) {
566 return dn.get_attribute(req);
567 } else if(req == "RFC822" || req == "Email") {
568 return set_to_vector(alt_name.email());
569 } else if(req == "DNS") {
570 return set_to_vector(alt_name.dns());
571 } else if(req == "URI") {
572 return set_to_vector(alt_name.uris());
573 } else if(req == "IP") {
574 std::vector<std::string> ip_str;
575 for(uint32_t ipv4 : alt_name.ipv4_address()) {
576 ip_str.push_back(ipv4_to_string(ipv4));
577 }
578 return ip_str;
579 } else {
580 return {};
581 }
582}
583
584} // namespace
585
586/*
587* Return information about the subject
588*/
589std::vector<std::string> X509_Certificate::subject_info(std::string_view req) const {
590 return get_cert_user_info(req, subject_dn(), subject_alt_name());
591}
592
593/*
594* Return information about the issuer
595*/
596std::vector<std::string> X509_Certificate::issuer_info(std::string_view req) const {
597 return get_cert_user_info(req, issuer_dn(), issuer_alt_name());
598}
599
600/*
601* Return the public key in this certificate
602*/
603std::unique_ptr<Public_Key> X509_Certificate::subject_public_key() const {
604 try {
605 return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
606 } catch(std::exception& e) {
607 throw Decoding_Error("X509_Certificate::subject_public_key", e);
608 }
609}
610
611std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const {
612 return this->subject_public_key();
613}
614
615std::vector<uint8_t> X509_Certificate::raw_issuer_dn_sha256() const {
616 if(data().m_issuer_dn_bits_sha256.empty()) {
617 throw Encoding_Error("X509_Certificate::raw_issuer_dn_sha256 called but SHA-256 disabled in build");
618 }
619 return data().m_issuer_dn_bits_sha256;
620}
621
622std::vector<uint8_t> X509_Certificate::raw_subject_dn_sha256() const {
623 if(data().m_subject_dn_bits_sha256.empty()) {
624 throw Encoding_Error("X509_Certificate::raw_subject_dn_sha256 called but SHA-256 disabled in build");
625 }
626 return data().m_subject_dn_bits_sha256;
627}
628
629std::string X509_Certificate::fingerprint(std::string_view hash_name) const {
630 /*
631 * The SHA-1 and SHA-256 fingerprints are precomputed since these
632 * are the most commonly used. Especially, SHA-256 fingerprints are
633 * used for cycle detection during path construction.
634 *
635 * If SHA-1 or SHA-256 was missing at parsing time the vectors are
636 * left empty in which case we fall back to create_hex_fingerprint
637 * which will throw if the hash is unavailable.
638 */
639 if(hash_name == "SHA-256" && !data().m_fingerprint_sha256.empty()) {
640 return data().m_fingerprint_sha256;
641 } else if(hash_name == "SHA-1" && !data().m_fingerprint_sha1.empty()) {
642 return data().m_fingerprint_sha1;
643 } else {
644 return create_hex_fingerprint(this->BER_encode(), hash_name);
645 }
646}
647
648bool X509_Certificate::matches_dns_name(std::string_view name) const {
649 if(name.empty()) {
650 return false;
651 }
652
653 if(auto req_ipv4 = string_to_ipv4(name)) {
654 const auto& ipv4_names = subject_alt_name().ipv4_address();
655 return ipv4_names.contains(req_ipv4.value());
656 } else {
657 auto issued_names = subject_info("DNS");
658
659 // Fall back to CN only if no SAN is included
660 if(!data().m_subject_alt_name_exists) {
661 issued_names = subject_info("Name");
662 }
663
664 for(const auto& issued_name : issued_names) {
665 if(host_wildcard_match(issued_name, name)) {
666 return true;
667 }
668 }
669 }
670
671 return false;
672}
673
674/*
675* Compare two certificates for equality
676*/
678 return (this->signature() == other.signature() && this->signature_algorithm() == other.signature_algorithm() &&
679 this->signed_body() == other.signed_body());
680}
681
683 /* If signature values are not equal, sort by lexicographic ordering of that */
684 if(this->signature() != other.signature()) {
685 return (this->signature() < other.signature());
686 }
687
688 // Then compare the signed contents
689 return this->signed_body() < other.signed_body();
690}
691
692/*
693* X.509 Certificate Comparison
694*/
695bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) {
696 return !(cert1 == cert2);
697}
698
699std::string X509_Certificate::to_string() const {
700 std::ostringstream out;
701
702 out << "Version: " << this->x509_version() << "\n";
703 out << "Subject: " << subject_dn() << "\n";
704 out << "Issuer: " << issuer_dn() << "\n";
705 out << "Issued: " << this->not_before().readable_string() << "\n";
706 out << "Expires: " << this->not_after().readable_string() << "\n";
707
708 try {
709 auto pubkey = this->subject_public_key();
710 out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
711 out << X509::PEM_encode(*pubkey) << "\n";
712 } catch(const Decoding_Error& ex) {
713 const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
714 out << "Public Key Invalid!\n"
715 << " OID: " << alg_id.oid().to_formatted_string() << "\n"
716 << " Error: " << ex.what() << "\n"
717 << " Hex: " << hex_encode(this->subject_public_key_bitstring()) << "\n";
718 }
719
720 out << "Constraints:\n";
722 if(constraints.empty()) {
723 out << " No key constraints set\n";
724 } else {
726 out << " Digital Signature\n";
727 }
729 out << " Non-Repudiation\n";
730 }
732 out << " Key Encipherment\n";
733 }
735 out << " Data Encipherment\n";
736 }
738 out << " Key Agreement\n";
739 }
741 out << " Cert Sign\n";
742 }
744 out << " CRL Sign\n";
745 }
747 out << " Encipher Only\n";
748 }
750 out << " Decipher Only\n";
751 }
752 }
753
754 const std::vector<OID>& policies = this->certificate_policy_oids();
755 if(!policies.empty()) {
756 out << "Policies: "
757 << "\n";
758 for(const auto& oid : policies) {
759 out << " " << oid.to_string() << "\n";
760 }
761 }
762
763 const std::vector<OID>& ex_constraints = this->extended_key_usage();
764 if(!ex_constraints.empty()) {
765 out << "Extended Constraints:\n";
766 for(auto&& oid : ex_constraints) {
767 out << " " << oid.to_formatted_string() << "\n";
768 }
769 }
770
772
773 if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty()) {
774 out << "Name Constraints:\n";
775
776 if(!name_constraints.permitted().empty()) {
777 out << " Permit";
778 for(const auto& st : name_constraints.permitted()) {
779 out << " " << st.base();
780 }
781 out << "\n";
782 }
783
784 if(!name_constraints.excluded().empty()) {
785 out << " Exclude";
786 for(const auto& st : name_constraints.excluded()) {
787 out << " " << st.base();
788 }
789 out << "\n";
790 }
791 }
792
793 if(!ocsp_responder().empty()) {
794 out << "OCSP responder " << ocsp_responder() << "\n";
795 }
796
797 const std::vector<std::string> ca_issuers = this->ca_issuers();
798 if(!ca_issuers.empty()) {
799 out << "CA Issuers:\n";
800 for(const auto& ca_issuer : ca_issuers) {
801 out << " URI: " << ca_issuer << "\n";
802 }
803 }
804
805 for(const auto& cdp : crl_distribution_points()) {
806 out << "CRL " << cdp << "\n";
807 }
808
809 out << "Signature algorithm: " << this->signature_algorithm().oid().to_formatted_string() << "\n";
810
811 out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
812
813 if(!this->authority_key_id().empty()) {
814 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
815 }
816
817 if(!this->subject_key_id().empty()) {
818 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
819 }
820
821 if(this->is_self_signed()) {
822 out << "Certificate is self signed\n";
823 }
824
825 return out.str();
826}
827
828} // 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:472
const std::set< uint32_t > & ipv4_address() const
Return the set of IPv4 addresses included in this alternative name.
Definition pkix_types.h:157
const std::set< std::string > & uris() const
Return the set of URIs included in this alternative name.
Definition pkix_types.h:148
const std::set< std::string > & dns() const
Return the set of DNS names included in this alternative name.
Definition pkix_types.h:154
const std::set< std::string > & email() const
Return the set of email addresses included in this alternative name.
Definition pkix_types.h:151
const char * what() const noexcept override
Definition exceptn.h:93
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:360
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:378
const std::vector< GeneralSubtree > & excluded() const
Definition pkix_types.h:385
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
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
const std::vector< OID > & extended_key_usage() const
Definition x509cert.cpp:441
bool is_CA_cert() const
Definition x509cert.cpp:421
Key_Constraints constraints() const
Definition x509cert.cpp:437
bool operator==(const X509_Certificate &other) const
Definition x509cert.cpp:677
const NameConstraints & name_constraints() const
Definition x509cert.cpp:449
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:528
const std::vector< uint8_t > & serial_number() const
Definition x509cert.cpp:397
std::string fingerprint(std::string_view hash_name="SHA-1") const
Definition x509cert.cpp:629
const X509_DN & subject_dn() const
Definition x509cert.cpp:409
std::vector< uint8_t > raw_subject_dn_sha256() const
Definition x509cert.cpp:622
uint32_t path_limit() const
Definition x509cert.cpp:429
const X509_Time & not_after() const
Definition x509cert.cpp:353
const std::vector< uint8_t > & authority_key_id() const
Definition x509cert.cpp:389
bool allowed_extended_usage(std::string_view usage) const
Definition x509cert.cpp:469
const AlternativeName & issuer_alt_name() const
Definition x509cert.cpp:556
const std::vector< uint8_t > & raw_subject_dn() const
Definition x509cert.cpp:417
const std::vector< uint8_t > & subject_key_id() const
Definition x509cert.cpp:393
const std::vector< uint8_t > & subject_public_key_bits() const
Definition x509cert.cpp:369
bool has_constraints(Key_Constraints constraints) const
Definition x509cert.cpp:457
const Extensions & v3_extensions() const
Definition x509cert.cpp:453
bool has_ex_constraint(std::string_view ex_constraint) const
Definition x509cert.cpp:516
std::vector< std::string > crl_distribution_points() const
Definition x509cert.cpp:540
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition x509cert.cpp:381
bool allowed_usage(Key_Constraints usage) const
Definition x509cert.cpp:462
const X509_DN & issuer_dn() const
Definition x509cert.cpp:405
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition x509cert.cpp:361
std::string ocsp_responder() const
Definition x509cert.cpp:532
bool matches_dns_name(std::string_view name) const
Definition x509cert.cpp:648
std::vector< std::string > subject_info(std::string_view name) const
Definition x509cert.cpp:589
uint32_t x509_version() const
Definition x509cert.cpp:341
std::string crl_distribution_point() const
Definition x509cert.cpp:544
const std::vector< OID > & certificate_policy_oids() const
Definition x509cert.cpp:445
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition x509cert.cpp:611
bool is_self_signed() const
Definition x509cert.cpp:345
const std::vector< uint8_t > & raw_issuer_dn() const
Definition x509cert.cpp:413
bool operator<(const X509_Certificate &other) const
Definition x509cert.cpp:682
const AlgorithmIdentifier & subject_public_key_algo() const
Definition x509cert.cpp:357
const AlternativeName & subject_alt_name() const
Definition x509cert.cpp:552
std::vector< std::string > ca_issuers() const
Definition x509cert.cpp:536
const std::vector< uint8_t > & subject_public_key_info() const
Definition x509cert.cpp:373
std::vector< uint8_t > raw_issuer_dn_sha256() const
Definition x509cert.cpp:615
bool is_serial_negative() const
Definition x509cert.cpp:401
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition x509cert.cpp:377
std::unique_ptr< Public_Key > subject_public_key() const
Definition x509cert.cpp:603
const std::vector< uint8_t > & v2_subject_key_id() const
Definition x509cert.cpp:365
const X509_Time & not_before() const
Definition x509cert.cpp:349
std::vector< std::string > issuer_info(std::string_view name) const
Definition x509cert.cpp:596
std::string to_string() const
Definition x509cert.cpp:699
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:23
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:417
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:35
std::string create_hex_fingerprint(const uint8_t bits[], size_t bits_len, std::string_view hash_name)
Definition pk_keys.cpp:38
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