Skip to content

Commit

Permalink
X509: Allow writing CDP extension into certificates (#3712)
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-schiffner committed Oct 9, 2023
1 parent 335af74 commit d2506bf
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
22 changes: 19 additions & 3 deletions src/lib/x509/x509_ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,9 @@ void CRL_ReasonCode::decode_inner(const std::vector<uint8_t>& in) {
}

std::vector<uint8_t> CRL_Distribution_Points::encode_inner() const {
throw Not_Implemented("CRL_Distribution_Points encoding");
std::vector<uint8_t> output;
DER_Encoder(output).start_sequence().encode_list(m_distribution_points).end_cons();
return output;
}

void CRL_Distribution_Points::decode_inner(const std::vector<uint8_t>& buf) {
Expand All @@ -742,8 +744,22 @@ void CRL_Distribution_Points::decode_inner(const std::vector<uint8_t>& buf) {
m_crl_distribution_urls.push_back(ss.str());
}

void CRL_Distribution_Points::Distribution_Point::encode_into(DER_Encoder& /*to*/) const {
throw Not_Implemented("CRL_Distribution_Points encoding");
void CRL_Distribution_Points::Distribution_Point::encode_into(DER_Encoder& der) const {
if(!m_point.get_attributes().contains("URI")) {
throw Not_Implemented("Empty CRL_Distribution_Point encoding");
}

const auto range = m_point.get_attributes().equal_range("URI");

for(auto i = range.first; i != range.second; ++i) {
der.start_sequence()
.start_cons(ASN1_Type(0), ASN1_Class::ContextSpecific)
.start_cons(ASN1_Type(0), ASN1_Class::ContextSpecific)
.add_object(ASN1_Type(6), ASN1_Class::ContextSpecific, i->second)
.end_cons()
.end_cons()
.end_cons();
}
}

void CRL_Distribution_Points::Distribution_Point::decode_from(BER_Decoder& ber) {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/x509/x509_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ class BOTAN_PUBLIC_API(2, 0) CRL_Distribution_Points final : public Certificate_
void encode_into(DER_Encoder&) const override;
void decode_from(BER_Decoder&) override;

explicit Distribution_Point(const AlternativeName& name = AlternativeName()) : m_point(name) {}

const AlternativeName& point() const { return m_point; }

private:
Expand Down
38 changes: 38 additions & 0 deletions src/tests/unit_x509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,20 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key,
/* Create the CA object */
Botan::X509_CA ca(ca_cert, ca_key, hash_fn, sig_padding, Test::rng());

/* Prepare CDP extension */
std::vector<std::string> cdp_urls = {
"http://example.com/crl1.pem",
"ldap://ldap.example.com/cn=crl1,dc=example,dc=com?certificateRevocationList;binary"};

std::vector<Botan::Cert_Extension::CRL_Distribution_Points::Distribution_Point> dps;

for(const auto& uri : cdp_urls) {
Botan::AlternativeName cdp_alt_name("", uri);
Botan::Cert_Extension::CRL_Distribution_Points::Distribution_Point dp(cdp_alt_name);

dps.emplace_back(dp);
}

auto user_key = make_a_private_key(sig_algo);

Botan::X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");
Expand All @@ -1285,6 +1299,7 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key,
const Botan::OID oid("1.2.3.4.5.6.7.8.9.1");
const Botan::OID ku_oid = Botan::OID::from_string("X509v3.KeyUsage");
req_extensions.add(std::make_unique<String_Extension>("AAAAAAAAAAAAAABCDEF"), false);
req_extensions.add(std::make_unique<Botan::Cert_Extension::CRL_Distribution_Points>(dps));
opts.extensions = req_extensions;
opts.set_padding_scheme(sig_padding);

Expand All @@ -1310,6 +1325,18 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key,
"Custom extension value matches in self-signed certificate", string_ext->value(), "AAAAAAAAAAAAAABCDEF");
}

// check if CDPs are present in the self-signed cert
auto cert_cdps =
self_signed_cert.v3_extensions().get_extension_object_as<Botan::Cert_Extension::CRL_Distribution_Points>();

if(result.confirm("CRL Distribution Points extension present in self-signed certificate",
!cert_cdps->crl_distribution_urls().empty())) {
for(const auto& cdp : cert_cdps->distribution_points()) {
result.confirm("CDP URI present in self-signed certificate",
std::ranges::find(cdp_urls, cdp.point().get_first_attribute("URI")) != cdp_urls.end());
}
}

const Botan::PKCS10_Request user_req = Botan::X509::create_cert_req(opts, *user_key, hash_fn, Test::rng());

/* Create a CA-signed certificate */
Expand All @@ -1335,6 +1362,17 @@ Test::Result test_x509_extensions(const Botan::Private_Key& ca_key,
"Custom extension value matches in CA-signed certificate", string_ext->value(), "AAAAAAAAAAAAAABCDEF");
}

// check if CDPs are present in the CA-signed cert
cert_cdps = ca_signed_cert.v3_extensions().get_extension_object_as<Botan::Cert_Extension::CRL_Distribution_Points>();

if(result.confirm("CRL Distribution Points extension present in self-signed certificate",
!cert_cdps->crl_distribution_urls().empty())) {
for(const auto& cdp : cert_cdps->distribution_points()) {
result.confirm("CDP URI present in self-signed certificate",
std::ranges::find(cdp_urls, cdp.point().get_first_attribute("URI")) != cdp_urls.end());
}
}

return result;
}

Expand Down

0 comments on commit d2506bf

Please sign in to comment.