aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/examples/x509info.cpp10
-rw-r--r--include/x509cert.h14
-rw-r--r--src/x509cert.cpp258
-rw-r--r--src/x509find.cpp7
-rw-r--r--src/x509stor.cpp4
5 files changed, 115 insertions, 178 deletions
diff --git a/doc/examples/x509info.cpp b/doc/examples/x509info.cpp
index 87ffcc30f..343628922 100644
--- a/doc/examples/x509info.cpp
+++ b/doc/examples/x509info.cpp
@@ -26,20 +26,18 @@ std::string to_hex(const SecureVector<byte>& bin)
return "(none)";
}
-void do_print(const std::string& what, const std::string& vals)
- // const std::vector<std::string>& vals)
+void do_print(const std::string& what,
+ const std::vector<std::string>& vals)
{
if(vals.size() == 0)
return;
std::cout << " " << what << ": ";
- std::cout << vals;
- //std::copy(vals.begin(), vals.end(),
- // std::ostream_iterator<std::string>(std::cout, " "));
+ std::copy(vals.begin(), vals.end(),
+ std::ostream_iterator<std::string>(std::cout, " "));
std::cout << "\n";
}
-
void do_subject(const X509_Certificate& cert, const std::string& what)
{
do_print(what, cert.subject_info(what));
diff --git a/include/x509cert.h b/include/x509cert.h
index 0a6d0ec83..cc90b450e 100644
--- a/include/x509cert.h
+++ b/include/x509cert.h
@@ -25,8 +25,8 @@ class X509_Certificate : public X509_Object
X509_DN issuer_dn() const;
X509_DN subject_dn() const;
- std::string subject_info(const std::string&) const;
- std::string issuer_info(const std::string&) const;
+ std::vector<std::string> subject_info(const std::string&) const;
+ std::vector<std::string> issuer_info(const std::string&) const;
std::string start_time() const;
std::string end_time() const;
@@ -36,7 +36,7 @@ class X509_Certificate : public X509_Object
MemoryVector<byte> authority_key_id() const;
MemoryVector<byte> subject_key_id() const;
- bool self_signed() const;
+ bool is_self_signed() const { return self_signed; }
bool is_CA_cert() const;
u32bit path_limit() const;
@@ -49,15 +49,13 @@ class X509_Certificate : public X509_Object
X509_Certificate(DataSource&);
X509_Certificate(const std::string&);
private:
+ void force_decode();
friend class X509_CA;
X509_Certificate() {}
- void force_decode();
-
void handle_v3_extension(const Extension&);
- Data_Store info;
- std::multimap<std::string, std::string> subject, issuer;
- bool is_ca;
+ Data_Store subject, issuer;
+ bool self_signed, is_ca;
};
/*************************************************
diff --git a/src/x509cert.cpp b/src/x509cert.cpp
index 9f8fe85a2..1313d9590 100644
--- a/src/x509cert.cpp
+++ b/src/x509cert.cpp
@@ -10,97 +10,38 @@
#include <botan/stl_util.h>
#include <botan/parsing.h>
#include <botan/bigint.h>
-#include <botan/conf.h>
#include <botan/oids.h>
#include <botan/pem.h>
#include <algorithm>
-#include <assert.h>
-
namespace Botan {
namespace {
/*************************************************
-* Get information from the DistinguishedName *
-*************************************************/
-void load_info(std::multimap<std::string, std::string>& names,
- const X509_DN& dn_info)
- {
- typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
- std::multimap<OID, std::string> attr = dn_info.get_attributes();
-
- for(rdn_iter j = attr.begin(); j != attr.end(); ++j)
- {
- const std::string oid_name = OIDS::lookup(j->first);
-
- if(oid_name == "PKCS9.EmailAddress")
- multimap_insert(names, std::string("RFC822"), j->second);
- else
- multimap_insert(names, oid_name, j->second);
- }
- }
-
-/*************************************************
-* Get information from the alternative name *
-*************************************************/
-void load_info(std::multimap<std::string, std::string>& names,
- const AlternativeName& alt_info)
- {
- typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
- std::multimap<std::string, std::string> attr = alt_info.get_attributes();
-
- for(rdn_iter j = attr.begin(); j != attr.end(); ++j)
- multimap_insert(names, j->first, j->second);
-
- typedef std::multimap<OID, ASN1_String>::const_iterator on_iter;
- std::multimap<OID, ASN1_String> othernames = alt_info.get_othernames();
- for(on_iter j = othernames.begin(); j != othernames.end(); ++j)
- multimap_insert(names, OIDS::lookup(j->first), j->second.value());
- }
-
-/*************************************************
-* Get some information from names *
+* Create and populate a X509_DN *
*************************************************/
-std::string get_info(const std::multimap<std::string, std::string>& names,
- const std::string& info)
+X509_DN create_dn(const Data_Store& info)
{
- typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
-
- const std::string what = X509_DN::deref_info_field(info);
- std::pair<rdn_iter, rdn_iter> range = names.equal_range(what);
-
- std::vector<std::string> results;
- for(rdn_iter j = range.first; j != range.second; ++j)
+ class DN_Matcher : public Data_Store::Matcher
{
- if(std::find(results.begin(), results.end(), j->second) == results.end())
- results.push_back(j->second);
- }
-
- std::string value;
- for(u32bit j = 0; j != results.size(); ++j)
- value += results[j] + '/';
- if(value.size())
- value.erase(value.size() - 1, 1);
- return value;
- }
+ public:
+ bool operator()(const std::string& key, const std::string&) const
+ {
+ if(key.find("X520.") != std::string::npos)
+ return true;
+ return false;
+ }
+ };
+
+ std::multimap<std::string, std::string> names
+ = info.search_with(DN_Matcher());
-/*************************************************
-* Create and populate a X509_DN *
-*************************************************/
-X509_DN create_dn(const std::multimap<std::string, std::string>& names)
- {
typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
X509_DN new_dn;
for(rdn_iter j = names.begin(); j != names.end(); ++j)
- {
- const std::string oid = j->first;
- const std::string value = j->second;
- if(!OIDS::have_oid(oid))
- continue;
- new_dn.add_attribute(oid, j->second);
- }
+ new_dn.add_attribute(j->first, j->second);
return new_dn;
}
@@ -112,7 +53,7 @@ X509_DN create_dn(const std::multimap<std::string, std::string>& names)
X509_Certificate::X509_Certificate(DataSource& in) :
X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
{
- is_ca = false;
+ is_ca = self_signed = false;
do_decode();
}
@@ -122,7 +63,7 @@ X509_Certificate::X509_Certificate(DataSource& in) :
X509_Certificate::X509_Certificate(const std::string& in) :
X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
{
- is_ca = false;
+ is_ca = self_signed = false;
do_decode();
}
@@ -131,44 +72,34 @@ X509_Certificate::X509_Certificate(const std::string& in) :
*************************************************/
void X509_Certificate::force_decode()
{
- BER_Decoder tbs_cert(tbs_bits);
-
u32bit version;
+ BigInt serial_bn;
+ AlgorithmIdentifier sig_algo_inner;
+ X509_DN dn_issuer, dn_subject;
+ X509_Time start, end;
+
+ BER_Decoder tbs_cert(tbs_bits);
tbs_cert.decode_optional(version, ASN1_Tag(0),
ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC));
-
- if(version > 2)
- throw Decoding_Error("Unknown X.509 cert version " + to_string(version));
- if(version < 2)
- {
- is_ca = Config::get_bool("x509/v1_assume_ca");
- info.add("X509v3.BasicConstraints.path_constraint", NO_CERT_PATH_LIMIT);
- }
-
- BigInt serial_bn;
tbs_cert.decode(serial_bn);
-
- AlgorithmIdentifier sig_algo_inner;
tbs_cert.decode(sig_algo_inner);
-
- if(sig_algo != sig_algo_inner)
- throw Decoding_Error("Algorithm identifier mismatch");
-
- X509_DN dn_issuer;
tbs_cert.decode(dn_issuer);
- load_info(issuer, dn_issuer);
-
- X509_Time start, end;
-
tbs_cert.start_cons(SEQUENCE)
.decode(start)
.decode(end)
.verify_end()
- .end_cons();
+ .end_cons()
+ .decode(dn_subject);
+
+ if(version > 2)
+ throw Decoding_Error("Unknown X.509 cert version " + to_string(version));
+ if(sig_algo != sig_algo_inner)
+ throw Decoding_Error("Algorithm identifier mismatch");
+
+ self_signed = (dn_subject == dn_issuer);
- X509_DN dn_subject;
- tbs_cert.decode(dn_subject);
- load_info(subject, dn_subject);
+ subject.add(dn_subject.contents());
+ issuer.add(dn_issuer.contents());
BER_Object public_key = tbs_cert.get_next_object();
if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
@@ -185,16 +116,24 @@ void X509_Certificate::force_decode()
v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
{
BER_Decoder v3_exts_decoder(v3_exts_data.value);
- BER_Decoder ext_data = v3_exts_decoder.start_cons(SEQUENCE);
- v3_exts_decoder.verify_end();
- while(ext_data.more_items())
+#if 0
+ Extensions extensions;
+ v3_exts_decoder.decode(extensions);
+
+ extensions.contents(subject, issuer);
+#else
+ BER_Decoder sequence = v3_exts_decoder.start_cons(SEQUENCE);
+
+ while(sequence.more_items())
{
Extension extn;
- ext_data.decode(extn);
+ sequence.decode(extn);
handle_v3_extension(extn);
}
- ext_data.end_cons();
+ sequence.verify_end();
+#endif
+ v3_exts_decoder.verify_end();
}
else if(v3_exts_data.type_tag != NO_OBJECT)
throw BER_Bad_Tag("Unknown tag in X.509 cert",
@@ -203,20 +142,26 @@ void X509_Certificate::force_decode()
if(tbs_cert.more_items())
throw Decoding_Error("TBSCertificate has more items that expected");
- info.add("X509.Certificate.version", version);
- info.add("X509.Certificate.serial", BigInt::encode(serial_bn));
- info.add("X509.Certificate.start", start.readable_string());
- info.add("X509.Certificate.end", end.readable_string());
+ subject.add("X509.Certificate.version", version);
+ subject.add("X509.Certificate.serial", BigInt::encode(serial_bn));
+ subject.add("X509.Certificate.start", start.readable_string());
+ subject.add("X509.Certificate.end", end.readable_string());
- info.add("X509.Certificate.v2.issuer_key_id", v2_issuer_key_id);
- info.add("X509.Certificate.v2.subject_key_id", v2_subject_key_id);
+ issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id);
+ subject.add("X509.Certificate.v2.key_id", v2_subject_key_id);
- info.add("X509.Certificate.public_key",
- PEM_Code::encode(
- ASN1::put_in_sequence(public_key.value),
- "PUBLIC KEY"
- )
+ subject.add("X509.Certificate.public_key",
+ PEM_Code::encode(
+ ASN1::put_in_sequence(public_key.value),
+ "PUBLIC KEY"
+ )
);
+
+ if(!subject.has_value("X509v3.BasicConstraints.path_constraint"))
+ {
+ u32bit limit = (x509_version() < 3) ? NO_CERT_PATH_LIMIT : 0;
+ subject.add("X509v3.BasicConstraints.path_constraint", limit);
+ }
}
/*************************************************
@@ -232,7 +177,7 @@ void X509_Certificate::handle_v3_extension(const Extension& extn)
BER::decode(value, constraints);
if(constraints != NO_CONSTRAINTS)
- info.add("X509v3.KeyUsage", constraints);
+ subject.add("X509v3.KeyUsage", constraints);
}
else if(extn.oid == OIDS::lookup("X509v3.ExtendedKeyUsage"))
{
@@ -241,12 +186,13 @@ void X509_Certificate::handle_v3_extension(const Extension& extn)
{
OID usage_oid;
key_usage.decode(usage_oid);
- info.add("X509v3.ExtendedKeyUsage", usage_oid.as_string());
+ subject.add("X509v3.ExtendedKeyUsage", usage_oid.as_string());
}
}
else if(extn.oid == OIDS::lookup("X509v3.BasicConstraints"))
{
u32bit max_path_len = 0;
+ is_ca = false;
value.start_cons(SEQUENCE)
.decode_optional(is_ca, BOOLEAN, UNIVERSAL, false)
@@ -255,14 +201,14 @@ void X509_Certificate::handle_v3_extension(const Extension& extn)
.verify_end()
.end_cons();
- info.add("X509v3.BasicConstraints.is_ca", is_ca);
- info.add("X509v3.BasicConstraints.path_constraint", max_path_len);
+ subject.add("X509v3.BasicConstraints.path_constraint",
+ (is_ca ? max_path_len : 0));
}
else if(extn.oid == OIDS::lookup("X509v3.SubjectKeyIdentifier"))
{
MemoryVector<byte> v3_subject_key_id;
value.decode(v3_subject_key_id, OCTET_STRING);
- info.add("X509v3.SubjectKeyIdentifier", v3_subject_key_id);
+ subject.add("X509v3.SubjectKeyIdentifier", v3_subject_key_id);
}
else if(extn.oid == OIDS::lookup("X509v3.AuthorityKeyIdentifier"))
{
@@ -270,23 +216,22 @@ void X509_Certificate::handle_v3_extension(const Extension& extn)
BER_Decoder key_id = value.start_cons(SEQUENCE);
key_id.decode_optional_string(v3_issuer_key_id, OCTET_STRING, 0);
- info.add("X509v3.AuthorityKeyIdentifier", v3_issuer_key_id);
+ issuer.add("X509v3.AuthorityKeyIdentifier", v3_issuer_key_id);
}
else if(extn.oid == OIDS::lookup("X509v3.SubjectAlternativeName"))
{
AlternativeName alt_name;
value.decode(alt_name);
- load_info(subject, alt_name);
+ subject.add(alt_name.contents());
}
else if(extn.oid == OIDS::lookup("X509v3.IssuerAlternativeName"))
{
AlternativeName alt_name;
value.decode(alt_name);
- load_info(issuer, alt_name);
+ issuer.add(alt_name.contents());
}
else if(extn.oid == OIDS::lookup("X509v3.CertificatePolicies"))
{
-
BER_Decoder ber_policies = value.start_cons(SEQUENCE);
while(ber_policies.more_items())
{
@@ -297,7 +242,7 @@ void X509_Certificate::handle_v3_extension(const Extension& extn)
if(extn.critical && policy.more_items())
throw Decoding_Error("X.509 v3 critical policy has qualifiers");
- info.add("X509v3.CertificatePolicies", oid.as_string());
+ subject.add("X509v3.CertificatePolicies", oid.as_string());
}
}
else
@@ -316,7 +261,7 @@ void X509_Certificate::handle_v3_extension(const Extension& extn)
*************************************************/
u32bit X509_Certificate::x509_version() const
{
- return (info.get1_u32bit("X509.Certificate.version") + 1);
+ return (subject.get1_u32bit("X509.Certificate.version") + 1);
}
/*************************************************
@@ -324,7 +269,7 @@ u32bit X509_Certificate::x509_version() const
*************************************************/
std::string X509_Certificate::start_time() const
{
- return info.get1("X509.Certificate.start");
+ return subject.get1("X509.Certificate.start");
}
/*************************************************
@@ -332,23 +277,25 @@ std::string X509_Certificate::start_time() const
*************************************************/
std::string X509_Certificate::end_time() const
{
- return info.get1("X509.Certificate.end");
+ return subject.get1("X509.Certificate.end");
}
/*************************************************
* Return information about the subject *
*************************************************/
-std::string X509_Certificate::subject_info(const std::string& info) const
+std::vector<std::string>
+X509_Certificate::subject_info(const std::string& what) const
{
- return get_info(subject, info);
+ return subject.get(X509_DN::deref_info_field(what));
}
/*************************************************
* Return information about the issuer *
*************************************************/
-std::string X509_Certificate::issuer_info(const std::string& info) const
+std::vector<std::string>
+X509_Certificate::issuer_info(const std::string& what) const
{
- return get_info(issuer, info);
+ return issuer.get(X509_DN::deref_info_field(what));
}
/*************************************************
@@ -356,26 +303,18 @@ std::string X509_Certificate::issuer_info(const std::string& info) const
*************************************************/
X509_PublicKey* X509_Certificate::subject_public_key() const
{
- DataSource_Memory source(info.get1("X509.Certificate.public_key"));
+ DataSource_Memory source(subject.get1("X509.Certificate.public_key"));
return X509::load_key(source);
}
/*************************************************
-* Check if the certificate is self-signed *
-*************************************************/
-bool X509_Certificate::self_signed() const
- {
- return (create_dn(issuer) == create_dn(subject));
- }
-
-/*************************************************
* Check if the certificate is for a CA *
*************************************************/
bool X509_Certificate::is_CA_cert() const
{
- if(!is_ca) return false;
- if((constraints() & KEY_CERT_SIGN) ||
- (constraints() == NO_CONSTRAINTS))
+ if(!is_ca)
+ return false;
+ if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS))
return true;
return false;
}
@@ -385,7 +324,7 @@ bool X509_Certificate::is_CA_cert() const
*************************************************/
u32bit X509_Certificate::path_limit() const
{
- return info.get1_u32bit("X509v3.BasicConstraints.path_constraint");
+ return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint");
}
/*************************************************
@@ -393,7 +332,7 @@ u32bit X509_Certificate::path_limit() const
*************************************************/
Key_Constraints X509_Certificate::constraints() const
{
- return Key_Constraints(info.get1_u32bit("X509v3.KeyUsage"));
+ return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage"));
}
/*************************************************
@@ -401,7 +340,7 @@ Key_Constraints X509_Certificate::constraints() const
*************************************************/
std::vector<std::string> X509_Certificate::ex_constraints() const
{
- return info.get("X509v3.ExtendedKeyUsage");
+ return subject.get("X509v3.ExtendedKeyUsage");
}
/*************************************************
@@ -409,7 +348,7 @@ std::vector<std::string> X509_Certificate::ex_constraints() const
*************************************************/
std::vector<std::string> X509_Certificate::policies() const
{
- return info.get("X509v3.CertificatePolicies");
+ return subject.get("X509v3.CertificatePolicies");
}
/*************************************************
@@ -417,7 +356,7 @@ std::vector<std::string> X509_Certificate::policies() const
*************************************************/
MemoryVector<byte> X509_Certificate::authority_key_id() const
{
- return info.get1_memvec("X509v3.AuthorityKeyIdentifier");
+ return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
}
/*************************************************
@@ -425,7 +364,7 @@ MemoryVector<byte> X509_Certificate::authority_key_id() const
*************************************************/
MemoryVector<byte> X509_Certificate::subject_key_id() const
{
- return info.get1_memvec("X509v3.SubjectKeyIdentifier");
+ return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
}
/*************************************************
@@ -433,7 +372,7 @@ MemoryVector<byte> X509_Certificate::subject_key_id() const
*************************************************/
MemoryVector<byte> X509_Certificate::serial_number() const
{
- return info.get1_memvec("X509.Certificate.serial");
+ return subject.get1_memvec("X509.Certificate.serial");
}
/*************************************************
@@ -455,13 +394,10 @@ X509_DN X509_Certificate::subject_dn() const
/*************************************************
* Compare two certificates for equality *
*************************************************/
-bool X509_Certificate::operator==(const X509_Certificate& cert) const
+bool X509_Certificate::operator==(const X509_Certificate& other) const
{
- if(sig != cert.sig || sig_algo != cert.sig_algo)
- return false;
- if(issuer != cert.issuer || subject != cert.subject)
- return false;
- return (info == cert.info);
+ return (sig == other.sig && sig_algo == other.sig_algo &&
+ issuer == other.issuer && subject == other.subject);
}
/*************************************************
diff --git a/src/x509find.cpp b/src/x509find.cpp
index a50ce0bfa..2ba430caf 100644
--- a/src/x509find.cpp
+++ b/src/x509find.cpp
@@ -59,7 +59,12 @@ class DN_Check : public X509_Store::Search_Func
public:
bool match(const X509_Certificate& cert) const
{
- return compare(looking_for, cert.subject_info(dn_entry));
+ std::vector<std::string> info = cert.subject_info(dn_entry);
+
+ for(u32bit j = 0; j != info.size(); j++)
+ if(compare(info[j], looking_for))
+ return true;
+ return false;
}
DN_Check(const std::string& entry, const std::string& target,
diff --git a/src/x509stor.cpp b/src/x509stor.cpp
index ee89a5d97..d84fbe8b0 100644
--- a/src/x509stor.cpp
+++ b/src/x509stor.cpp
@@ -294,7 +294,7 @@ X509_Code X509_Store::construct_cert_chain(const X509_Certificate& end_cert,
if(certs[parent].is_trusted())
break;
- if(parent_cert.self_signed())
+ if(parent_cert.is_self_signed())
return CANNOT_ESTABLISH_TRUST;
if(parent_cert.path_limit() < indexes.size() - 1)
@@ -481,7 +481,7 @@ void X509_Store::add_new_certstore(Certificate_Store* certstore)
*************************************************/
void X509_Store::add_cert(const X509_Certificate& cert, bool trusted)
{
- if(trusted && !cert.self_signed())
+ if(trusted && !cert.is_self_signed())
throw Invalid_Argument("X509_Store: Trusted certs must be self-signed");
if(find_cert(cert.subject_dn(), cert.subject_key_id()) == NO_CERT_FOUND)