9#include <botan/x509cert.h>
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>
17#include <botan/pk_keys.h>
18#include <botan/x509_ext.h>
19#include <botan/x509_key.h>
20#include <botan/internal/parsing.h>
25class X509_Certificate_Data final {
27 std::vector<uint8_t> m_serial;
28 AlgorithmIdentifier m_sig_algo_inner;
31 std::vector<uint8_t> m_issuer_dn_bits;
32 std::vector<uint8_t> m_subject_dn_bits;
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;
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;
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;
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;
54 std::vector<uint8_t> m_issuer_dn_bits_sha256;
55 std::vector<uint8_t> m_subject_dn_bits_sha256;
57 std::string m_fingerprint_sha1;
58 std::string m_fingerprint_sha256;
60 std::array<uint8_t, 20> m_cert_data_sha1 = {};
61 std::array<uint8_t, 32> m_cert_data_sha256 = {};
63 AlternativeName m_subject_alt_name;
64 AlternativeName m_issuer_alt_name;
65 NameConstraints m_name_constraints;
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;
83 return {
"X509 CERTIFICATE"};
95#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
104std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(
const X509_Object& obj) {
105 auto data = std::make_unique<X509_Certificate_Data>();
108 BER_Object public_key;
109 BER_Object v3_exts_data;
114 .decode(data->m_sig_algo_inner)
115 .decode(data->m_issuer_dn)
117 .decode(data->m_not_before)
118 .decode(data->m_not_after)
120 .decode(data->m_subject_dn)
121 .get_next(public_key)
124 .get_next(v3_exts_data)
125 .verify_end(
"TBSCertificate has extra data after extensions block");
127 if(data->m_version > 2) {
128 throw Decoding_Error(
"Unknown X.509 cert version " + std::to_string(data->m_version));
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");
137 data->m_version += 1;
139 data->m_serial = serial_bn.serialize();
141 data->m_serial_negative = serial_bn.signum() < 0;
145 data->m_subject_public_key_bits.assign(public_key.bits(), public_key.bits() + public_key.length());
150 .
decode(data->m_subject_public_key_algid)
157 }
else if(v3_exts_data.is_set()) {
158 throw BER_Bad_Tag(
"Unknown tag in X.509 cert", v3_exts_data.tagging());
163 data->m_key_constraints = ext->get_constraints();
168 if(data->m_key_constraints.empty()) {
169 throw Decoding_Error(
"Certificate has invalid encoding for KeyUsage");
174 data->m_subject_key_id = ext->get_key_id();
178 data->m_authority_key_id = ext->get_key_id();
182 data->m_name_constraints = ext->get_name_constraints();
186 data->m_extended_key_usage = ext->object_identifiers();
198 if(data->m_extended_key_usage.empty()) {
199 throw Decoding_Error(
"Certificate has invalid empty EKU extension");
209 if(ext->is_ca() ==
true) {
217 const bool allowed_by_ku =
232 const bool allowed_by_ext_ku = [](
const std::vector<OID>& ext_ku) ->
bool {
240 const auto any_eku =
OID::from_name(
"X509v3.AnyExtendedKeyUsage");
242 for(
const auto& oid : ext_ku) {
243 if(oid == any_eku || oid == server_auth || oid == client_auth || oid == ocsp_sign) {
249 }(data->m_extended_key_usage);
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();
259 data->m_issuer_alt_name = ext->get_alt_name();
263 data->m_subject_alt_name = ext->get_alt_name();
270 data->m_subject_alt_name_exists = data->m_v3_extensions.extension_set(san_oid);
273 data->m_cert_policies = ext->get_policy_oids();
277 data->m_ocsp_responders = ext->ocsp_responders();
278 data->m_ca_issuers = ext->ca_issuers();
282 data->m_crl_distribution_points = ext->crl_distribution_urls();
290 if(data->m_subject_dn == data->m_issuer_dn) {
291 if(!data->m_subject_key_id.empty() && !data->m_authority_key_id.empty()) {
296 data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
302 data->m_self_signed =
true;
306 const std::vector<uint8_t> full_encoding = obj.BER_encode();
309 sha1->update(data->m_subject_public_key_bitstring);
310 data->m_subject_public_key_bitstring_sha1 = sha1->final_stdvec();
313 sha1->update(full_encoding);
314 sha1->final(data->m_cert_data_sha1);
320 sha256->update(data->m_issuer_dn_bits);
321 data->m_issuer_dn_bits_sha256 = sha256->final_stdvec();
323 sha256->update(data->m_subject_dn_bits);
324 data->m_subject_dn_bits_sha256 = sha256->final_stdvec();
326 sha256->update(full_encoding);
327 sha256->final(data->m_cert_data_sha256);
338void X509_Certificate::force_decode() {
340 m_data = parse_x509_cert_body(*
this);
343const X509_Certificate_Data& X509_Certificate::data()
const {
344 if(m_data ==
nullptr) {
345 throw Invalid_State(
"X509_Certificate uninitialized");
351 return static_cast<uint32_t
>(data().m_version);
355 return data().m_self_signed;
359 return data().m_not_before;
363 return data().m_not_after;
367 return data().m_subject_public_key_algid;
371 return data().m_v2_issuer_key_id;
375 return data().m_v2_subject_key_id;
379 return data().m_subject_public_key_bits;
383 return data().m_subject_public_key_bits_seq;
387 return data().m_subject_public_key_bitstring;
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");
395 return data().m_subject_public_key_bitstring_sha1;
399 return data().m_authority_key_id;
403 return data().m_subject_key_id;
407 return data().m_serial;
411 return data().m_serial_negative;
415 return data().m_issuer_dn;
419 return data().m_subject_dn;
423 return data().m_issuer_dn_bits;
427 return data().m_subject_dn_bits;
431 if(data().m_fingerprint_sha1.empty()) {
434 return data().m_cert_data_sha1;
438 return data().m_cert_data_sha256;
442 if(data().m_version < 3 && data().m_self_signed) {
446 return data().m_is_ca_certificate;
450 if(data().m_version < 3 && data().m_self_signed) {
454 return static_cast<uint32_t
>(data().m_path_len_constraint.value_or(Cert_Extension::NO_CERT_PATH_LIMIT));
458 return data().m_path_len_constraint;
462 return data().m_key_constraints;
466 return data().m_extended_key_usage;
470 return data().m_cert_policies;
474 return data().m_name_constraints;
478 return data().m_v3_extensions;
545 const auto any_eku =
OID::from_name(
"X509v3.AnyExtendedKeyUsage");
549 if(ext_ku == usage) {
560 if(ext_ku == any_eku && usage != ocsp_eku) {
576 if(data().m_ocsp_responders.empty()) {
579 return data().m_ocsp_responders[0];
583 return data().m_ocsp_responders;
587 return data().m_ca_issuers;
591 return data().m_crl_distribution_points;
596 if(!data().m_crl_distribution_points.empty()) {
597 return data().m_crl_distribution_points[0];
603 return data().m_subject_alt_name;
607 return data().m_issuer_alt_name;
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()}; };
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;
629 }
else if(req ==
"IPv6") {
630 std::vector<std::string> ip_str;
632 ip_str.push_back(ipv6.to_string());
662 }
catch(std::exception& e) {
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");
675 return data().m_issuer_dn_bits_sha256;
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");
682 return data().m_subject_dn_bits_sha256;
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;
705 return Tag(data().m_cert_data_sha256);
715 return ipv4_names.contains(req_ipv4.value());
720 return ipv6_names.contains(req_ipv6.value());
726 if(!data().m_subject_alt_name_exists) {
730 for(
const auto& issued_name : issued_names) {
761 return !(cert1 == cert2);
765 std::ostringstream out;
769 out <<
"Issuer: " <<
issuer_dn() <<
"\n";
775 out <<
"Public Key [" << pubkey->algo_name() <<
"-" << pubkey->key_length() <<
"]\n\n";
779 out <<
"Public Key Invalid!\n"
781 <<
" Error: " << ex.
what() <<
"\n"
785 out <<
"Constraints:\n";
787 if(constraints.
empty()) {
788 out <<
" No key constraints set\n";
791 out <<
" Digital Signature\n";
794 out <<
" Non-Repudiation\n";
797 out <<
" Key Encipherment\n";
800 out <<
" Data Encipherment\n";
803 out <<
" Key Agreement\n";
806 out <<
" Cert Sign\n";
809 out <<
" CRL Sign\n";
812 out <<
" Encipher Only\n";
815 out <<
" Decipher Only\n";
820 if(!policies.empty()) {
823 for(
const auto& oid : policies) {
824 out <<
" " << oid.to_string() <<
"\n";
829 if(!ex_constraints.empty()) {
830 out <<
"Extended Constraints:\n";
831 for(
auto&& oid : ex_constraints) {
832 out <<
" " << oid.to_formatted_string() <<
"\n";
839 out <<
"Name Constraints:\n";
844 out <<
" " << st.base();
852 out <<
" " << st.base();
860 out <<
"OCSP Responders:\n";
867 if(!ca_issuers.empty()) {
868 out <<
"CA Issuers:\n";
870 out <<
" URI: " << ca_issuer <<
"\n";
875 out <<
"CRL " << cdp <<
"\n";
891 out <<
"Certificate is self signed\n";
std::vector< uint8_t > BER_encode() const
std::string readable_string() const
Returns a human friendly string representation of no particular formatting.
const std::set< uint32_t > & ipv4_address() const
Return the set of IPv4 addresses included in this alternative name.
const std::set< std::string > & uris() const
Return the set of URIs included in this alternative name.
const std::set< std::string > & dns() const
Return the set of DNS names included in this alternative name.
const std::set< IPv6Address > & ipv6_address() const
Return the set of IPv6 addresses included in this alternative name.
const std::set< std::string > & email() const
Return the set of email addresses included in this alternative name.
BER_Decoder & decode(bool &out)
BER_Decoder & verify_end()
const char * what() const noexcept override
bool critical_extension_set(const OID &oid) const
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
static std::optional< IPv6Address > from_string(std::string_view str)
bool includes(Key_Constraints::Bits other) const
const std::vector< GeneralSubtree > & permitted() const
std::string to_formatted_string() const
static std::optional< OID > from_name(std::string_view name)
static OID from_string(std::string_view str)
const std::vector< OID > & extended_key_usage() const
Key_Constraints constraints() const
bool operator==(const X509_Certificate &other) const
const NameConstraints & name_constraints() const
X509_Certificate()=default
bool is_critical(std::string_view ex_name) const
const std::vector< uint8_t > & serial_number() const
std::string fingerprint(std::string_view hash_name="SHA-1") const
const X509_DN & subject_dn() const
uint32_t path_limit() const
const X509_Time & not_after() const
const std::vector< uint8_t > & authority_key_id() const
std::span< const uint8_t, 32 > certificate_data_sha256() const
bool allowed_extended_usage(std::string_view usage) const
const AlternativeName & issuer_alt_name() const
const std::vector< uint8_t > & raw_subject_dn() const
const std::vector< uint8_t > & subject_key_id() const
~X509_Certificate() override
const std::vector< uint8_t > & subject_public_key_bits() const
bool has_constraints(Key_Constraints constraints) const
std::optional< size_t > path_length_constraint() const
const Extensions & v3_extensions() const
bool has_ex_constraint(std::string_view ex_constraint) const
std::vector< std::string > crl_distribution_points() const
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
bool allowed_usage(Key_Constraints usage) const
const X509_DN & issuer_dn() const
const std::vector< uint8_t > & v2_issuer_key_id() const
std::string ocsp_responder() const
std::span< const uint8_t, 20 > certificate_data_sha1() const
bool matches_dns_name(std::string_view name) const
std::vector< std::string > subject_info(std::string_view name) const
const std::vector< uint8_t > & raw_subject_dn_sha256() const
uint32_t x509_version() const
std::string crl_distribution_point() const
const std::vector< OID > & certificate_policy_oids() const
std::unique_ptr< Public_Key > load_subject_public_key() const
X509_Certificate(DataSource &source)
bool is_self_signed() const
const std::vector< uint8_t > & raw_issuer_dn() const
bool operator<(const X509_Certificate &other) const
const std::vector< uint8_t > & raw_issuer_dn_sha256() const
const AlgorithmIdentifier & subject_public_key_algo() const
const std::vector< std::string > & ocsp_responders() const
const AlternativeName & subject_alt_name() const
std::vector< std::string > ca_issuers() const
const std::vector< uint8_t > & subject_public_key_info() const
bool is_serial_negative() const
const std::vector< uint8_t > & subject_public_key_bitstring() const
std::unique_ptr< Public_Key > subject_public_key() const
const std::vector< uint8_t > & v2_subject_key_id() const
const X509_Time & not_before() const
std::vector< std::string > issuer_info(std::string_view name) const
std::string to_string() const
bool has_field(const OID &oid) const
std::vector< std::string > get_attribute(std::string_view attr) const
const std::vector< uint8_t > & signed_body() const
const AlgorithmIdentifier & signature_algorithm() const
virtual std::vector< std::string > alternate_PEM_labels() const
const std::vector< uint8_t > & signature() const
void load_data(DataSource &src)
virtual std::string PEM_label() const =0
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
std::unique_ptr< Public_Key > load_key(DataSource &source)
std::string PEM_encode(const Public_Key &key)
std::string create_hex_fingerprint(std::span< const uint8_t > bits, std::string_view hash_name)
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
std::optional< uint32_t > string_to_ipv4(std::string_view str)
std::string format_hex_fingerprint(std::span< const uint8_t > bits)
std::string ipv4_to_string(uint32_t ip)
bool host_wildcard_match(std::string_view issued, std::string_view host)