aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/cert/x509/x509_ext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/cert/x509/x509_ext.cpp')
-rw-r--r--src/lib/cert/x509/x509_ext.cpp105
1 files changed, 101 insertions, 4 deletions
diff --git a/src/lib/cert/x509/x509_ext.cpp b/src/lib/cert/x509/x509_ext.cpp
index 47fd909eb..b54c82b87 100644
--- a/src/lib/cert/x509/x509_ext.cpp
+++ b/src/lib/cert/x509/x509_ext.cpp
@@ -6,6 +6,7 @@
*/
#include <botan/x509_ext.h>
+#include <botan/x509cert.h>
#include <botan/sha160.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
@@ -20,7 +21,7 @@ namespace Botan {
/*
* List of X.509 Certificate Extensions
*/
-Certificate_Extension* Extensions::get_extension(const OID& oid)
+Certificate_Extension* Extensions::get_extension(const OID& oid, bool critical)
{
#define X509_EXTENSION(NAME, TYPE) \
if(OIDS::name_of(oid, NAME)) \
@@ -40,7 +41,7 @@ Certificate_Extension* Extensions::get_extension(const OID& oid)
X509_EXTENSION("X509v3.CRLNumber", CRL_Number);
X509_EXTENSION("X509v3.ReasonCode", CRL_ReasonCode);
- return nullptr;
+ return critical ? new Cert_Extension::Unknown_Critical_Extension(oid) : nullptr;
}
/*
@@ -55,7 +56,7 @@ Extensions::Extensions(const Extensions& extensions) : ASN1_Object()
* Extensions Assignment Operator
*/
Extensions& Extensions::operator=(const Extensions& other)
- {
+ {
m_extensions.clear();
for(size_t i = 0; i != other.m_extensions.size(); ++i)
@@ -63,6 +64,7 @@ Extensions& Extensions::operator=(const Extensions& other)
std::make_pair(std::unique_ptr<Certificate_Extension>(other.m_extensions[i].first->copy()),
other.m_extensions[i].second));
+ m_extensions_raw = other.m_extensions_raw;
m_throw_on_unknown_critical = other.m_throw_on_unknown_critical;
return (*this);
@@ -76,12 +78,31 @@ OID Certificate_Extension::oid_of() const
return OIDS::lookup(oid_name());
}
+/*
+* Validate the extension (the default implementation is a NOP)
+*/
+void Certificate_Extension::validate(const X509_Certificate&, const X509_Certificate&,
+ const std::vector<X509_Certificate>&,
+ std::vector<std::set<Certificate_Status_Code>>&,
+ size_t)
+ {
+ }
+
void Extensions::add(Certificate_Extension* extn, bool critical)
{
m_extensions.push_back(std::make_pair(std::unique_ptr<Certificate_Extension>(extn), critical));
m_extensions_raw.emplace(extn->oid_of(), std::make_pair(extn->encode_inner(), critical));
}
+std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> Extensions::extensions() const
+ {
+ std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> exts;
+ for(auto& ext : m_extensions)
+ {
+ exts.push_back(std::make_pair(std::unique_ptr<Certificate_Extension>(ext.first->copy()), ext.second));
+ }
+ return exts;
+ }
std::map<OID, std::pair<std::vector<byte>, bool>> Extensions::extensions_raw() const
{
@@ -136,7 +157,7 @@ void Extensions::decode_from(BER_Decoder& from_source)
m_extensions_raw.emplace(oid, std::make_pair(value, critical));
- std::unique_ptr<Certificate_Extension> ext(get_extension(oid));
+ std::unique_ptr<Certificate_Extension> ext(get_extension(oid, critical));
if(!ext && critical && m_throw_on_unknown_critical)
throw Decoding_Error("Encountered unknown X.509 extension marked "
@@ -500,6 +521,68 @@ void Name_Constraints::contents_to(Data_Store& subject, Data_Store&) const
}
}
+void Name_Constraints::validate(const X509_Certificate& subject, const X509_Certificate& issuer,
+ const std::vector<X509_Certificate>& cert_path,
+ std::vector<std::set<Certificate_Status_Code>>& cert_status,
+ size_t pos)
+ {
+ if(!m_name_constraints.permitted().empty() || !m_name_constraints.excluded().empty())
+ {
+ if(!subject.is_CA_cert() || !subject.is_critical("X509v3.NameConstraints"))
+ cert_status.at(pos).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
+
+ const bool at_self_signed_root = (pos == cert_path.size() - 1);
+
+ // Check that all subordinate certs pass the name constraint
+ for(size_t j = 0; j <= pos; ++j)
+ {
+ if(pos == j && at_self_signed_root)
+ continue;
+
+ bool permitted = m_name_constraints.permitted().empty();
+ bool failed = false;
+
+ for(auto c: m_name_constraints.permitted())
+ {
+ switch(c.base().matches(cert_path.at(j)))
+ {
+ case GeneralName::MatchResult::NotFound:
+ case GeneralName::MatchResult::All:
+ permitted = true;
+ break;
+ case GeneralName::MatchResult::UnknownType:
+ failed = issuer.is_critical("X509v3.NameConstraints");
+ permitted = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ for(auto c: m_name_constraints.excluded())
+ {
+ switch(c.base().matches(cert_path.at(j)))
+ {
+ case GeneralName::MatchResult::All:
+ case GeneralName::MatchResult::Some:
+ failed = true;
+ break;
+ case GeneralName::MatchResult::UnknownType:
+ failed = issuer.is_critical("X509v3.NameConstraints");
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(failed || !permitted)
+ {
+ cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
+ }
+ }
+ }
+ }
+
namespace {
/*
@@ -730,6 +813,20 @@ void CRL_Distribution_Points::Distribution_Point::decode_from(class BER_Decoder&
.end_cons().end_cons();
}
+std::vector<byte> Unknown_Critical_Extension::encode_inner() const
+ {
+ throw Exception("Unknown_Critical_Extension encoding not implemented");
+ }
+
+void Unknown_Critical_Extension::decode_inner(const std::vector<byte>& buf)
+ {
+ }
+
+void Unknown_Critical_Extension::contents_to(Data_Store& info, Data_Store&) const
+ {
+ // TODO: textual representation?
+ }
+
}
}