Botan 3.13.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,2026 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/uri.h>
19#include <botan/x509_ext.h>
20#include <botan/x509_key.h>
21#include <botan/internal/charset.h>
22#include <sstream>
23
24namespace Botan {
25
26class X509_Certificate_Data final {
27 public:
28 X509_Serial_Number m_serial;
29 // TODO(Botan4) once negative serials are rejected this extra vector can go away
30 std::vector<uint8_t> m_serial_bits;
31 AlgorithmIdentifier m_sig_algo_inner;
32 X509_DN m_issuer_dn;
33 X509_DN m_subject_dn;
34 std::vector<uint8_t> m_issuer_dn_bits;
35 std::vector<uint8_t> m_subject_dn_bits;
36 X509_Time m_not_before;
37 X509_Time m_not_after;
38 std::vector<uint8_t> m_subject_public_key_bits;
39 std::vector<uint8_t> m_subject_public_key_bits_seq;
40 std::vector<uint8_t> m_subject_public_key_bitstring;
41 AlgorithmIdentifier m_subject_public_key_algid;
42
43 // TODO(Botan4) change this to std::array<uint8_t, 20> and getter to span
44 std::vector<uint8_t> m_subject_public_key_bitstring_sha1;
45 std::array<uint8_t, 32> m_subject_public_key_bitstring_sha256 = {};
46
47 std::vector<uint8_t> m_v2_issuer_key_id;
48 std::vector<uint8_t> m_v2_subject_key_id;
49 Extensions m_v3_extensions;
50
51 std::vector<OID> m_extended_key_usage;
52 std::vector<uint8_t> m_authority_key_id;
53 std::vector<uint8_t> m_subject_key_id;
54 std::vector<OID> m_cert_policies;
55
56 std::vector<URI> m_crl_distribution_points;
57 std::vector<URI> m_ocsp_responders;
58 std::vector<URI> m_ca_issuers;
59
60 // TODO(Botan4) change this to std::array<uint8_t, 32> and getter to span
61 std::vector<uint8_t> m_issuer_dn_bits_sha256;
62 // TODO(Botan4) change this to std::array<uint8_t, 32> and getter to span
63 std::vector<uint8_t> m_subject_dn_bits_sha256;
64 std::array<uint8_t, 20> m_issuer_dn_bits_sha1 = {};
65 std::array<uint8_t, 20> m_subject_dn_bits_sha1 = {};
66
67 std::string m_fingerprint_sha1;
68 std::string m_fingerprint_sha256;
69
70 std::array<uint8_t, 20> m_cert_data_sha1 = {};
71 std::array<uint8_t, 32> m_cert_data_sha256 = {};
72
73 AlternativeName m_subject_alt_name;
74 AlternativeName m_issuer_alt_name;
75 NameConstraints m_name_constraints;
76
77 size_t m_version = 0;
78 std::optional<size_t> m_path_len_constraint;
79 Key_Constraints m_key_constraints;
80 bool m_self_signed = false;
81 bool m_is_ca_certificate = false;
82 bool m_subject_alt_name_exists = false;
83 bool m_skip_revocation_check = false;
84};
85
87
88std::string X509_Certificate::PEM_label() const {
89 return "CERTIFICATE";
90}
91
92std::vector<std::string> X509_Certificate::alternate_PEM_labels() const {
93 return {"X509 CERTIFICATE"};
94}
95
99
100X509_Certificate::X509_Certificate(std::span<const uint8_t> in) {
101 DataSource_Memory src(in);
102 load_data(src);
103}
104
105#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
106X509_Certificate::X509_Certificate(std::string_view fsname) {
107 DataSource_Stream src(fsname, true);
108 load_data(src);
109}
110#endif
111
112namespace {
113
114std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& obj) {
115 auto data = std::make_unique<X509_Certificate_Data>();
116
117 BER_Object public_key;
118 BER_Object v3_exts_data;
119
120 BER_Decoder(obj.signed_body(), BER_Decoder::Limits::DER())
121 .decode_optional(data->m_version, ASN1_Type(0), ASN1_Class::Constructed | ASN1_Class::ContextSpecific)
122 .decode(data->m_serial)
123 .decode(data->m_sig_algo_inner)
124 .decode(data->m_issuer_dn)
125 .start_sequence()
126 .decode(data->m_not_before)
127 .decode(data->m_not_after)
128 .end_cons()
129 .decode(data->m_subject_dn)
130 .get_next(public_key)
131 .decode_optional_string(data->m_v2_issuer_key_id, ASN1_Type::BitString, 1)
132 .decode_optional_string(data->m_v2_subject_key_id, ASN1_Type::BitString, 2)
133 .get_next(v3_exts_data)
134 .verify_end("TBSCertificate has extra data after extensions block");
135
136 if(data->m_version > 2) {
137 throw Decoding_Error("Unknown X.509 cert version " + std::to_string(data->m_version));
138 }
139 if(obj.signature_algorithm() != data->m_sig_algo_inner) {
140 throw Decoding_Error("X.509 Certificate had differing algorithm identifiers in inner and outer ID fields");
141 }
142
143 public_key.assert_is_a(ASN1_Type::Sequence, ASN1_Class::Constructed, "X.509 certificate public key");
144
145 // for general sanity convert wire version (0 based) to standards version (v1 .. v3)
146 data->m_version += 1;
147
148 data->m_serial_bits = data->m_serial.magnitude();
149 data->m_subject_dn_bits = ASN1::put_in_sequence(data->m_subject_dn.get_bits());
150 data->m_issuer_dn_bits = ASN1::put_in_sequence(data->m_issuer_dn.get_bits());
151
152 data->m_subject_public_key_bits.assign(public_key.bits(), public_key.bits() + public_key.length());
153
154 data->m_subject_public_key_bits_seq = ASN1::put_in_sequence(data->m_subject_public_key_bits);
155
156 BER_Decoder(data->m_subject_public_key_bits, BER_Decoder::Limits::DER())
157 .decode(data->m_subject_public_key_algid)
158 .decode_octet_aligned_bitstring(data->m_subject_public_key_bitstring)
159 .verify_end();
160
161 if(v3_exts_data.is_a(3, ASN1_Class::Constructed | ASN1_Class::ContextSpecific)) {
162 // Path validation will reject a v1/v2 cert with v3 extensions
163 BER_Decoder cert_extensions(v3_exts_data, BER_Decoder::Limits::DER());
164 data->m_v3_extensions.decode_from(cert_extensions, Extension_Context::Certificate);
165 cert_extensions.verify_end();
166 } else if(v3_exts_data.is_set()) {
167 throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.tagging());
168 }
169
170 // Now cache some fields from the extensions
171 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Key_Usage>()) {
172 data->m_key_constraints = ext->get_constraints();
173 /*
174 RFC 5280: When the keyUsage extension appears in a certificate,
175 at least one of the bits MUST be set to 1.
176 */
177 if(data->m_key_constraints.empty()) {
178 throw Decoding_Error("Certificate has invalid encoding for KeyUsage");
179 }
180 }
181
182 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Key_ID>()) {
183 data->m_subject_key_id = ext->get_key_id();
184 }
185
186 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>()) {
187 data->m_authority_key_id = ext->get_key_id();
188 }
189
190 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Name_Constraints>()) {
191 data->m_name_constraints = ext->get_name_constraints();
192 }
193
194 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Extended_Key_Usage>()) {
195 data->m_extended_key_usage = ext->object_identifiers();
196 /*
197 RFC 5280 section 4.2.1.12
198
199 "This extension indicates one or more purposes ..."
200
201 "If the extension is present, then the certificate MUST only be
202 used for one of the purposes indicated."
203
204 Thus we reject an EKU extension which is empty, since this indicates
205 the certificate cannot be used for any purpose.
206 */
207 if(data->m_extended_key_usage.empty()) {
208 throw Decoding_Error("Certificate has invalid empty EKU extension");
209 }
210 }
211
212 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
213 /*
214 * RFC 5280 4.2.1.9 requires that conforming CAs "MUST mark the
215 * extension [basicConstraints] as critical in such certificates"
216 * but places no such requirement on validators.
217 */
218 if(ext->is_ca() == true) {
219 /*
220 * RFC 5280 section 4.2.1.3 requires that CAs include KeyUsage in all
221 * intermediate CA certificates they issue. Currently we accept it being
222 * missing, as do most other implementations. But it may be worth
223 * removing this entirely, or alternately adding a warning level
224 * validation failure for it.
225 */
226 const bool allowed_by_ku =
227 data->m_key_constraints.includes(Key_Constraints::KeyCertSign) || data->m_key_constraints.empty();
228
229 /*
230 * If the extended key usages are set then we must restrict the usage in
231 * accordance with it as well.
232 *
233 * RFC 5280 does not define any extended key usages compatible with certificate
234 * signing, but some CAs use serverAuth, clientAuth, OCSPSigning, or AnyExtendedKeyUsage
235 * for this purpose, even though clearly all of these (besides AEKU) are invalid.
236 * This check at least allows excluding a certificate which is set for only eg
237 * timestamping or code signing, and that seems about the best we can possibly enforce.
238 * OpenSSL, BoringSSL, and Go all completely ignore EKUs in determining ability to
239 * issue certs.
240 */
241 const bool allowed_by_ext_ku = [](const std::vector<OID>& ext_ku) -> bool {
242 if(ext_ku.empty()) {
243 return true;
244 }
245
246 const auto server_auth = OID::from_name("PKIX.ServerAuth");
247 const auto client_auth = OID::from_name("PKIX.ClientAuth");
248 const auto ocsp_sign = OID::from_name("PKIX.OCSPSigning");
249 const auto any_eku = OID::from_name("X509v3.AnyExtendedKeyUsage");
250
251 for(const auto& oid : ext_ku) {
252 if(oid == any_eku || oid == server_auth || oid == client_auth || oid == ocsp_sign) {
253 return true;
254 }
255 }
256
257 return false;
258 }(data->m_extended_key_usage);
259
260 if(allowed_by_ku && allowed_by_ext_ku) {
261 data->m_is_ca_certificate = true;
262 data->m_path_len_constraint = ext->path_length_constraint();
263 }
264 }
265 }
266
267 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Issuer_Alternative_Name>()) {
268 data->m_issuer_alt_name = ext->get_alt_name();
269 }
270
271 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>()) {
272 data->m_subject_alt_name = ext->get_alt_name();
273 }
274
275 // This will be set even if SAN parsing failed entirely eg due to a decoding error
276 // or if the SAN is empty. This is used to guard against using the CN for domain
277 // name checking.
278 const auto san_oid = OID::from_string("X509v3.SubjectAlternativeName");
279 data->m_subject_alt_name_exists = data->m_v3_extensions.extension_set(san_oid);
280
281 /*
282 * RFC 9608 Section 4:
283 *
284 * If the noRevAvail certificate extension specified in this document is
285 * present or the ocsp-nocheck certificate extension [RFC6960] is
286 * present, then Step (a)(3) is skipped. Otherwise, revocation status
287 * determination of the certificate is performed.
288 */
289 data->m_skip_revocation_check =
290 data->m_v3_extensions.extension_set(Cert_Extension::NoRevocationAvailable::static_oid()) ||
291 data->m_v3_extensions.extension_set(Cert_Extension::OCSP_NoCheck::static_oid());
292
293 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Certificate_Policies>()) {
294 data->m_cert_policies = ext->get_policy_oids();
295 }
296
297 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>()) {
298 data->m_ocsp_responders = ext->ocsp_responder_uris();
299 data->m_ca_issuers = ext->ca_issuer_uris();
300 }
301
302 if(const auto* ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>()) {
303 data->m_crl_distribution_points = ext->crl_distribution_point_uris();
304 }
305
306 /*
307 Determine if this certificate appears to be self-issued (subject == issuer).
308 This is only a heuristic used for path building so it's ok it is not precise.
309 The self-signature is verified during path validation.
310 */
311 if(data->m_subject_dn == data->m_issuer_dn) {
312 if(!data->m_subject_key_id.empty() && !data->m_authority_key_id.empty()) {
313 /*
314 Both SKID and AKID are set so we can reliably determine self-signed vs
315 self-issued by comparing the two
316 */
317 data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
318 } else {
319 /*
320 Without both SKID and AKID we can't determine with certainty. Assume
321 self-signed since that's by far the common case.
322 */
323 data->m_self_signed = true;
324 }
325 }
326
327 const std::vector<uint8_t> full_encoding = obj.BER_encode();
328
329 if(auto sha1 = HashFunction::create("SHA-1")) {
330 sha1->update(data->m_subject_public_key_bitstring);
331 data->m_subject_public_key_bitstring_sha1 = sha1->final_stdvec();
332 // otherwise left as empty, and we will throw if subject_public_key_bitstring_sha1 is called
333
334 sha1->update(full_encoding);
335 sha1->final(data->m_cert_data_sha1);
336 data->m_fingerprint_sha1 = format_hex_fingerprint(data->m_cert_data_sha1);
337
338 sha1->update(data->m_issuer_dn_bits);
339 sha1->final(data->m_issuer_dn_bits_sha1);
340
341 sha1->update(data->m_subject_dn_bits);
342 sha1->final(data->m_subject_dn_bits_sha1);
343 }
344
345 // SHA-256 is a hard dependency of this module
346 auto sha256 = HashFunction::create_or_throw("SHA-256");
347 sha256->update(data->m_issuer_dn_bits);
348 data->m_issuer_dn_bits_sha256 = sha256->final_stdvec();
349
350 sha256->update(data->m_subject_dn_bits);
351 data->m_subject_dn_bits_sha256 = sha256->final_stdvec();
352
353 sha256->update(full_encoding);
354 sha256->final(data->m_cert_data_sha256);
355 data->m_fingerprint_sha256 = format_hex_fingerprint(data->m_cert_data_sha256);
356
357 sha256->update(data->m_subject_public_key_bitstring);
358 sha256->final(data->m_subject_public_key_bitstring_sha256);
359
360 return data;
361}
362
363} // namespace
364
365/*
366* Decode the TBSCertificate data
367*/
368void X509_Certificate::force_decode() {
369 m_data.reset();
370 m_data = parse_x509_cert_body(*this);
371}
372
373const X509_Certificate_Data& X509_Certificate::data() const {
374 if(m_data == nullptr) {
375 throw Invalid_State("X509_Certificate uninitialized");
376 }
377 return *m_data;
378}
379
381 return static_cast<uint32_t>(data().m_version);
382}
383
385 return data().m_self_signed;
386}
387
389 return data().m_not_before;
390}
391
393 return data().m_not_after;
394}
395
397 return data().m_subject_public_key_algid;
398}
399
400const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const {
401 return data().m_v2_issuer_key_id;
402}
403
404const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const {
405 return data().m_v2_subject_key_id;
406}
407
408const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const {
409 return data().m_subject_public_key_bits;
410}
411
412const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const {
413 return data().m_subject_public_key_bits_seq;
414}
415
416const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const {
417 return data().m_subject_public_key_bitstring;
418}
419
420const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const {
421 if(data().m_subject_public_key_bitstring_sha1.empty()) {
422 throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");
423 }
424
425 return data().m_subject_public_key_bitstring_sha1;
426}
427
428std::span<const uint8_t, 32> X509_Certificate::subject_public_key_bitstring_sha256() const {
429 return data().m_subject_public_key_bitstring_sha256;
430}
431
432const std::vector<uint8_t>& X509_Certificate::authority_key_id() const {
433 return data().m_authority_key_id;
434}
435
436const std::vector<uint8_t>& X509_Certificate::subject_key_id() const {
437 return data().m_subject_key_id;
438}
439
440const std::vector<uint8_t>& X509_Certificate::serial_number() const {
441 return data().m_serial_bits;
442}
443
445 return data().m_serial;
446}
447
449 return data().m_serial.is_negative();
450}
451
453 return data().m_skip_revocation_check;
454}
455
457 return data().m_issuer_dn;
458}
459
461 return data().m_subject_dn;
462}
463
464const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const {
465 return data().m_issuer_dn_bits;
466}
467
468const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const {
469 return data().m_subject_dn_bits;
470}
471
472std::span<const uint8_t, 20> X509_Certificate::certificate_data_sha1() const {
473 if(data().m_fingerprint_sha1.empty()) {
474 throw Not_Implemented("SHA-1 not available");
475 }
476 return data().m_cert_data_sha1;
477}
478
479std::span<const uint8_t, 32> X509_Certificate::certificate_data_sha256() const {
480 return data().m_cert_data_sha256;
481}
482
484 if(data().m_version < 3 && data().m_self_signed) {
485 return true;
486 }
487
488 return data().m_is_ca_certificate;
489}
490
492 if(data().m_version < 3 && data().m_self_signed) {
493 return 32; // in theory infinite, but this is more than enough
494 }
495
496 return static_cast<uint32_t>(data().m_path_len_constraint.value_or(Cert_Extension::NO_CERT_PATH_LIMIT));
497}
498
499std::optional<size_t> X509_Certificate::path_length_constraint() const {
500 return data().m_path_len_constraint;
501}
502
504 return data().m_key_constraints;
505}
506
507const std::vector<OID>& X509_Certificate::extended_key_usage() const {
508 return data().m_extended_key_usage;
509}
510
511const std::vector<OID>& X509_Certificate::certificate_policy_oids() const {
512 return data().m_cert_policies;
513}
514
516 return data().m_name_constraints;
517}
518
520 return data().m_v3_extensions;
521}
522
524 // Unlike allowed_usage, returns false if constraints was not set
525 return constraints().includes(usage);
526}
527
529 if(constraints().empty()) {
530 return true;
531 }
532 return constraints().includes(usage);
533}
534
535bool X509_Certificate::allowed_extended_usage(std::string_view usage) const {
537}
538
540 const std::vector<OID>& ex = extended_key_usage();
541 if(ex.empty()) {
542 return true;
543 }
544
545 if(has_ex_constraint(usage)) {
546 return true;
547 }
548
549 return false;
550}
551
581
582bool X509_Certificate::has_ex_constraint(std::string_view ex_constraint) const {
583 return has_ex_constraint(OID::from_string(ex_constraint));
584}
585
586bool X509_Certificate::has_ex_constraint(const OID& usage) const {
587 const auto any_eku = OID::from_name("X509v3.AnyExtendedKeyUsage");
588 const auto ocsp_eku = OID::from_name("PKIX.OCSPSigning");
589
590 for(const auto& ext_ku : extended_key_usage()) {
591 if(ext_ku == usage) {
592 return true;
593 }
594
595 /*
596 Do not accept AnyExtendedKeyUsage for OCSP due to RFC 6960 4.2.2.2:
597
598 OCSP signing delegation SHALL be designated by the inclusion of
599 id-kp-OCSPSigning in an extended key usage certificate extension
600 included in the OCSP response signer's certificate.
601 */
602 if(ext_ku == any_eku && usage != ocsp_eku) {
603 return true;
604 }
605 }
606
607 return false;
608}
609
610/*
611* Return if a certificate extension is marked critical
612*/
613bool X509_Certificate::is_critical(std::string_view ex_name) const {
615}
616
617namespace {
618
619std::vector<std::string> uris_as_strings(const std::vector<URI>& uris) {
620 std::vector<std::string> out;
621 out.reserve(uris.size());
622 for(const auto& uri : uris) {
623 out.push_back(uri.original_input());
624 }
625 return out;
626}
627
628} // namespace
629
631 if(data().m_ocsp_responders.empty()) {
632 return {};
633 }
634 return data().m_ocsp_responders[0].original_input();
635}
636
637std::vector<std::string> X509_Certificate::ocsp_responders() const {
638 return uris_as_strings(data().m_ocsp_responders);
639}
640
641const std::vector<URI>& X509_Certificate::ocsp_responder_uris() const {
642 return data().m_ocsp_responders;
643}
644
645std::vector<std::string> X509_Certificate::ca_issuers() const {
646 return uris_as_strings(data().m_ca_issuers);
647}
648
649const std::vector<URI>& X509_Certificate::ca_issuer_uris() const {
650 return data().m_ca_issuers;
651}
652
653std::vector<std::string> X509_Certificate::crl_distribution_points() const {
654 return uris_as_strings(data().m_crl_distribution_points);
655}
656
657const std::vector<URI>& X509_Certificate::crl_distribution_point_uris() const {
658 return data().m_crl_distribution_points;
659}
660
662 // just returns the first (arbitrarily)
663 if(!data().m_crl_distribution_points.empty()) {
664 return data().m_crl_distribution_points[0].original_input();
665 }
666 return "";
667}
668
669std::vector<EmailAddress> X509_Certificate::subject_email_addresses() const {
670 const auto& san_emails = subject_alt_name().email_addresses();
671
672 std::vector<EmailAddress> out;
673 out.reserve(san_emails.size());
674
675 for(const auto& addr : san_emails) {
676 out.push_back(addr);
677 }
678
679 for(const auto& dn_email_str : subject_dn().get_attribute("PKCS9.EmailAddress")) {
680 if(auto parsed = EmailAddress::from_string(dn_email_str)) {
681 out.push_back(std::move(*parsed));
682 }
683 }
684
685 return out;
686}
687
689 return data().m_subject_alt_name;
690}
691
693 return data().m_issuer_alt_name;
694}
695
696namespace {
697
698std::vector<std::string> get_cert_user_info(std::string_view req, const X509_DN& dn, const AlternativeName& alt_name) {
699 if(dn.has_field(req)) {
700 return dn.get_attribute(req);
701 } else if(req == "RFC822" || req == "Email") {
702 std::vector<std::string> out;
703 out.reserve(alt_name.email_addresses().size());
704 for(const auto& addr : alt_name.email_addresses()) {
705 out.push_back(addr.to_string());
706 }
707 return out;
708 } else if(req == "DNS") {
709 std::vector<std::string> out;
710 out.reserve(alt_name.dns_names().size());
711 for(const auto& dns : alt_name.dns_names()) {
712 out.push_back(dns.to_string());
713 }
714 return out;
715 } else if(req == "URI") {
716 std::vector<std::string> out;
717 out.reserve(alt_name.uri_names().size());
718 for(const auto& uri : alt_name.uri_names()) {
719 out.push_back(uri.original_input());
720 }
721 return out;
722 } else if(req == "IP") {
723 std::vector<std::string> ip_str;
724 for(const auto& ipv4 : alt_name.ipv4_addresses()) {
725 ip_str.push_back(ipv4.to_string());
726 }
727 return ip_str;
728 } else if(req == "IPv6") {
729 std::vector<std::string> ip_str;
730 for(const auto& ipv6 : alt_name.ipv6_addresses()) {
731 ip_str.push_back(ipv6.to_string());
732 }
733 return ip_str;
734 } else {
735 return {};
736 }
737}
738
739} // namespace
740
741/*
742* Return information about the subject
743*/
744std::vector<std::string> X509_Certificate::subject_info(std::string_view req) const {
745 return get_cert_user_info(req, subject_dn(), subject_alt_name());
746}
747
748/*
749* Return information about the issuer
750*/
751std::vector<std::string> X509_Certificate::issuer_info(std::string_view req) const {
752 return get_cert_user_info(req, issuer_dn(), issuer_alt_name());
753}
754
755/*
756* Return the public key in this certificate
757*/
758std::unique_ptr<Public_Key> X509_Certificate::subject_public_key() const {
759 try {
760 return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
761 } catch(std::exception& e) {
762 throw Decoding_Error("X509_Certificate::subject_public_key", e);
763 }
764}
765
766std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const {
767 return this->subject_public_key();
768}
769
770const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn_sha256() const {
771 if(data().m_issuer_dn_bits_sha256.empty()) {
772 throw Encoding_Error("X509_Certificate::raw_issuer_dn_sha256 called but SHA-256 disabled in build");
773 }
774 return data().m_issuer_dn_bits_sha256;
775}
776
777const std::vector<uint8_t>& X509_Certificate::raw_subject_dn_sha256() const {
778 if(data().m_subject_dn_bits_sha256.empty()) {
779 throw Encoding_Error("X509_Certificate::raw_subject_dn_sha256 called but SHA-256 disabled in build");
780 }
781 return data().m_subject_dn_bits_sha256;
782}
783
784std::span<const uint8_t, 20> X509_Certificate::raw_issuer_dn_sha1() const {
785 return data().m_issuer_dn_bits_sha1;
786}
787
788std::span<const uint8_t, 20> X509_Certificate::raw_subject_dn_sha1() const {
789 return data().m_subject_dn_bits_sha1;
790}
791
792std::string X509_Certificate::fingerprint(std::string_view hash_name) const {
793 /*
794 * The SHA-1 and SHA-256 fingerprints are precomputed since these
795 * are the most commonly used. Especially, SHA-256 fingerprints are
796 * used for cycle detection during path construction.
797 *
798 * If SHA-1 or SHA-256 was missing at parsing time the vectors are
799 * left empty in which case we fall back to create_hex_fingerprint
800 * which will throw if the hash is unavailable.
801 */
802 if(hash_name == "SHA-256" && !data().m_fingerprint_sha256.empty()) {
803 return data().m_fingerprint_sha256;
804 } else if(hash_name == "SHA-1" && !data().m_fingerprint_sha1.empty()) {
805 return data().m_fingerprint_sha1;
806 } else {
807 return create_hex_fingerprint(this->BER_encode(), hash_name);
808 }
809}
810
812 return Tag(data().m_cert_data_sha256);
813}
814
816 const auto& sans = subject_alt_name().dns_names();
817 if(!sans.empty()) {
818 for(const auto& san : sans) {
819 if(name.matches_wildcard(san.name())) {
820 return true;
821 }
822 }
823 return false;
824 }
825
826 /*
827 Fall back to CN for DNS name only if no SAN is included
828 We assume if the issuer knew about SAN then they would have included
829 the DNS name there if the intention was to provide such a name.
830 */
831 if(!data().m_subject_alt_name_exists) {
832 for(const auto& cn : subject_dn().get_attribute("CN")) {
833 if(auto cn_dns = DNSName::from_san_string(cn)) {
834 if(name.matches_wildcard(cn_dns->name())) {
835 return true;
836 }
837 }
838 }
839 }
840
841 return false;
842}
843
844bool X509_Certificate::matches_ip(const IPv4Address& address) const {
845 return subject_alt_name().ipv4_addresses().contains(address);
846}
847
848bool X509_Certificate::matches_ip(const IPv6Address& address) const {
849 return subject_alt_name().ipv6_addresses().contains(address);
850}
851
852bool X509_Certificate::matches_dns_name(std::string_view name) const {
853 if(name.empty()) {
854 return false;
855 }
856
857 if(auto req_ipv4 = IPv4Address::from_string(name)) {
858 return matches_ip(*req_ipv4);
859 }
860
861 if(auto req_ipv6 = IPv6Address::from_string(name)) {
862 return matches_ip(*req_ipv6);
863 }
864
865 if(auto parsed = DNSName::from_string(name)) {
866 return matches_dns_name(*parsed);
867 }
868
869 return false;
870}
871
872/*
873* Compare two certificates for equality
874*/
876 return (this->signature() == other.signature() && this->signature_algorithm() == other.signature_algorithm() &&
877 this->signed_body() == other.signed_body());
878}
879
881 /* If signature values are not equal, sort by lexicographic ordering of that */
882 if(this->signature() != other.signature()) {
883 return (this->signature() < other.signature());
884 }
885
886 // Then compare the signed contents
887 return this->signed_body() < other.signed_body();
888}
889
890/*
891* X.509 Certificate Comparison
892*/
893bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) {
894 return !(cert1 == cert2);
895}
896
897namespace {
898
899void format_alt_name(std::ostream& out, std::string_view label, const AlternativeName& alt_name) {
900 if(alt_name.is_empty()) {
901 return;
902 }
903
904 out << label << ":\n";
905
906 for(const auto& dns : alt_name.dns_names()) {
907 out << " DNS: " << escape_control_chars(dns.to_string()) << "\n";
908 }
909 for(const auto& ipv4 : alt_name.ipv4_addresses()) {
910 out << " IP: " << ipv4.to_string() << "\n";
911 }
912 for(const auto& ipv6 : alt_name.ipv6_addresses()) {
913 out << " IP: " << ipv6.to_string() << "\n";
914 }
915 for(const auto& uri : alt_name.uri_names()) {
916 out << " URI: " << escape_control_chars(uri.original_input()) << "\n";
917 }
918 for(const auto& email : alt_name.email_addresses()) {
919 out << " Email: " << escape_control_chars(email.to_string()) << "\n";
920 }
921 for(const auto& mbox : alt_name.smtp_utf8_mailboxes()) {
922 out << " SmtpUTF8: " << escape_control_chars(mbox.to_string()) << "\n";
923 }
924 for(const auto& dn : alt_name.directory_names()) {
925 out << " DirName: " << dn << "\n";
926 }
927 for(const auto& oid : alt_name.registered_ids()) {
928 out << " RegisteredID: " << oid.to_formatted_string() << "\n";
929 }
930
931 // SmtpUTF8Mailbox values are also retained verbatim in other_name_values;
932 // skip them here since they are already printed in decoded form above
933 const auto smtp_utf8_oid = OID::from_string("PKIX.SmtpUTF8Mailbox");
934 for(const auto& other : alt_name.other_name_values()) {
935 if(other.oid() == smtp_utf8_oid) {
936 continue;
937 }
938 out << " OtherName " << other.oid().to_formatted_string() << ": " << hex_encode(other.value()) << "\n";
939 }
940}
941
942} // namespace
943
944std::string X509_Certificate::to_string() const {
945 std::ostringstream out;
946
947 out << "Version: " << this->x509_version() << "\n";
948 out << "Subject: " << subject_dn() << "\n";
949 out << "Issuer: " << issuer_dn() << "\n";
950 out << "Issued: " << this->not_before().readable_string() << "\n";
951 out << "Expires: " << this->not_after().readable_string() << "\n";
952
953 try {
954 auto pubkey = this->subject_public_key();
955 out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
956 out << X509::PEM_encode(*pubkey) << "\n";
957 } catch(const Decoding_Error& ex) {
958 const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
959 out << "Public Key Invalid!\n"
960 << " OID: " << alg_id.oid().to_formatted_string() << "\n"
961 << " Error: " << ex.what() << "\n"
962 << " Hex: " << hex_encode(this->subject_public_key_bitstring()) << "\n";
963 }
964
965 format_alt_name(out, "Subject Alternative Name", this->subject_alt_name());
966
967 out << "Constraints:\n";
969 if(constraints.empty()) {
970 out << " No key constraints set\n";
971 } else {
973 out << " Digital Signature\n";
974 }
976 out << " Non-Repudiation\n";
977 }
979 out << " Key Encipherment\n";
980 }
982 out << " Data Encipherment\n";
983 }
985 out << " Key Agreement\n";
986 }
988 out << " Cert Sign\n";
989 }
991 out << " CRL Sign\n";
992 }
994 out << " Encipher Only\n";
995 }
997 out << " Decipher Only\n";
998 }
999 }
1000
1001 if(this->is_CA_cert()) {
1002 out << "Basic Constraints: CA";
1003 if(const auto path_len = this->path_length_constraint()) {
1004 out << ", path length " << *path_len;
1005 }
1006 out << "\n";
1007 }
1008
1009 const std::vector<OID>& policies = this->certificate_policy_oids();
1010 if(!policies.empty()) {
1011 out << "Policies: "
1012 << "\n";
1013 for(const auto& oid : policies) {
1014 out << " " << oid.to_string() << "\n";
1015 }
1016 }
1017
1018 const std::vector<OID>& ex_constraints = this->extended_key_usage();
1019 if(!ex_constraints.empty()) {
1020 out << "Extended Constraints:\n";
1021 for(auto&& oid : ex_constraints) {
1022 out << " " << oid.to_formatted_string() << "\n";
1023 }
1024 }
1025
1027
1028 if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty()) {
1029 out << "Name Constraints:\n";
1030
1031 if(!name_constraints.permitted().empty()) {
1032 out << " Permit";
1033 for(const auto& st : name_constraints.permitted()) {
1034 out << " " << st.base();
1035 }
1036 out << "\n";
1037 }
1038
1039 if(!name_constraints.excluded().empty()) {
1040 out << " Exclude";
1041 for(const auto& st : name_constraints.excluded()) {
1042 out << " " << st.base();
1043 }
1044 out << "\n";
1045 }
1046 }
1047
1048 const auto& ocsp_responders = this->ocsp_responder_uris();
1049 if(!ocsp_responders.empty()) {
1050 out << "OCSP Responders:\n";
1051 for(const auto& ocsp_responder : ocsp_responders) {
1052 out << " URI: " << ocsp_responder.original_input() << "\n";
1053 }
1054 }
1055
1056 const auto& ca_issuers = this->ca_issuer_uris();
1057 if(!ca_issuers.empty()) {
1058 out << "CA Issuers:\n";
1059 for(const auto& ca_issuer : ca_issuers) {
1060 out << " URI: " << ca_issuer.original_input() << "\n";
1061 }
1062 }
1063
1064 for(const auto& cdp : crl_distribution_point_uris()) {
1065 out << "CRL " << cdp.original_input() << "\n";
1066 }
1067
1068 out << "Signature algorithm: " << this->signature_algorithm().oid().to_formatted_string() << "\n";
1069
1070 out << "Serial number: " << this->serial().to_string() << "\n";
1071
1072 if(!this->authority_key_id().empty()) {
1073 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
1074 }
1075
1076 if(!this->subject_key_id().empty()) {
1077 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
1078 }
1079
1080 format_alt_name(out, "Issuer Alternative Name", this->issuer_alt_name());
1081
1082 if(this->skip_revocation_check()) {
1083 out << "Revocation status checking is disabled for this certificate\n";
1084 }
1085
1086 if(this->is_self_signed()) {
1087 out << "Certificate is self signed\n";
1088 }
1089
1090 return out.str();
1091}
1092
1093} // namespace Botan
std::vector< uint8_t > BER_encode() const
Definition asn1_obj.cpp:21
std::string readable_string() const
Returns a human friendly string representation of no particular formatting.
const OID & oid() const
Definition asn1_obj.h:688
const std::set< IPv6Address > & ipv6_addresses() const
Return the set of IPv6 addresses included in this alternative name.
Definition pkix_types.h:423
const std::set< DNSName > & dns_names() const
Return the set of DNS names included in this alternative name.
Definition pkix_types.h:409
const std::set< EmailAddress > & email_addresses() const
Return the set of email addresses included in this alternative name.
Definition pkix_types.h:400
const std::set< IPv4Address > & ipv4_addresses() const
Return the set of IPv4 addresses included in this alternative name.
Definition pkix_types.h:420
const std::set< URI > & uri_names() const
Return the set of URIs included in this alternative name.
Definition pkix_types.h:391
static Limits DER()
Definition ber_dec.h:42
BER_Decoder & decode(bool &out)
Definition ber_dec.h:358
BER_Decoder & verify_end()
Definition ber_dec.cpp:471
BER_Decoder & decode_octet_aligned_bitstring(std::vector< uint8_t, Alloc > &out, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:462
bool matches_wildcard(std::string_view wildcard) const
Definition dns_name.cpp:186
static std::optional< DNSName > from_san_string(std::string_view name)
Definition dns_name.cpp:149
static std::optional< DNSName > from_string(std::string_view name)
Definition dns_name.cpp:136
static std::optional< EmailAddress > from_string(std::string_view addr)
Definition email.cpp:78
const char * what() const noexcept override
Definition exceptn.h:94
bool critical_extension_set(const OID &oid) const
Definition x509_ext.cpp:239
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< IPv4Address > from_string(std::string_view str)
static std::optional< IPv6Address > from_string(std::string_view str)
bool includes(Key_Constraints::Bits other) const
Definition pkix_enums.h:186
Name Constraints.
Definition pkix_types.h:750
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:768
std::string to_formatted_string() const
Definition asn1_oid.cpp:137
static std::optional< OID > from_name(std::string_view name)
Definition asn1_oid.cpp:66
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
const std::vector< OID > & extended_key_usage() const
Definition x509cert.cpp:507
bool is_CA_cert() const
Definition x509cert.cpp:483
Key_Constraints constraints() const
Definition x509cert.cpp:503
bool operator==(const X509_Certificate &other) const
Definition x509cert.cpp:875
const NameConstraints & name_constraints() const
Definition x509cert.cpp:515
std::vector< std::string > ocsp_responders() const
Definition x509cert.cpp:637
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:613
const std::vector< uint8_t > & serial_number() const
Definition x509cert.cpp:440
std::string fingerprint(std::string_view hash_name="SHA-1") const
Definition x509cert.cpp:792
const std::vector< URI > & ocsp_responder_uris() const
Definition x509cert.cpp:641
const X509_DN & subject_dn() const
Definition x509cert.cpp:460
bool skip_revocation_check() const
Definition x509cert.cpp:452
uint32_t path_limit() const
Definition x509cert.cpp:491
const X509_Serial_Number & serial() const
Definition x509cert.cpp:444
const X509_Time & not_after() const
Definition x509cert.cpp:392
const std::vector< uint8_t > & authority_key_id() const
Definition x509cert.cpp:432
std::span< const uint8_t, 32 > certificate_data_sha256() const
Definition x509cert.cpp:479
bool allowed_extended_usage(std::string_view usage) const
Definition x509cert.cpp:535
const AlternativeName & issuer_alt_name() const
Definition x509cert.cpp:692
const std::vector< uint8_t > & raw_subject_dn() const
Definition x509cert.cpp:468
const std::vector< uint8_t > & subject_key_id() const
Definition x509cert.cpp:436
~X509_Certificate() override
std::span< const uint8_t, 32 > subject_public_key_bitstring_sha256() const
Definition x509cert.cpp:428
const std::vector< uint8_t > & subject_public_key_bits() const
Definition x509cert.cpp:408
bool has_constraints(Key_Constraints constraints) const
Definition x509cert.cpp:523
std::optional< size_t > path_length_constraint() const
Definition x509cert.cpp:499
const Extensions & v3_extensions() const
Definition x509cert.cpp:519
bool has_ex_constraint(std::string_view ex_constraint) const
Definition x509cert.cpp:582
std::vector< std::string > crl_distribution_points() const
Definition x509cert.cpp:653
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition x509cert.cpp:420
bool allowed_usage(Key_Constraints usage) const
Definition x509cert.cpp:528
const X509_DN & issuer_dn() const
Definition x509cert.cpp:456
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition x509cert.cpp:400
std::string ocsp_responder() const
Definition x509cert.cpp:630
std::span< const uint8_t, 20 > certificate_data_sha1() const
Definition x509cert.cpp:472
bool matches_dns_name(std::string_view name) const
Definition x509cert.cpp:852
std::vector< std::string > subject_info(std::string_view name) const
Definition x509cert.cpp:744
const std::vector< uint8_t > & raw_subject_dn_sha256() const
Definition x509cert.cpp:777
const std::vector< URI > & crl_distribution_point_uris() const
Definition x509cert.cpp:657
uint32_t x509_version() const
Definition x509cert.cpp:380
const std::vector< URI > & ca_issuer_uris() const
Definition x509cert.cpp:649
std::string crl_distribution_point() const
Definition x509cert.cpp:661
const std::vector< OID > & certificate_policy_oids() const
Definition x509cert.cpp:511
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition x509cert.cpp:766
X509_Certificate(DataSource &source)
Definition x509cert.cpp:96
bool is_self_signed() const
Definition x509cert.cpp:384
bool matches_ip(const IPv4Address &address) const
Definition x509cert.cpp:844
const std::vector< uint8_t > & raw_issuer_dn() const
Definition x509cert.cpp:464
bool operator<(const X509_Certificate &other) const
Definition x509cert.cpp:880
std::span< const uint8_t, 20 > raw_subject_dn_sha1() const
Definition x509cert.cpp:788
const std::vector< uint8_t > & raw_issuer_dn_sha256() const
Definition x509cert.cpp:770
const AlgorithmIdentifier & subject_public_key_algo() const
Definition x509cert.cpp:396
const AlternativeName & subject_alt_name() const
Definition x509cert.cpp:688
std::vector< std::string > ca_issuers() const
Definition x509cert.cpp:645
const std::vector< uint8_t > & subject_public_key_info() const
Definition x509cert.cpp:412
std::vector< EmailAddress > subject_email_addresses() const
Definition x509cert.cpp:669
bool is_serial_negative() const
Definition x509cert.cpp:448
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition x509cert.cpp:416
std::unique_ptr< Public_Key > subject_public_key() const
Definition x509cert.cpp:758
const std::vector< uint8_t > & v2_subject_key_id() const
Definition x509cert.cpp:404
const X509_Time & not_before() const
Definition x509cert.cpp:388
std::vector< std::string > issuer_info(std::string_view name) const
Definition x509cert.cpp:751
std::span< const uint8_t, 20 > raw_issuer_dn_sha1() const
Definition x509cert.cpp:784
std::string to_string() const
Definition x509cert.cpp:944
bool has_field(const OID &oid) const
Definition x509_dn.cpp:213
std::vector< std::string > get_attribute(std::string_view attr) const
Definition x509_dn.cpp:245
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::string to_string() const
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition asn1_obj.cpp:208
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:27
ASN1_Type
Definition asn1_obj.h:47
std::string create_hex_fingerprint(std::span< const uint8_t > bits, std::string_view hash_name)
Definition pk_keys.cpp:38
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition hex.cpp:34
bool operator!=(const AlgorithmIdentifier &x, const AlgorithmIdentifier &y)
Definition alg_id.cpp:58
std::string format_hex_fingerprint(std::span< const uint8_t > bits)
Definition pk_keys.cpp:45
std::string escape_control_chars(std::string_view utf8)
Definition charset.cpp:207