Botan 3.12.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 <sstream>
22
23namespace Botan {
24
25class X509_Certificate_Data final {
26 public:
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 std::array<uint8_t, 20> m_cert_data_sha1 = {};
61 std::array<uint8_t, 32> m_cert_data_sha256 = {};
62
63 AlternativeName m_subject_alt_name;
64 AlternativeName m_issuer_alt_name;
65 NameConstraints m_name_constraints;
66
67 size_t m_version = 0;
68 std::optional<size_t> m_path_len_constraint;
69 Key_Constraints m_key_constraints;
70 bool m_self_signed = false;
71 bool m_is_ca_certificate = false;
72 bool m_serial_negative = false;
73 bool m_subject_alt_name_exists = false;
74};
75
77
78std::string X509_Certificate::PEM_label() const {
79 return "CERTIFICATE";
80}
81
82std::vector<std::string> X509_Certificate::alternate_PEM_labels() const {
83 return {"X509 CERTIFICATE"};
84}
85
89
90X509_Certificate::X509_Certificate(std::span<const uint8_t> in) {
91 DataSource_Memory src(in);
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(), BER_Decoder::Limits::DER())
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 identifiers 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.signum() < 0;
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, BER_Decoder::Limits::DER())
150 .decode(data->m_subject_public_key_algid)
151 .decode(data->m_subject_public_key_bitstring, ASN1_Type::BitString)
152 .verify_end();
153
154 if(v3_exts_data.is_a(3, ASN1_Class::Constructed | ASN1_Class::ContextSpecific)) {
155 // Path validation will reject a v1/v2 cert with v3 extensions
156 BER_Decoder(v3_exts_data, BER_Decoder::Limits::DER()).decode(data->m_v3_extensions).verify_end();
157 } else if(v3_exts_data.is_set()) {
158 throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.tagging());
159 }
160
161 // Now cache some fields from the extensions
162 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Key_Usage>()) {
163 data->m_key_constraints = ext->get_constraints();
164 /*
165 RFC 5280: When the keyUsage extension appears in a certificate,
166 at least one of the bits MUST be set to 1.
167 */
168 if(data->m_key_constraints.empty()) {
169 throw Decoding_Error("Certificate has invalid encoding for KeyUsage");
170 }
171 }
172
173 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Key_ID>()) {
174 data->m_subject_key_id = ext->get_key_id();
175 }
176
177 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>()) {
178 data->m_authority_key_id = ext->get_key_id();
179 }
180
181 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Name_Constraints>()) {
182 data->m_name_constraints = ext->get_name_constraints();
183 }
184
185 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Extended_Key_Usage>()) {
186 data->m_extended_key_usage = ext->object_identifiers();
187 /*
188 RFC 5280 section 4.2.1.12
189
190 "This extension indicates one or more purposes ..."
191
192 "If the extension is present, then the certificate MUST only be
193 used for one of the purposes indicated."
194
195 Thus we reject an EKU extension which is empty, since this indicates
196 the certificate cannot be used for any purpose.
197 */
198 if(data->m_extended_key_usage.empty()) {
199 throw Decoding_Error("Certificate has invalid empty EKU extension");
200 }
201 }
202
203 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
204 /*
205 * RFC 5280 4.2.1.9 requires that conforming CAs "MUST mark the
206 * extension [basicConstraints] as critical in such certificates"
207 * but places no such requirement on validators.
208 */
209 if(ext->is_ca() == true) {
210 /*
211 * RFC 5280 section 4.2.1.3 requires that CAs include KeyUsage in all
212 * intermediate CA certificates they issue. Currently we accept it being
213 * missing, as do most other implementations. But it may be worth
214 * removing this entirely, or alternately adding a warning level
215 * validation failure for it.
216 */
217 const bool allowed_by_ku =
218 data->m_key_constraints.includes(Key_Constraints::KeyCertSign) || data->m_key_constraints.empty();
219
220 /*
221 * If the extended key usages are set then we must restrict the usage in
222 * accordance with it as well.
223 *
224 * RFC 5280 does not define any extended key usages compatible with certificate
225 * signing, but some CAs use serverAuth, clientAuth, OCSPSigning, or AnyExtendedKeyUsage
226 * for this purpose, even though clearly all of these (besides AEKU) are invalid.
227 * This check at least allows excluding a certificate which is set for only eg
228 * timestamping or code signing, and that seems about the best we can possibly enforce.
229 * OpenSSL, BoringSSL, and Go all completely ignore EKUs in determining ability to
230 * issue certs.
231 */
232 const bool allowed_by_ext_ku = [](const std::vector<OID>& ext_ku) -> bool {
233 if(ext_ku.empty()) {
234 return true;
235 }
236
237 const auto server_auth = OID::from_name("PKIX.ServerAuth");
238 const auto client_auth = OID::from_name("PKIX.ClientAuth");
239 const auto ocsp_sign = OID::from_name("PKIX.OCSPSigning");
240 const auto any_eku = OID::from_name("X509v3.AnyExtendedKeyUsage");
241
242 for(const auto& oid : ext_ku) {
243 if(oid == any_eku || oid == server_auth || oid == client_auth || oid == ocsp_sign) {
244 return true;
245 }
246 }
247
248 return false;
249 }(data->m_extended_key_usage);
250
251 if(allowed_by_ku && allowed_by_ext_ku) {
252 data->m_is_ca_certificate = true;
253 data->m_path_len_constraint = ext->path_length_constraint();
254 }
255 }
256 }
257
258 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Issuer_Alternative_Name>()) {
259 data->m_issuer_alt_name = ext->get_alt_name();
260 }
261
262 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
263 data->m_subject_alt_name = ext->get_alt_name();
264 }
265
266 // This will be set even if SAN parsing failed entirely eg due to a decoding error
267 // or if the SAN is empty. This is used to guard against using the CN for domain
268 // name checking.
269 const auto san_oid = OID::from_string("X509v3.SubjectAlternativeName");
270 data->m_subject_alt_name_exists = data->m_v3_extensions.extension_set(san_oid);
271
272 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Certificate_Policies>()) {
273 data->m_cert_policies = ext->get_policy_oids();
274 }
275
276 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>()) {
277 data->m_ocsp_responders = ext->ocsp_responders();
278 data->m_ca_issuers = ext->ca_issuers();
279 }
280
281 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>()) {
282 data->m_crl_distribution_points = ext->crl_distribution_urls();
283 }
284
285 /*
286 Determine if this certificate appears to be self-issued (subject == issuer).
287 This is only a heuristic used for path building so it's ok it is not precise.
288 The self-signature is verified during path validation.
289 */
290 if(data->m_subject_dn == data->m_issuer_dn) {
291 if(!data->m_subject_key_id.empty() && !data->m_authority_key_id.empty()) {
292 /*
293 Both SKID and AKID are set so we can reliably determine self-signed vs
294 self-issued by comparing the two
295 */
296 data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
297 } else {
298 /*
299 Without both SKID and AKID we can't determine with certainty. Assume
300 self-signed since that's by far the common case.
301 */
302 data->m_self_signed = true;
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 sha1->update(full_encoding);
314 sha1->final(data->m_cert_data_sha1);
315 data->m_fingerprint_sha1 = format_hex_fingerprint(data->m_cert_data_sha1);
316 }
317
318 // SHA-256 is a hard dependency of this module
319 auto sha256 = HashFunction::create_or_throw("SHA-256");
320 sha256->update(data->m_issuer_dn_bits);
321 data->m_issuer_dn_bits_sha256 = sha256->final_stdvec();
322
323 sha256->update(data->m_subject_dn_bits);
324 data->m_subject_dn_bits_sha256 = sha256->final_stdvec();
325
326 sha256->update(full_encoding);
327 sha256->final(data->m_cert_data_sha256);
328 data->m_fingerprint_sha256 = format_hex_fingerprint(data->m_cert_data_sha256);
329
330 return data;
331}
332
333} // namespace
334
335/*
336* Decode the TBSCertificate data
337*/
338void X509_Certificate::force_decode() {
339 m_data.reset();
340 m_data = parse_x509_cert_body(*this);
341}
342
343const X509_Certificate_Data& X509_Certificate::data() const {
344 if(m_data == nullptr) {
345 throw Invalid_State("X509_Certificate uninitialized");
346 }
347 return *m_data;
348}
349
351 return static_cast<uint32_t>(data().m_version);
352}
353
355 return data().m_self_signed;
356}
357
359 return data().m_not_before;
360}
361
363 return data().m_not_after;
364}
365
367 return data().m_subject_public_key_algid;
368}
369
370const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const {
371 return data().m_v2_issuer_key_id;
372}
373
374const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const {
375 return data().m_v2_subject_key_id;
376}
377
378const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const {
379 return data().m_subject_public_key_bits;
380}
381
382const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const {
383 return data().m_subject_public_key_bits_seq;
384}
385
386const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const {
387 return data().m_subject_public_key_bitstring;
388}
389
390const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const {
391 if(data().m_subject_public_key_bitstring_sha1.empty()) {
392 throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");
393 }
394
395 return data().m_subject_public_key_bitstring_sha1;
396}
397
398const std::vector<uint8_t>& X509_Certificate::authority_key_id() const {
399 return data().m_authority_key_id;
400}
401
402const std::vector<uint8_t>& X509_Certificate::subject_key_id() const {
403 return data().m_subject_key_id;
404}
405
406const std::vector<uint8_t>& X509_Certificate::serial_number() const {
407 return data().m_serial;
408}
409
411 return data().m_serial_negative;
412}
413
415 return data().m_issuer_dn;
416}
417
419 return data().m_subject_dn;
420}
421
422const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const {
423 return data().m_issuer_dn_bits;
424}
425
426const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const {
427 return data().m_subject_dn_bits;
428}
429
430std::span<const uint8_t, 20> X509_Certificate::certificate_data_sha1() const {
431 if(data().m_fingerprint_sha1.empty()) {
432 throw Not_Implemented("SHA-1 not available");
433 }
434 return data().m_cert_data_sha1;
435}
436
437std::span<const uint8_t, 32> X509_Certificate::certificate_data_sha256() const {
438 return data().m_cert_data_sha256;
439}
440
442 if(data().m_version < 3 && data().m_self_signed) {
443 return true;
444 }
445
446 return data().m_is_ca_certificate;
447}
448
450 if(data().m_version < 3 && data().m_self_signed) {
451 return 32; // in theory infinite, but this is more than enough
452 }
453
454 return static_cast<uint32_t>(data().m_path_len_constraint.value_or(Cert_Extension::NO_CERT_PATH_LIMIT));
455}
456
457std::optional<size_t> X509_Certificate::path_length_constraint() const {
458 return data().m_path_len_constraint;
459}
460
462 return data().m_key_constraints;
463}
464
465const std::vector<OID>& X509_Certificate::extended_key_usage() const {
466 return data().m_extended_key_usage;
467}
468
469const std::vector<OID>& X509_Certificate::certificate_policy_oids() const {
470 return data().m_cert_policies;
471}
472
474 return data().m_name_constraints;
475}
476
478 return data().m_v3_extensions;
479}
480
482 // Unlike allowed_usage, returns false if constraints was not set
483 return constraints().includes(usage);
484}
485
487 if(constraints().empty()) {
488 return true;
489 }
490 return constraints().includes(usage);
491}
492
493bool X509_Certificate::allowed_extended_usage(std::string_view usage) const {
495}
496
498 const std::vector<OID>& ex = extended_key_usage();
499 if(ex.empty()) {
500 return true;
501 }
502
503 if(has_ex_constraint(usage)) {
504 return true;
505 }
506
507 return false;
508}
509
539
540bool X509_Certificate::has_ex_constraint(std::string_view ex_constraint) const {
541 return has_ex_constraint(OID::from_string(ex_constraint));
542}
543
544bool X509_Certificate::has_ex_constraint(const OID& usage) const {
545 const auto any_eku = OID::from_name("X509v3.AnyExtendedKeyUsage");
546 const auto ocsp_eku = OID::from_name("PKIX.OCSPSigning");
547
548 for(const auto& ext_ku : extended_key_usage()) {
549 if(ext_ku == usage) {
550 return true;
551 }
552
553 /*
554 Do not accept AnyExtendedKeyUsage for OCSP due to RFC 6960 4.2.2.2:
555
556 OCSP signing delegation SHALL be designated by the inclusion of
557 id-kp-OCSPSigning in an extended key usage certificate extension
558 included in the OCSP response signer's certificate.
559 */
560 if(ext_ku == any_eku && usage != ocsp_eku) {
561 return true;
562 }
563 }
564
565 return false;
566}
567
568/*
569* Return if a certificate extension is marked critical
570*/
571bool X509_Certificate::is_critical(std::string_view ex_name) const {
573}
574
576 if(data().m_ocsp_responders.empty()) {
577 return {};
578 }
579 return data().m_ocsp_responders[0];
580}
581
582const std::vector<std::string>& X509_Certificate::ocsp_responders() const {
583 return data().m_ocsp_responders;
584}
585
586std::vector<std::string> X509_Certificate::ca_issuers() const {
587 return data().m_ca_issuers;
588}
589
590std::vector<std::string> X509_Certificate::crl_distribution_points() const {
591 return data().m_crl_distribution_points;
592}
593
595 // just returns the first (arbitrarily)
596 if(!data().m_crl_distribution_points.empty()) {
597 return data().m_crl_distribution_points[0];
598 }
599 return "";
600}
601
603 return data().m_subject_alt_name;
604}
605
607 return data().m_issuer_alt_name;
608}
609
610namespace {
611
612std::vector<std::string> get_cert_user_info(std::string_view req, const X509_DN& dn, const AlternativeName& alt_name) {
613 auto set_to_vector = [](const std::set<std::string>& s) -> std::vector<std::string> { return {s.begin(), s.end()}; };
614
615 if(dn.has_field(req)) {
616 return dn.get_attribute(req);
617 } else if(req == "RFC822" || req == "Email") {
618 return set_to_vector(alt_name.email());
619 } else if(req == "DNS") {
620 return set_to_vector(alt_name.dns());
621 } else if(req == "URI") {
622 return set_to_vector(alt_name.uris());
623 } else if(req == "IP") {
624 std::vector<std::string> ip_str;
625 for(const uint32_t ipv4 : alt_name.ipv4_address()) {
626 ip_str.push_back(ipv4_to_string(ipv4));
627 }
628 return ip_str;
629 } else if(req == "IPv6") {
630 std::vector<std::string> ip_str;
631 for(const auto& ipv6 : alt_name.ipv6_address()) {
632 ip_str.push_back(ipv6.to_string());
633 }
634 return ip_str;
635 } else {
636 return {};
637 }
638}
639
640} // namespace
641
642/*
643* Return information about the subject
644*/
645std::vector<std::string> X509_Certificate::subject_info(std::string_view req) const {
646 return get_cert_user_info(req, subject_dn(), subject_alt_name());
647}
648
649/*
650* Return information about the issuer
651*/
652std::vector<std::string> X509_Certificate::issuer_info(std::string_view req) const {
653 return get_cert_user_info(req, issuer_dn(), issuer_alt_name());
654}
655
656/*
657* Return the public key in this certificate
658*/
659std::unique_ptr<Public_Key> X509_Certificate::subject_public_key() const {
660 try {
661 return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
662 } catch(std::exception& e) {
663 throw Decoding_Error("X509_Certificate::subject_public_key", e);
664 }
665}
666
667std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const {
668 return this->subject_public_key();
669}
670
671const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn_sha256() const {
672 if(data().m_issuer_dn_bits_sha256.empty()) {
673 throw Encoding_Error("X509_Certificate::raw_issuer_dn_sha256 called but SHA-256 disabled in build");
674 }
675 return data().m_issuer_dn_bits_sha256;
676}
677
678const std::vector<uint8_t>& X509_Certificate::raw_subject_dn_sha256() const {
679 if(data().m_subject_dn_bits_sha256.empty()) {
680 throw Encoding_Error("X509_Certificate::raw_subject_dn_sha256 called but SHA-256 disabled in build");
681 }
682 return data().m_subject_dn_bits_sha256;
683}
684
685std::string X509_Certificate::fingerprint(std::string_view hash_name) const {
686 /*
687 * The SHA-1 and SHA-256 fingerprints are precomputed since these
688 * are the most commonly used. Especially, SHA-256 fingerprints are
689 * used for cycle detection during path construction.
690 *
691 * If SHA-1 or SHA-256 was missing at parsing time the vectors are
692 * left empty in which case we fall back to create_hex_fingerprint
693 * which will throw if the hash is unavailable.
694 */
695 if(hash_name == "SHA-256" && !data().m_fingerprint_sha256.empty()) {
696 return data().m_fingerprint_sha256;
697 } else if(hash_name == "SHA-1" && !data().m_fingerprint_sha1.empty()) {
698 return data().m_fingerprint_sha1;
699 } else {
700 return create_hex_fingerprint(this->BER_encode(), hash_name);
701 }
702}
703
705 return Tag(data().m_cert_data_sha256);
706}
707
708bool X509_Certificate::matches_dns_name(std::string_view name) const {
709 if(name.empty()) {
710 return false;
711 }
712
713 if(auto req_ipv4 = string_to_ipv4(name)) {
714 const auto& ipv4_names = subject_alt_name().ipv4_address();
715 return ipv4_names.contains(req_ipv4.value());
716 }
717
718 if(auto req_ipv6 = IPv6Address::from_string(name)) {
719 const auto& ipv6_names = subject_alt_name().ipv6_address();
720 return ipv6_names.contains(req_ipv6.value());
721 }
722
723 auto issued_names = subject_info("DNS");
724
725 // Fall back to CN only if no SAN is included
726 if(!data().m_subject_alt_name_exists) {
727 issued_names = subject_info("Name");
728 }
729
730 for(const auto& issued_name : issued_names) {
731 if(host_wildcard_match(issued_name, name)) {
732 return true;
733 }
734 }
735
736 return false;
737}
738
739/*
740* Compare two certificates for equality
741*/
743 return (this->signature() == other.signature() && this->signature_algorithm() == other.signature_algorithm() &&
744 this->signed_body() == other.signed_body());
745}
746
748 /* If signature values are not equal, sort by lexicographic ordering of that */
749 if(this->signature() != other.signature()) {
750 return (this->signature() < other.signature());
751 }
752
753 // Then compare the signed contents
754 return this->signed_body() < other.signed_body();
755}
756
757/*
758* X.509 Certificate Comparison
759*/
760bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) {
761 return !(cert1 == cert2);
762}
763
764std::string X509_Certificate::to_string() const {
765 std::ostringstream out;
766
767 out << "Version: " << this->x509_version() << "\n";
768 out << "Subject: " << subject_dn() << "\n";
769 out << "Issuer: " << issuer_dn() << "\n";
770 out << "Issued: " << this->not_before().readable_string() << "\n";
771 out << "Expires: " << this->not_after().readable_string() << "\n";
772
773 try {
774 auto pubkey = this->subject_public_key();
775 out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
776 out << X509::PEM_encode(*pubkey) << "\n";
777 } catch(const Decoding_Error& ex) {
778 const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
779 out << "Public Key Invalid!\n"
780 << " OID: " << alg_id.oid().to_formatted_string() << "\n"
781 << " Error: " << ex.what() << "\n"
782 << " Hex: " << hex_encode(this->subject_public_key_bitstring()) << "\n";
783 }
784
785 out << "Constraints:\n";
787 if(constraints.empty()) {
788 out << " No key constraints set\n";
789 } else {
791 out << " Digital Signature\n";
792 }
794 out << " Non-Repudiation\n";
795 }
797 out << " Key Encipherment\n";
798 }
800 out << " Data Encipherment\n";
801 }
803 out << " Key Agreement\n";
804 }
806 out << " Cert Sign\n";
807 }
809 out << " CRL Sign\n";
810 }
812 out << " Encipher Only\n";
813 }
815 out << " Decipher Only\n";
816 }
817 }
818
819 const std::vector<OID>& policies = this->certificate_policy_oids();
820 if(!policies.empty()) {
821 out << "Policies: "
822 << "\n";
823 for(const auto& oid : policies) {
824 out << " " << oid.to_string() << "\n";
825 }
826 }
827
828 const std::vector<OID>& ex_constraints = this->extended_key_usage();
829 if(!ex_constraints.empty()) {
830 out << "Extended Constraints:\n";
831 for(auto&& oid : ex_constraints) {
832 out << " " << oid.to_formatted_string() << "\n";
833 }
834 }
835
837
838 if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty()) {
839 out << "Name Constraints:\n";
840
841 if(!name_constraints.permitted().empty()) {
842 out << " Permit";
843 for(const auto& st : name_constraints.permitted()) {
844 out << " " << st.base();
845 }
846 out << "\n";
847 }
848
849 if(!name_constraints.excluded().empty()) {
850 out << " Exclude";
851 for(const auto& st : name_constraints.excluded()) {
852 out << " " << st.base();
853 }
854 out << "\n";
855 }
856 }
857
858 const auto& ocsp_responders = this->ocsp_responders();
859 if(!ocsp_responders.empty()) {
860 out << "OCSP Responders:\n";
861 for(const auto& ocsp_responder : ocsp_responders) {
862 out << " URI: " << ocsp_responder << "\n";
863 }
864 }
865
866 const std::vector<std::string> ca_issuers = this->ca_issuers();
867 if(!ca_issuers.empty()) {
868 out << "CA Issuers:\n";
869 for(const auto& ca_issuer : ca_issuers) {
870 out << " URI: " << ca_issuer << "\n";
871 }
872 }
873
874 for(const auto& cdp : crl_distribution_points()) {
875 out << "CRL " << cdp << "\n";
876 }
877
878 out << "Signature algorithm: " << this->signature_algorithm().oid().to_formatted_string() << "\n";
879
880 out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
881
882 if(!this->authority_key_id().empty()) {
883 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
884 }
885
886 if(!this->subject_key_id().empty()) {
887 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
888 }
889
890 if(this->is_self_signed()) {
891 out << "Certificate is self signed\n";
892 }
893
894 return out.str();
895}
896
897} // 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.
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:186
const std::set< std::string > & uris() const
Return the set of URIs included in this alternative name.
Definition pkix_types.h:177
const std::set< std::string > & dns() const
Return the set of DNS names included in this alternative name.
Definition pkix_types.h:183
const std::set< IPv6Address > & ipv6_address() const
Return the set of IPv6 addresses included in this alternative name.
Definition pkix_types.h:189
const std::set< std::string > & email() const
Return the set of email addresses included in this alternative name.
Definition pkix_types.h:180
static Limits DER()
Definition ber_dec.h:35
BER_Decoder & decode(bool &out)
Definition ber_dec.h:220
BER_Decoder & verify_end()
Definition ber_dec.cpp:381
const char * what() const noexcept override
Definition exceptn.h:94
bool critical_extension_set(const OID &oid) const
Definition x509_ext.cpp:215
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:308
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:111
static std::optional< IPv6Address > from_string(std::string_view str)
bool includes(Key_Constraints::Bits other) const
Definition pkix_enums.h:177
Name Constraints.
Definition pkix_types.h:431
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:449
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:465
bool is_CA_cert() const
Definition x509cert.cpp:441
Key_Constraints constraints() const
Definition x509cert.cpp:461
bool operator==(const X509_Certificate &other) const
Definition x509cert.cpp:742
const NameConstraints & name_constraints() const
Definition x509cert.cpp:473
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:571
const std::vector< uint8_t > & serial_number() const
Definition x509cert.cpp:406
std::string fingerprint(std::string_view hash_name="SHA-1") const
Definition x509cert.cpp:685
const X509_DN & subject_dn() const
Definition x509cert.cpp:418
uint32_t path_limit() const
Definition x509cert.cpp:449
const X509_Time & not_after() const
Definition x509cert.cpp:362
const std::vector< uint8_t > & authority_key_id() const
Definition x509cert.cpp:398
std::span< const uint8_t, 32 > certificate_data_sha256() const
Definition x509cert.cpp:437
bool allowed_extended_usage(std::string_view usage) const
Definition x509cert.cpp:493
const AlternativeName & issuer_alt_name() const
Definition x509cert.cpp:606
const std::vector< uint8_t > & raw_subject_dn() const
Definition x509cert.cpp:426
const std::vector< uint8_t > & subject_key_id() const
Definition x509cert.cpp:402
~X509_Certificate() override
const std::vector< uint8_t > & subject_public_key_bits() const
Definition x509cert.cpp:378
bool has_constraints(Key_Constraints constraints) const
Definition x509cert.cpp:481
std::optional< size_t > path_length_constraint() const
Definition x509cert.cpp:457
const Extensions & v3_extensions() const
Definition x509cert.cpp:477
bool has_ex_constraint(std::string_view ex_constraint) const
Definition x509cert.cpp:540
std::vector< std::string > crl_distribution_points() const
Definition x509cert.cpp:590
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition x509cert.cpp:390
bool allowed_usage(Key_Constraints usage) const
Definition x509cert.cpp:486
const X509_DN & issuer_dn() const
Definition x509cert.cpp:414
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition x509cert.cpp:370
std::string ocsp_responder() const
Definition x509cert.cpp:575
std::span< const uint8_t, 20 > certificate_data_sha1() const
Definition x509cert.cpp:430
bool matches_dns_name(std::string_view name) const
Definition x509cert.cpp:708
std::vector< std::string > subject_info(std::string_view name) const
Definition x509cert.cpp:645
const std::vector< uint8_t > & raw_subject_dn_sha256() const
Definition x509cert.cpp:678
uint32_t x509_version() const
Definition x509cert.cpp:350
std::string crl_distribution_point() const
Definition x509cert.cpp:594
const std::vector< OID > & certificate_policy_oids() const
Definition x509cert.cpp:469
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition x509cert.cpp:667
X509_Certificate(DataSource &source)
Definition x509cert.cpp:86
bool is_self_signed() const
Definition x509cert.cpp:354
const std::vector< uint8_t > & raw_issuer_dn() const
Definition x509cert.cpp:422
bool operator<(const X509_Certificate &other) const
Definition x509cert.cpp:747
const std::vector< uint8_t > & raw_issuer_dn_sha256() const
Definition x509cert.cpp:671
const AlgorithmIdentifier & subject_public_key_algo() const
Definition x509cert.cpp:366
const std::vector< std::string > & ocsp_responders() const
Definition x509cert.cpp:582
const AlternativeName & subject_alt_name() const
Definition x509cert.cpp:602
std::vector< std::string > ca_issuers() const
Definition x509cert.cpp:586
const std::vector< uint8_t > & subject_public_key_info() const
Definition x509cert.cpp:382
bool is_serial_negative() const
Definition x509cert.cpp:410
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition x509cert.cpp:386
std::unique_ptr< Public_Key > subject_public_key() const
Definition x509cert.cpp:659
const std::vector< uint8_t > & v2_subject_key_id() const
Definition x509cert.cpp:374
const X509_Time & not_before() const
Definition x509cert.cpp:358
std::vector< std::string > issuer_info(std::string_view name) const
Definition x509cert.cpp:652
std::string to_string() const
Definition x509cert.cpp:764
bool has_field(const OID &oid) const
Definition x509_dn.cpp:153
std::vector< std::string > get_attribute(std::string_view attr) const
Definition x509_dn.cpp:181
const std::vector< uint8_t > & signed_body() const
Definition x509_obj.cpp:66
const AlgorithmIdentifier & signature_algorithm() const
Definition x509_obj.cpp:73
virtual std::vector< std::string > alternate_PEM_labels() const
Definition x509_obj.h:102
const std::vector< uint8_t > & signature() const
Definition x509_obj.cpp:59
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
std::string create_hex_fingerprint(std::span< const uint8_t > bits, std::string_view hash_name)
Definition pk_keys.cpp:38
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition alg_id.cpp:68
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition hex.cpp:34
std::optional< uint32_t > string_to_ipv4(std::string_view str)
Definition parsing.cpp:155
std::string format_hex_fingerprint(std::span< const uint8_t > bits)
Definition pk_keys.cpp:45
std::string ipv4_to_string(uint32_t ip)
Definition parsing.cpp:361
bool host_wildcard_match(std::string_view issued, std::string_view host)
Definition parsing.cpp:389