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