aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-06-13 18:06:57 +0000
committerlloyd <[email protected]>2012-06-13 18:06:57 +0000
commit6dc2f28174e110427899727690c82a8d230c908e (patch)
tree0d092b56dd740b15552b211a2f9b7ffd50d59964
parent9644a3ecebb15d8241e65dcae63bd6d0382a95a6 (diff)
Add support (decoding only) for the CRL Distribution Point extension.
-rw-r--r--src/asn1/ber_dec.h38
-rw-r--r--src/cert/x509/x509_ext.cpp54
-rw-r--r--src/cert/x509/x509_ext.h62
-rw-r--r--src/cert/x509/x509cert.cpp7
-rw-r--r--src/cert/x509/x509cert.h5
-rw-r--r--src/libstate/policy.cpp1
-rw-r--r--src/utils/datastor/datastor.cpp16
-rw-r--r--src/utils/datastor/datastor.h5
8 files changed, 156 insertions, 32 deletions
diff --git a/src/asn1/ber_dec.h b/src/asn1/ber_dec.h
index e9f519d59..0d0d0ec72 100644
--- a/src/asn1/ber_dec.h
+++ b/src/asn1/ber_dec.h
@@ -97,6 +97,15 @@ class BOTAN_DLL BER_Decoder
const T& default_value = T());
template<typename T>
+ BER_Decoder& decode_optional_implicit(
+ T& out,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ ASN1_Tag real_type,
+ ASN1_Tag real_class,
+ const T& default_value = T());
+
+ template<typename T>
BER_Decoder& decode_list(std::vector<T>& out,
ASN1_Tag type_tag = SEQUENCE,
ASN1_Tag class_tag = UNIVERSAL);
@@ -172,6 +181,35 @@ BER_Decoder& BER_Decoder::decode_optional(T& out,
}
/*
+* Decode an OPTIONAL or DEFAULT element
+*/
+template<typename T>
+BER_Decoder& BER_Decoder::decode_optional_implicit(
+ T& out,
+ ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ ASN1_Tag real_type,
+ ASN1_Tag real_class,
+ const T& default_value)
+ {
+ BER_Object obj = get_next_object();
+
+ if(obj.type_tag == type_tag && obj.class_tag == class_tag)
+ {
+ obj.type_tag = real_type;
+ obj.class_tag = real_class;
+ push_back(obj);
+ decode(out, real_type, real_class);
+ }
+ else
+ {
+ out = default_value;
+ push_back(obj);
+ }
+
+ return (*this);
+ }
+/*
* Decode a list of homogenously typed values
*/
template<typename T>
diff --git a/src/cert/x509/x509_ext.cpp b/src/cert/x509/x509_ext.cpp
index 6be0c7571..7cef2969b 100644
--- a/src/cert/x509/x509_ext.cpp
+++ b/src/cert/x509/x509_ext.cpp
@@ -1,6 +1,6 @@
/*
* X.509 Certificate Extensions
-* (C) 1999-2010 Jack Lloyd
+* (C) 1999-2010,2012 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -34,6 +34,7 @@ Certificate_Extension* Extensions::get_extension(const OID& oid)
X509_EXTENSION("X509v3.IssuerAlternativeName", Issuer_Alternative_Name);
X509_EXTENSION("X509v3.SubjectAlternativeName", Subject_Alternative_Name);
X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies);
+ X509_EXTENSION("X509v3.CRLDistributionPoints", CRL_Distribution_Points);
X509_EXTENSION("PKIX.AuthorityInformationAccess", Authority_Information_Access);
X509_EXTENSION("X509v3.CRLNumber", CRL_Number);
X509_EXTENSION("X509v3.ReasonCode", CRL_ReasonCode);
@@ -375,22 +376,18 @@ void Alternative_Name::contents_to(Data_Store& subject_info,
* Alternative_Name Constructor
*/
Alternative_Name::Alternative_Name(const AlternativeName& alt_name,
- const std::string& oid_name_str,
- const std::string& config_name_str)
+ const std::string& oid_name_str)
{
this->alt_name = alt_name;
this->oid_name_str = oid_name_str;
- this->config_name_str = config_name_str;
}
/*
* Subject_Alternative_Name Constructor
*/
Subject_Alternative_Name::Subject_Alternative_Name(
- const AlternativeName& name) :
-
- Alternative_Name(name, "X509v3.SubjectAlternativeName",
- "subject_alternative_name")
+ const AlternativeName& name) :
+ Alternative_Name(name, "X509v3.SubjectAlternativeName")
{
}
@@ -398,8 +395,7 @@ Subject_Alternative_Name::Subject_Alternative_Name(
* Issuer_Alternative_Name Constructor
*/
Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) :
- Alternative_Name(name, "X509v3.IssuerAlternativeName",
- "issuer_alternative_name")
+ Alternative_Name(name, "X509v3.IssuerAlternativeName")
{
}
@@ -621,6 +617,44 @@ void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const
info.add("X509v3.CRLReasonCode", reason);
}
+std::vector<byte> CRL_Distribution_Points::encode_inner() const
+ {
+ throw std::runtime_error("CRL_Distribution_Points encoding not implemented");
+ }
+
+void CRL_Distribution_Points::decode_inner(const std::vector<byte>& buf)
+ {
+ BER_Decoder(buf).decode_list(m_distribution_points).verify_end();
+ }
+
+void CRL_Distribution_Points::contents_to(Data_Store& info, Data_Store&) const
+ {
+ for(size_t i = 0; i != m_distribution_points.size(); ++i)
+ {
+ auto point = m_distribution_points[i].point().contents();
+
+ auto uris = point.equal_range("URI");
+
+ for(auto uri = uris.first; uri != uris.second; ++uri)
+ info.add("CRL.DistributionPoint", uri->second);
+ }
+ }
+
+void CRL_Distribution_Points::Distribution_Point::encode_into(class DER_Encoder&) const
+ {
+ throw std::runtime_error("CRL_Distribution_Points encoding not implemented");
+ }
+
+void CRL_Distribution_Points::Distribution_Point::decode_from(class BER_Decoder& ber)
+ {
+ ber.start_cons(SEQUENCE)
+ .start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC)
+ .decode_optional_implicit(m_point, ASN1_Tag(0),
+ ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED),
+ SEQUENCE, CONSTRUCTED)
+ .end_cons().end_cons();
+ }
+
}
}
diff --git a/src/cert/x509/x509_ext.h b/src/cert/x509/x509_ext.h
index 63bbdb072..42434c4c2 100644
--- a/src/cert/x509/x509_ext.h
+++ b/src/cert/x509/x509_ext.h
@@ -1,6 +1,6 @@
/*
* X.509 Certificate Extensions
-* (C) 1999-2007 Jack Lloyd
+* (C) 1999-2007,2012 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/
@@ -43,11 +43,6 @@ class BOTAN_DLL Certificate_Extension
Data_Store& issuer) const = 0;
/*
- * @return short readable name
- */
- virtual std::string config_id() const = 0;
-
- /*
* @return specific OID name
*/
virtual std::string oid_name() const = 0;
@@ -104,7 +99,6 @@ class BOTAN_DLL Basic_Constraints : public Certificate_Extension
bool get_is_ca() const { return is_ca; }
size_t get_path_limit() const;
private:
- std::string config_id() const { return "basic_constraints"; }
std::string oid_name() const { return "X509v3.BasicConstraints"; }
std::vector<byte> encode_inner() const;
@@ -127,7 +121,6 @@ class BOTAN_DLL Key_Usage : public Certificate_Extension
Key_Constraints get_constraints() const { return constraints; }
private:
- std::string config_id() const { return "key_usage"; }
std::string oid_name() const { return "X509v3.KeyUsage"; }
bool should_encode() const { return (constraints != NO_CONSTRAINTS); }
@@ -151,7 +144,6 @@ class BOTAN_DLL Subject_Key_ID : public Certificate_Extension
std::vector<byte> get_key_id() const { return key_id; }
private:
- std::string config_id() const { return "subject_key_id"; }
std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; }
bool should_encode() const { return (key_id.size() > 0); }
@@ -175,7 +167,6 @@ class BOTAN_DLL Authority_Key_ID : public Certificate_Extension
std::vector<byte> get_key_id() const { return key_id; }
private:
- std::string config_id() const { return "authority_key_id"; }
std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; }
bool should_encode() const { return (key_id.size() > 0); }
@@ -195,12 +186,10 @@ class BOTAN_DLL Alternative_Name : public Certificate_Extension
AlternativeName get_alt_name() const { return alt_name; }
protected:
- Alternative_Name(const AlternativeName&,
- const std::string&, const std::string&);
+ Alternative_Name(const AlternativeName&, const std::string& oid_name);
Alternative_Name(const std::string&, const std::string&);
private:
- std::string config_id() const { return config_name_str; }
std::string oid_name() const { return oid_name_str; }
bool should_encode() const { return alt_name.has_items(); }
@@ -208,7 +197,7 @@ class BOTAN_DLL Alternative_Name : public Certificate_Extension
void decode_inner(const std::vector<byte>&);
void contents_to(Data_Store&, Data_Store&) const;
- std::string config_name_str, oid_name_str;
+ std::string oid_name_str;
AlternativeName alt_name;
};
@@ -249,7 +238,6 @@ class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension
std::vector<OID> get_oids() const { return oids; }
private:
- std::string config_id() const { return "extended_key_usage"; }
std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; }
bool should_encode() const { return (oids.size() > 0); }
@@ -274,7 +262,6 @@ class BOTAN_DLL Certificate_Policies : public Certificate_Extension
std::vector<OID> get_oids() const { return oids; }
private:
- std::string config_id() const { return "policy_info"; }
std::string oid_name() const { return "X509v3.CertificatePolicies"; }
bool should_encode() const { return (oids.size() > 0); }
@@ -297,7 +284,6 @@ class BOTAN_DLL Authority_Information_Access : public Certificate_Extension
m_ocsp_responder(ocsp) {}
private:
- std::string config_id() const { return "auth_information_access"; }
std::string oid_name() const { return "PKIX.AuthorityInformationAccess"; }
bool should_encode() const { return (m_ocsp_responder != ""); }
@@ -323,7 +309,6 @@ class BOTAN_DLL CRL_Number : public Certificate_Extension
size_t get_crl_number() const;
private:
- std::string config_id() const { return "crl_number"; }
std::string oid_name() const { return "X509v3.CRLNumber"; }
bool should_encode() const { return has_value; }
@@ -347,7 +332,6 @@ class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension
CRL_Code get_reason() const { return reason; }
private:
- std::string config_id() const { return "crl_reason"; }
std::string oid_name() const { return "X509v3.ReasonCode"; }
bool should_encode() const { return (reason != UNSPECIFIED); }
@@ -358,6 +342,46 @@ class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension
CRL_Code reason;
};
+/**
+* CRL Distribution Points Extension
+*/
+class BOTAN_DLL CRL_Distribution_Points : public Certificate_Extension
+ {
+ public:
+ class BOTAN_DLL Distribution_Point : public ASN1_Object
+ {
+ public:
+ void encode_into(class DER_Encoder&) const;
+ void decode_from(class BER_Decoder&);
+
+ const AlternativeName& point() const { return m_point; }
+ private:
+ AlternativeName m_point;
+ };
+
+ CRL_Distribution_Points* copy() const
+ { return new CRL_Distribution_Points(m_distribution_points); }
+
+ CRL_Distribution_Points() {}
+
+ CRL_Distribution_Points(const std::vector<Distribution_Point>& points) :
+ m_distribution_points(points) {}
+
+ std::vector<Distribution_Point> distribution_points() const
+ { return m_distribution_points; }
+
+ private:
+ std::string oid_name() const { return "X509v3.CRLDistributionPoints"; }
+
+ bool should_encode() const { return !m_distribution_points.empty(); }
+
+ std::vector<byte> encode_inner() const;
+ void decode_inner(const std::vector<byte>&);
+ void contents_to(Data_Store&, Data_Store&) const;
+
+ std::vector<Distribution_Point> m_distribution_points;
+ };
+
}
}
diff --git a/src/cert/x509/x509cert.cpp b/src/cert/x509/x509cert.cpp
index 05a548be4..1a99192c8 100644
--- a/src/cert/x509/x509cert.cpp
+++ b/src/cert/x509/x509cert.cpp
@@ -278,7 +278,12 @@ std::vector<std::string> X509_Certificate::policies() const
std::string X509_Certificate::ocsp_responder() const
{
- return subject.get1("OCSP.responder");
+ return subject.get1("OCSP.responder", "");
+ }
+
+std::string X509_Certificate::crl_distribution_point() const
+ {
+ return subject.get1("CRL.DistributionPoint", "");
}
/*
diff --git a/src/cert/x509/x509cert.h b/src/cert/x509/x509cert.h
index c226928dc..c4f2dfb72 100644
--- a/src/cert/x509/x509cert.h
+++ b/src/cert/x509/x509cert.h
@@ -171,6 +171,11 @@ class BOTAN_DLL X509_Certificate : public X509_Object
std::string ocsp_responder() const;
/**
+ * Return the CRL distribution point, or empty if not set
+ */
+ std::string crl_distribution_point() const;
+
+ /**
* @return a string describing the certificate
*/
std::string to_string() const;
diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp
index 527833e61..fc127478e 100644
--- a/src/libstate/policy.cpp
+++ b/src/libstate/policy.cpp
@@ -189,6 +189,7 @@ void set_default_oids(Library_State& config)
add_oid(config, "2.5.29.21", "X509v3.ReasonCode");
add_oid(config, "2.5.29.23", "X509v3.HoldInstructionCode");
add_oid(config, "2.5.29.24", "X509v3.InvalidityDate");
+ add_oid(config, "2.5.29.31", "X509v3.CRLDistributionPoints");
add_oid(config, "2.5.29.32", "X509v3.CertificatePolicies");
add_oid(config, "2.5.29.35", "X509v3.AuthorityKeyIdentifier");
add_oid(config, "2.5.29.36", "X509v3.PolicyConstraints");
diff --git a/src/utils/datastor/datastor.cpp b/src/utils/datastor/datastor.cpp
index d32c4787e..7563e9309 100644
--- a/src/utils/datastor/datastor.cpp
+++ b/src/utils/datastor/datastor.cpp
@@ -64,13 +64,27 @@ std::string Data_Store::get1(const std::string& key) const
std::vector<std::string> vals = get(key);
if(vals.empty())
- throw Invalid_State("Data_Store::get1: Not values for " + key);
+ throw Invalid_State("Data_Store::get1: No values set for " + key);
if(vals.size() > 1)
throw Invalid_State("Data_Store::get1: More than one value for " + key);
return vals[0];
}
+std::string Data_Store::get1(const std::string& key,
+ const std::string& default_value) const
+ {
+ std::vector<std::string> vals = get(key);
+
+ if(vals.size() > 1)
+ throw Invalid_State("Data_Store::get1: More than one value for " + key);
+
+ if(vals.empty())
+ return default_value;
+
+ return vals[0];
+ }
+
/*
* Get a single std::vector atom
*/
diff --git a/src/utils/datastor/datastor.h b/src/utils/datastor/datastor.h
index b471f85e1..1c0504fc9 100644
--- a/src/utils/datastor/datastor.h
+++ b/src/utils/datastor/datastor.h
@@ -33,7 +33,10 @@ class BOTAN_DLL Data_Store
std::vector<std::string> get(const std::string&) const;
- std::string get1(const std::string&) const;
+ std::string get1(const std::string& key) const;
+
+ std::string get1(const std::string& key,
+ const std::string& default_value) const;
std::vector<byte> get1_memvec(const std::string&) const;
u32bit get1_u32bit(const std::string&, u32bit = 0) const;