9 #include <botan/x509cert.h>
10 #include <botan/x509_ext.h>
11 #include <botan/der_enc.h>
12 #include <botan/ber_dec.h>
13 #include <botan/internal/stl_util.h>
14 #include <botan/parsing.h>
15 #include <botan/bigint.h>
16 #include <botan/oids.h>
17 #include <botan/pem.h>
18 #include <botan/hash.h>
19 #include <botan/hex.h>
31 std::vector<std::string> lookup_oids(
const std::vector<std::string>& in)
33 std::vector<std::string> out;
35 for(
auto i = in.begin(); i != in.end(); ++i)
48 m_v3_extensions(false)
53 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
57 X509_Certificate::X509_Certificate(
const std::string& fsname) :
58 X509_Object(fsname,
"CERTIFICATE/X509 CERTIFICATE"),
60 m_v3_extensions(false)
69 X509_Certificate::X509_Certificate(
const std::vector<uint8_t>& in) :
72 m_v3_extensions(false)
80 void X509_Certificate::force_decode()
90 tbs_cert.decode_optional(version,
ASN1_Tag(0),
93 .decode(sig_algo_inner)
113 BER_Object public_key = tbs_cert.get_next_object();
115 throw BER_Bad_Tag(
"X509_Certificate: Unexpected tag for public key",
118 std::vector<uint8_t> v2_issuer_key_id, v2_subject_key_id;
120 tbs_cert.decode_optional_string(v2_issuer_key_id,
BIT_STRING, 1);
121 tbs_cert.decode_optional_string(v2_subject_key_id,
BIT_STRING, 2);
123 BER_Object v3_exts_data = tbs_cert.get_next_object();
131 throw BER_Bad_Tag(
"Unknown tag in X.509 cert",
134 if(tbs_cert.more_items())
135 throw Decoding_Error(
"TBSCertificate has more items that expected");
137 m_subject.
add(
"X509.Certificate.version", static_cast<uint32_t>(version));
139 m_subject.
add(
"X509.Certificate.start", start.
to_string());
142 m_issuer.
add(
"X509.Certificate.v2.key_id", v2_issuer_key_id);
143 m_subject.
add(
"X509.Certificate.v2.key_id", v2_subject_key_id);
147 m_self_signed =
false;
148 if(dn_subject == dn_issuer)
154 if(m_self_signed && version == 0)
156 m_subject.
add(
"X509v3.BasicConstraints.is_ca", 1);
157 m_subject.
add(
"X509v3.BasicConstraints.path_constraint", Cert_Extension::NO_CERT_PATH_LIMIT);
161 !m_subject.
has_value(
"X509v3.BasicConstraints.path_constraint"))
164 Cert_Extension::NO_CERT_PATH_LIMIT : 0;
166 m_subject.
add(
"X509v3.BasicConstraints.path_constraint", static_cast<uint32_t>(limit));
175 return (m_subject.
get1_uint32(
"X509.Certificate.version") + 1);
183 return m_subject.
get1(
"X509.Certificate.start");
191 return m_subject.
get1(
"X509.Certificate.end");
197 std::vector<std::string>
206 std::vector<std::string>
232 std::vector<uint8_t> public_key_bitstr;
235 .decode(public_key_algid)
238 return public_key_bitstr;
246 return hash->final_stdvec();
254 if(!m_subject.
get1_uint32(
"X509v3.BasicConstraints.is_ca"))
274 if(std::find(ex.begin(), ex.end(), usage) != ex.end())
324 if(std::find(ex.begin(), ex.end(), ex_constraint) != ex.end())
337 return m_subject.
get1_uint32(
"X509v3.BasicConstraints.path_constraint", 0);
345 return !!m_subject.
get1_uint32(ex_name +
".is_critical",0);
362 return lookup_oids(m_subject.
get(
"X509v3.ExtendedKeyUsage"));
370 std::vector<GeneralSubtree> permit, exclude;
372 for(
const std::string& v: m_subject.
get(
"X509v3.NameConstraints.permitted"))
377 for(
const std::string& v: m_subject.
get(
"X509v3.NameConstraints.excluded"))
390 return lookup_oids(m_subject.
get(
"X509v3.CertificatePolicies"));
395 return m_v3_extensions;
400 return m_subject.
get1(
"OCSP.responder",
"");
405 return m_subject.
get1(
"CRL.DistributionPoint",
"");
413 return m_issuer.
get1_memvec(
"X509v3.AuthorityKeyIdentifier");
421 return m_subject.
get1_memvec(
"X509v3.SubjectKeyIdentifier");
429 return m_subject.
get1_memvec(
"X509.Certificate.serial");
439 return m_issuer.
get1_memvec(
"X509.Certificate.dn_bits");
446 return hash->final_stdvec();
456 return m_subject.
get1_memvec(
"X509.Certificate.dn_bits");
463 return hash->final_stdvec();
470 const auto hex_print =
hex_encode(hash->final());
472 std::string formatted_print;
474 for(
size_t i = 0; i != hex_print.size(); i += 2)
476 formatted_print.push_back(hex_print[i]);
477 formatted_print.push_back(hex_print[i+1]);
479 if(i != hex_print.size() - 2)
480 formatted_print.push_back(
':');
483 return formatted_print;
491 std::vector<std::string> issued_names =
subject_info(
"DNS");
494 if(issued_names.empty())
497 for(
size_t i = 0; i != issued_names.size(); ++i)
513 m_self_signed == other.m_self_signed &&
514 m_issuer == other.m_issuer &&
515 m_subject == other.m_subject);
537 return !(cert1 == cert2);
542 const std::vector<std::string> dn_fields{
546 "Organizational Unit",
556 std::ostringstream out;
558 for(
auto&& field : dn_fields)
562 out <<
"Subject " << field <<
": " << val <<
"\n";
566 for(
auto&& field : dn_fields)
570 out <<
"Issuer " << field <<
": " << val <<
"\n";
576 out <<
"Not valid before: " << this->
start_time() <<
"\n";
577 out <<
"Not valid after: " << this->
end_time() <<
"\n";
579 out <<
"Constraints:\n";
586 out <<
" Digital Signature\n";
588 out <<
" Non-Repudiation\n";
590 out <<
" Key Encipherment\n";
592 out <<
" Data Encipherment\n";
594 out <<
" Key Agreement\n";
596 out <<
" Cert Sign\n";
598 out <<
" CRL Sign\n";
600 out <<
" Encipher Only\n";
602 out <<
" Decipher Only\n";
606 if(!policies.empty())
608 out <<
"Policies: " <<
"\n";
609 for(
size_t i = 0; i != policies.size(); i++)
610 out <<
" " << policies[i] <<
"\n";
614 if(!ex_constraints.empty())
616 out <<
"Extended Constraints:\n";
617 for(
size_t i = 0; i != ex_constraints.size(); i++)
618 out <<
" " << ex_constraints[i] <<
"\n";
622 if(!name_constraints.
permitted().empty() ||
623 !name_constraints.
excluded().empty())
625 out <<
"Name Constraints:\n";
627 if(!name_constraints.
permitted().empty())
630 for(
auto st: name_constraints.
permitted())
632 out <<
" " << st.base();
637 if(!name_constraints.
excluded().empty())
640 for(
auto st: name_constraints.
excluded())
642 out <<
" " << st.base();
653 out <<
"Signature algorithm: " <<
676 [](
const std::string& key,
const std::string&)
678 return (key.find(
"X520.") != std::string::npos);
683 for(
auto i = names.begin(); i != names.end(); ++i)
695 [](
const std::string& key,
const std::string&)
697 return (key ==
"RFC822" ||
705 for(
auto i = names.begin(); i != names.end(); ++i)
AlgorithmIdentifier m_sig_algo
std::vector< uint8_t > get1_memvec(const std::string &) const
void add_attribute(const std::string &, const std::string &)
bool operator==(const X509_Certificate &other) const
std::vector< uint8_t > serial_number() const
std::vector< uint8_t > BER_encode() const
uint32_t get1_uint32(const std::string &, uint32_t=0) const
std::multimap< std::string, std::string > search_for(std::function< bool(std::string, std::string)> predicate) const
std::vector< uint8_t > subject_public_key_bitstring() const
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
bool matches_dns_name(const std::string &name) const
Public_Key * load_key(DataSource &source)
std::string ocsp_responder() const
Key_Constraints constraints() const
std::vector< uint8_t > get_bits() const
const std::vector< GeneralSubtree > & permitted() const
std::vector< uint8_t > raw_subject_dn() const
void add_attribute(const std::string &, const std::string &)
std::string to_string(const BER_Object &obj)
bool allowed_usage(Key_Constraints usage) const
std::string crl_distribution_point() const
void contents_to(Data_Store &, Data_Store &) const
std::string get1(const std::string &key) const
NameConstraints name_constraints() const
std::string fingerprint(const std::string &hash_name="SHA-1") const
const std::vector< GeneralSubtree > & excluded() const
std::vector< uint8_t > m_tbs_bits
secure_vector< uint8_t > value
Extensions v3_extensions() const
std::vector< uint8_t > subject_public_key_bits() const
X509_DN create_dn(const Data_Store &info)
std::string end_time() const
AlternativeName create_alt_name(const Data_Store &info)
std::string to_string() const
std::vector< uint8_t > subject_public_key_bitstring_sha1() const
std::string lookup(const OID &oid)
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
bool has_ex_constraint(const std::string &ex_constraint) const
std::string start_time() const
std::vector< uint8_t > raw_issuer_dn_sha256() const
std::string PEM_encode(const Public_Key &key)
bool operator<(const X509_Certificate &other) const
A single Name Constraint.
uint32_t x509_version() const
std::vector< std::string > policies() const
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
std::string to_string() const
Return an internal string representation of the time.
bool check_signature(const Public_Key &key) const
bool has_value(const std::string &) const
std::vector< uint8_t > raw_issuer_dn() const
std::vector< uint8_t > raw_subject_dn_sha256() const
uint32_t path_limit() const
X509_DN issuer_dn() const
std::vector< std::string > subject_info(const std::string &name) const
bool is_critical(const std::string &ex_name) const
std::vector< std::string > ex_constraints() const
std::vector< uint8_t > subject_key_id() const
bool allowed_extended_usage(const std::string &usage) const
static std::string deref_info_field(const std::string &)
std::vector< std::string > issuer_info(const std::string &name) const
Public_Key * subject_public_key() const
bool has_constraints(Key_Constraints constraints) const
Returns true if the specified.
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
std::multimap< std::string, std::string > contents() const
bool host_wildcard_match(const std::string &issued, const std::string &host)
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
static std::vector< uint8_t > encode(const BigInt &n, Base base=Binary)
X509_DN subject_dn() const
std::vector< std::string > get(const std::string &) const
std::vector< uint8_t > m_sig
AlgorithmIdentifier signature_algorithm() const
std::vector< uint8_t > authority_key_id() const
void add(const std::multimap< std::string, std::string > &)