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