Skip to content

Commit

Permalink
Merge pull request #4406 from randombit/jack/update-limbo
Browse files Browse the repository at this point in the history
Update Limbo test suite and fix relevant bugs
  • Loading branch information
randombit authored Oct 29, 2024
2 parents 0550c5c + 5d3f3c0 commit dc326ed
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
53 changes: 52 additions & 1 deletion src/lib/x509/alt_name.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,57 @@ void AlternativeName::encode_into(DER_Encoder& der) const {
der.end_cons();
}

namespace {

std::string check_and_canonicalize_dns_name(std::string_view name) {
if(name.size() > 255) {
throw Decoding_Error("DNS SAN exceeds maximum allowed length");
}

if(name.empty()) {
throw Decoding_Error("DNS SAN cannot be empty");
}

if(name.starts_with(".")) {
throw Decoding_Error("DNS SAN cannot start with a dot");
}

/*
* Table mapping uppercase to lowercase and only including values for valid DNS names
* namely A-Z, a-z, 0-9, hypen, and dot, plus '*' for wildcarding.
*/
// clang-format off
constexpr uint8_t DNS_CHAR_MAPPING[128] = {
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '*', '\0', '\0', '-', '.', '\0', '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\0', '\0', '\0', '\0',
'\0', '\0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\0', '\0', '\0', '\0', '\0',
};
// clang-format on

std::string canon;
canon.reserve(name.size());

for(char c : name) {
const uint8_t cu = static_cast<uint8_t>(c);
if(cu >= 128) {
throw Decoding_Error("DNS name must not contain any extended ASCII code points");
}
const uint8_t mapped = DNS_CHAR_MAPPING[cu];
if(mapped == 0) {
throw Decoding_Error("Name in DNS SAN includes invalid character");
}
canon.push_back(static_cast<char>(mapped));
}

return canon;
}

} // namespace

void AlternativeName::decode_from(BER_Decoder& source) {
BER_Decoder names = source.start_sequence();

Expand Down Expand Up @@ -140,7 +191,7 @@ void AlternativeName::decode_from(BER_Decoder& source) {
} else if(obj.is_a(1, ASN1_Class::ContextSpecific)) {
add_email(ASN1::to_string(obj));
} else if(obj.is_a(2, ASN1_Class::ContextSpecific)) {
add_dns(ASN1::to_string(obj));
m_dns.insert(check_and_canonicalize_dns_name(ASN1::to_string(obj)));
} else if(obj.is_a(4, ASN1_Class::ContextSpecific | ASN1_Class::Constructed)) {
BER_Decoder dec(obj);
X509_DN dn;
Expand Down
14 changes: 14 additions & 0 deletions src/lib/x509/x509cert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,20 @@ std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& o

if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Extended_Key_Usage>()) {
data->m_extended_key_usage = ext->object_identifiers();
/*
RFC 5280 section 4.2.1.12
"This extension indicates one or more purposes ..."
"If the extension is present, then the certificate MUST only be
used for one of the purposes indicated."
Thus we reject an EKU extension which is empty, since this indicates
the certificate cannot be used for any purpose.
*/
if(data->m_extended_key_usage.empty()) {
throw Decoding_Error("Certificate has invalid empty EKU extension");
}
}

if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>()) {
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/ci/setup_gh_actions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ if type -p "apt-get"; then

elif [ "$TARGET" = "limbo" ]; then
sudo apt-get -qq install python3-dateutil
wget -nv https://raw.githubusercontent.com/C2SP/x509-limbo/bd88042508ccfde351b2fee293aebda8971fbebb/limbo.json -O "${SCRIPT_LOCATION}/../../../limbo.json"
wget -nv https://raw.githubusercontent.com/C2SP/x509-limbo/f98aa03f45d108ae4e1bc5a61ec4bd0b8d137559/limbo.json -O "${SCRIPT_LOCATION}/../../../limbo.json"

elif [ "$TARGET" = "coverage" ] || [ "$TARGET" = "sanitizer" ]; then
if [ "$TARGET" = "coverage" ]; then
Expand Down

0 comments on commit dc326ed

Please sign in to comment.