Description: Support building Percona XtraBackup against OpenSSL 4
 Allow OpenSSL versions over 3 when checking with cmake, and use constants and
 constant casting to match requirements of the OpenSSL 4 API.
 This patch was copied from the support-openssl4 patch in mysql-9.7.
Author: Lena Voytek <lena@debian.org>
Forwarded: not-needed
Last-Update: 2026-08-17
---
--- a/cmake/ssl.cmake
+++ b/cmake/ssl.cmake
@@ -151,8 +151,8 @@
       ${version_part} "${${version_part}}")
   ENDFOREACH()
   SET(OPENSSL_VERSION_MAJOR ${OPENSSL_VERSION_MAJOR} CACHE INTERNAL "" FORCE)
-  IF(OPENSSL_VERSION_MAJOR VERSION_EQUAL 3)
-    # OpenSSL 3
+  IF(OPENSSL_VERSION_MAJOR VERSION_GREATER_EQUAL 3)
+    # OpenSSL 3 and later
     SET(OPENSSL_FIX_VERSION "${OPENSSL_VERSION_PATCH}")
   ELSE()
     # Verify version number. Version information looks like:
@@ -866,9 +866,9 @@
   ENDIF()
 ENDMACRO(MYSQL_CHECK_SSL_DLLS)
 
-# Downgrade OpenSSL 3 deprecation warnings.
+# Downgrade OpenSSL 3+ deprecation warnings.
 MACRO(DOWNGRADE_OPENSSL3_DEPRECATION_WARNINGS)
-  IF(OPENSSL_VERSION_MAJOR VERSION_EQUAL 3)
+  IF(OPENSSL_VERSION_MAJOR VERSION_GREATER_EQUAL 3)
     IF(MY_COMPILER_IS_GNU_OR_CLANG)
       ADD_COMPILE_FLAGS(${ARGV}
         COMPILE_FLAGS "-Wno-error=deprecated-declarations")
--- a/storage/ndb/src/common/util/NodeCertificate.cpp
+++ b/storage/ndb/src/common/util/NodeCertificate.cpp
@@ -477,7 +477,7 @@
   /* Set the subject common name */
   char cn[CN_max_length];
   print_name(cn, CN_max_length);
-  set_common_name(X509_REQ_get_subject_name(m_req), cn);
+  set_common_name(const_cast<X509_NAME *>(X509_REQ_get_subject_name(m_req)), cn);
 
   /* Set the subject alt names extension */
   if (bound_hostnames()) {
@@ -561,7 +561,7 @@
   if (!cert) return nullptr;
 
   /* Copy name from csr to cert */
-  X509_NAME *name = X509_REQ_get_subject_name(m_req);
+  X509_NAME *name = const_cast<X509_NAME *>(X509_REQ_get_subject_name(m_req));
   if (X509_set_subject_name(cert, name) != 1) return nullptr;
 
   /* Set serial number in x509 */
@@ -581,7 +581,7 @@
 
 bool SigningRequest::parse_name() {
   if (m_req == nullptr) return false;
-  X509_NAME *name = X509_REQ_get_subject_name(m_req);
+  X509_NAME *name = const_cast<X509_NAME *>(X509_REQ_get_subject_name(m_req));
   return CertSubject::parse_name(name);
 }
 
@@ -604,8 +604,10 @@
 
 int SerialNumber::print(char *buf, int len, const ASN1_STRING *serial) {
   int offset = 0;
-  for (int i = 0; i < serial->length && offset < (len - 4); i++)
-    offset += sprintf(buf + offset, "%02X:", serial->data[i]);
+  const int serial_len = ASN1_STRING_length(serial);
+  const unsigned char *serial_data = ASN1_STRING_get0_data(serial);
+  for (int i = 0; i < serial_len && offset < (len - 4); i++)
+    offset += sprintf(buf + offset, "%02X:", serial_data[i]);
   if (offset) buf[offset - 1] = '\0';
   return offset;
 }
@@ -615,8 +617,10 @@
 SerialNumber::HexString::HexString(const ASN1_STRING *serial) {
   buf.append("0x");
   int truncated [[maybe_unused]] = 0;
-  for (int i = 0; i < serial->length; i++)
-    truncated = buf.appendf("%02x", serial->data[i]);
+  const int serial_len = ASN1_STRING_length(serial);
+  const unsigned char *serial_data = ASN1_STRING_get0_data(serial);
+  for (int i = 0; i < serial_len; i++)
+    truncated = buf.appendf("%02x", serial_data[i]);
   assert(!truncated);
 }
 
@@ -641,7 +645,7 @@
 }
 
 int Certificate::set_common_name(X509 *cert, const char *CN) {
-  X509_NAME *name = X509_get_subject_name(cert);
+  X509_NAME *name = const_cast<X509_NAME *>(X509_get_subject_name(cert));
   return CertSubject::set_common_name(name, CN);
 }
 
@@ -655,8 +659,10 @@
   const ASN1_BIT_STRING *sig = nullptr;
   const X509_ALGOR *algorithm;
   X509_get0_signature(&sig, &algorithm, cert);
-  if (sig && sig->data)
-    prefix = (sig->data[0] << 16) | (sig->data[1] << 8) | sig->data[2];
+  if (sig && ASN1_STRING_get0_data(sig)) {
+    const unsigned char *sig_data = ASN1_STRING_get0_data(sig);
+    prefix = (sig_data[0] << 16) | (sig_data[1] << 8) | sig_data[2];
+  }
   return prefix;
 }
 
@@ -768,7 +774,7 @@
   if (r1 == 0) return false;
 
   /* Set subject name */
-  X509_NAME *name = X509_get_subject_name(cert);
+  X509_NAME *name = const_cast<X509_NAME *>(X509_get_subject_name(cert));
   r1 = X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, subject, -1, -1, 0);
   if (r1 == 0) return false;
 
@@ -905,8 +911,9 @@
       auto *str =
           static_cast<ASN1_STRING *>(GENERAL_NAME_get0_value(name, &name_type));
       if (name_type == GEN_DNS) {
-        if (str->length < size) size = str->length;
-        memcpy(buffer, str->data, size);
+        const int str_len = ASN1_STRING_length(str);
+        if (str_len < size) size = str_len;
+        memcpy(buffer, ASN1_STRING_get0_data(str), size);
         buffer[size] = '\0';
         nwritten = size;
       }
@@ -927,8 +934,9 @@
     auto *str =
         static_cast<ASN1_STRING *>(GENERAL_NAME_get0_value(name, &name_type));
     if (name_type == GEN_DNS) {
-      if ((str->length == 9) &&
-          (strncmp("localhost", (const char *)str->data, 9) == 0))
+      if ((ASN1_STRING_length(str) == 9) &&
+          (strncmp("localhost", (const char *)ASN1_STRING_get0_data(str), 9) ==
+           0))
         return true;
     }
   }
@@ -1005,21 +1013,24 @@
 bool CertSubject::parse_name(X509_NAME *name) {
   int idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
   if (idx < 0) return false;
-  X509_NAME_ENTRY *cn = X509_NAME_get_entry(name, idx);
+  X509_NAME_ENTRY *cn =
+      const_cast<X509_NAME_ENTRY *>(X509_NAME_get_entry(name, idx));
   if (cn == nullptr) return false;
-  ASN1_STRING *str = X509_NAME_ENTRY_get_data(cn);
+  ASN1_STRING *str = const_cast<ASN1_STRING *>(X509_NAME_ENTRY_get_data(cn));
   return parse_name(str);
 }
 
 bool CertSubject::parse_name(const ASN1_STRING *str) {
   if (str == nullptr) return false;
-  if (str->length == 0) return false;
+  const int str_len = ASN1_STRING_length(str);
+  const unsigned char *str_data = ASN1_STRING_get0_data(str);
+  if (str_len == 0) return false;
 
   int p = 0;  // cursor into name
-  auto atEnd = [&]() { return (str->length == p); };
-  auto data = [&]() { return (char *)(str->data) + p; };
+  auto atEnd = [&]() { return (str_len == p); };
+  auto data = [&]() { return (char *)(str_data) + p; };
   auto find = [&](const char *a, size_t l) {
-    if (str->length <= p) return false;
+    if (str_len <= p) return false;
     int r = strncmp(data(), a, l);
     if (r == 0) {
       p += l;
@@ -1360,12 +1371,13 @@
 
 bool NodeCertificate::parse_name() {
   if (m_x509 == nullptr) return false;
-  X509_NAME *name = X509_get_subject_name(m_x509);
+  X509_NAME *name = const_cast<X509_NAME *>(X509_get_subject_name(m_x509));
   int idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
   if (idx < 0) return false;
-  X509_NAME_ENTRY *cn = X509_NAME_get_entry(name, idx);
+  X509_NAME_ENTRY *cn =
+      const_cast<X509_NAME_ENTRY *>(X509_NAME_get_entry(name, idx));
   if (cn == nullptr) return false;
-  ASN1_STRING *str = X509_NAME_ENTRY_get_data(cn);
+  ASN1_STRING *str = const_cast<ASN1_STRING *>(X509_NAME_ENTRY_get_data(cn));
   return CertSubject::parse_name(str);
 }
 
--- a/storage/ndb/src/common/util/testSecureSocket.cpp
+++ b/storage/ndb/src/common/util/testSecureSocket.cpp
@@ -221,7 +221,7 @@
   X509_set_pubkey(tls_cert, tls_key);
 
   /* Set the names */
-  X509_NAME *name = X509_get_subject_name(tls_cert);
+  X509_NAME *name = const_cast<X509_NAME *>(X509_get_subject_name(tls_cert));
   X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
                              (const unsigned char *)common_name, -1, -1, 0);
   X509_set_issuer_name(tls_cert, X509_get_subject_name(tls_cert));
--- a/router/src/router/src/certificate_generator.cc
+++ b/router/src/router/src/certificate_generator.cc
@@ -254,7 +254,7 @@
   }
 
   // Set CN value in subject
-  auto name = X509_get_subject_name(cert.get());
+  auto name = const_cast<X509_NAME *>(X509_get_subject_name(cert.get()));
   if (!name) {
     return stdx::unexpected(make_error_code(cert_errc::cert_set_cn_failed));
   }
--- a/router/src/mock_server/src/classic_mock_session.cc
+++ b/router/src/mock_server/src/classic_mock_session.cc
@@ -747,7 +747,8 @@
   }
 }
 
-stdx::expected<std::string, std::error_code> cert_get_name(X509_NAME *name) {
+stdx::expected<std::string, std::error_code> cert_get_name(
+    const X509_NAME *name) {
   std::unique_ptr<BIO, decltype(&BIO_free)> bio{BIO_new(BIO_s_mem()),
                                                 &BIO_free};
   // X509_NAME_oneline() is a legacy function and supposed to be not used for
--- a/router/tests/component/test_bootstrap.cc
+++ b/router/tests/component/test_bootstrap.cc
@@ -4672,7 +4672,7 @@
       << router_console_output;
 }
 
-std::string get_x509_name(X509_NAME *name) {
+std::string get_x509_name(const X509_NAME *name) {
   char buffer[256];
   X509_NAME_oneline(name, buffer, sizeof(buffer));
   return std::string(buffer);
--- a/router/tests/component/test_rest_api_enable.cc
+++ b/router/tests/component/test_rest_api_enable.cc
@@ -348,7 +348,7 @@
     X509_ptr cert(PEM_read_bio_X509_AUX(input.get(), nullptr, nullptr, nullptr),
                   X509_free);
 
-    X509_NAME *subject = X509_get_subject_name(cert.get());
+    const X509_NAME *subject = X509_get_subject_name(cert.get());
     BIO_ptr output_bio(BIO_new(BIO_s_mem()), BIO_free);
     X509_NAME_print_ex(output_bio.get(), subject, 0, 0);
 
--- a/sql/auth/sql_authentication.cc
+++ b/sql/auth/sql_authentication.cc
@@ -5342,7 +5342,7 @@
     if (!X509_set_pubkey(x509, pkey)) goto err;
 
     /** Set CN value in subject */
-    name = X509_get_subject_name(x509);
+    name = const_cast<X509_NAME *>(X509_get_subject_name(x509));
     if (!name) goto err;
 
     if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
