Repository: randombit/botan (cpp)

Issue:
Weird ecc_randomized failure
https://github.com/randombit/botan/actions/runs/11540997855/job/32122471011

Seed 1802538CC7A462A1

```

  ECC randomized secp160k1 ran 79 tests in 62.22 msec 1 FAILED
  Failure 1: ECC randomized secp160k1 secp160k1 with error EC_Scalar::from_bigint input out of range (at /home/runner/work/botan/botan/source/src/tests/test_ec_group.cpp:160)
```

Pull request description:
Fix random test failure introduced by #4385
Fixes #4415

Patch:
diff --git a/src/lib/x509/alt_name.cpp b/src/lib/x509/alt_name.cpp
index d835cc856..1b262aa4b 100644
--- a/src/lib/x509/alt_name.cpp
+++ b/src/lib/x509/alt_name.cpp
@@ -109,57 +109,6 @@ 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();
 
@@ -191,7 +140,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)) {
-         m_dns.insert(check_and_canonicalize_dns_name(ASN1::to_string(obj)));
+         add_dns(ASN1::to_string(obj));
       } else if(obj.is_a(4, ASN1_Class::ContextSpecific | ASN1_Class::Constructed)) {
          BER_Decoder dec(obj);
          X509_DN dn;
diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp
index 26b9e9c88..b964c0c4e 100644
--- a/src/lib/x509/x509cert.cpp
+++ b/src/lib/x509/x509cert.cpp
@@ -181,20 +181,6 @@ 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>()) {
diff --git a/src/scripts/ci/setup_gh_actions.sh b/src/scripts/ci/setup_gh_actions.sh
index 7d8e074c0..089bf3607 100755
--- a/src/scripts/ci/setup_gh_actions.sh
+++ b/src/scripts/ci/setup_gh_actions.sh
@@ -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/f98aa03f45d108ae4e1bc5a61ec4bd0b8d137559/limbo.json -O "${SCRIPT_LOCATION}/../../../limbo.json"
+        wget -nv https://raw.githubusercontent.com/C2SP/x509-limbo/bd88042508ccfde351b2fee293aebda8971fbebb/limbo.json -O "${SCRIPT_LOCATION}/../../../limbo.json"
 
     elif [ "$TARGET" = "coverage" ] || [ "$TARGET" = "sanitizer" ]; then
         if [ "$TARGET" = "coverage" ]; then


Test patch:
diff --git a/src/tests/test_ec_group.cpp b/src/tests/test_ec_group.cpp
index 20c276a7e..170747205 100644
--- a/src/tests/test_ec_group.cpp
+++ b/src/tests/test_ec_group.cpp
@@ -59,6 +59,12 @@ Botan::BigInt test_integer(Botan::RandomNumberGenerator& rng, size_t bits, const
       }
    }
 
+   if(x == 0) {
+      // EC_Scalar rejects zero as an input, if we hit this case instead
+      // test with a completely randomized scalar
+      return BigInt::random_integer(rng, 1, max);
+   }
+
    if(max > 0) {
       while(x >= max) {
          const size_t b = x.bits() - 1;