Package: grpc Followup-For: Bug #1138463 X-Debbugs-Cc: [email protected] Control: tags -1 patch ftbfs
Dear Maintainer, The patch fixes the build issue. -- System Information: Debian Release: trixie/sid APT prefers noble-updates APT policy: (500, 'noble-updates'), (500, 'noble-security'), (500, 'noble'), (100, 'noble-backports') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 6.8.0-117-generic (SMP w/12 CPU threads; PREEMPT) Kernel taint flags: TAINT_WARN Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled
From 9eaf2c5e572608c63132739c1f17302e6582511e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Tue, 24 Mar 2026 12:34:24 +0100 Subject: [PATCH 1/6] tsi: Fix OpenSSL 4.0 compatibility in SSL transport security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update ssl_transport_security.cc and ssl_transport_security_utils.cc for OpenSSL 4.0 API changes: - Add OPENSSL_cleanup() in atexit handler for OpenSSL 4.0+ OpenSSL 4.0 no longer registers OPENSSL_cleanup() via atexit(), so gRPC must call it explicitly after its own shutdown completes. - Guard ENGINE API usage behind OPENSSL_NO_ENGINE, add OSSL_STORE-based private key loading for OpenSSL 3.0+ OpenSSL 4.0 always defines OPENSSL_NO_ENGINE. - Replace direct ASN1_OCTET_STRING field access with ASN1_STRING_length() and ASN1_STRING_get0_data() accessors for opaque struct in OpenSSL 4.0 - Adapt to const-correctness changes On OpenSSL 4.0 since ENGINE is gone: "engine:"-prefixed keys will fall through to ssl_ctx_use_pem_private_key() which will fail with an error. Signed-off-by: Björn Svensson <[email protected]> Origin: upstream, https://github.com/grpc/grpc/pull/41932 Bug-Debian: https://bugs.debian.org/1138463 Bug-Ubuntu: https://bugs.launchpad.net/bugs/2155015 --- src/core/tsi/ssl_transport_security.cc | 35 ++++++++++++-------- src/core/tsi/ssl_transport_security_utils.cc | 14 ++++---- 2 files changed, 29 insertions(+), 20 deletions(-) --- a/test/core/handshake/client_ssl.cc +++ b/test/core/handshake/client_ssl.cc @@ -208,13 +208,15 @@ OpenSSL_add_ssl_algorithms(); args->ssl_library_info->Notify(); - const SSL_METHOD* method = TLSv1_2_server_method(); + const SSL_METHOD* method = TLS_server_method(); SSL_CTX* ctx = SSL_CTX_new(method); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); abort(); } + SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); + SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); // Load key pair. if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { --- a/test/core/handshake/server_ssl_common.cc +++ b/test/core/handshake/server_ssl_common.cc @@ -196,13 +196,15 @@ // server port. s.Await(); - const SSL_METHOD* method = TLSv1_2_client_method(); + const SSL_METHOD* method = TLS_client_method(); SSL_CTX* ctx = SSL_CTX_new(method); if (!ctx) { perror("Unable to create SSL context"); ERR_print_errors_fp(stderr); abort(); } + SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); + SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); // Load key pair. if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -25,6 +25,7 @@ #include <gtest/gtest.h> #include <openssl/crypto.h> #include <openssl/err.h> +#include <openssl/evp.h> #include <openssl/pem.h> #include <grpc/grpc.h> @@ -712,7 +713,16 @@ gpr_log(GPR_INFO, "ssl_tsi_test_do_round_trip_with_error_on_stack"); // Invoke an SSL function that causes an error, and ensure the error // makes it to the stack. +#if OPENSSL_VERSION_NUMBER < 0x30000000L ASSERT_FALSE(EC_KEY_new_by_curve_name(NID_rsa)); +#else + // Use EVP_PKEY_CTX with an invalid operation to push an error. + EVP_PKEY_CTX* err_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr); + ASSERT_NE(err_ctx, nullptr); + // Calling sign_init without a key will fail and push an error. + ASSERT_LE(EVP_PKEY_sign_init(err_ctx), 0); + EVP_PKEY_CTX_free(err_ctx); +#endif ASSERT_NE(ERR_peek_error(), 0); tsi_test_fixture* fixture = ssl_tsi_test_fixture_create(); tsi_test_do_round_trip(fixture); --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -37,7 +37,9 @@ #include <openssl/bio.h> #include <openssl/crypto.h> /* For OPENSSL_free */ +#if !defined(OPENSSL_NO_ENGINE) #include <openssl/engine.h> +#endif #include <openssl/err.h> #include <openssl/ssl.h> #include <openssl/tls1.h> @@ -270,9 +272,7 @@ static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8, size_t* utf8_size) { int common_name_index = -1; - X509_NAME_ENTRY* common_name_entry = nullptr; - ASN1_STRING* common_name_asn1 = nullptr; - X509_NAME* subject_name = X509_get_subject_name(cert); + auto* subject_name = X509_get_subject_name(cert); int utf8_returned_size = 0; if (subject_name == nullptr) { gpr_log(GPR_INFO, "Could not get subject name from certificate."); @@ -284,12 +284,13 @@ gpr_log(GPR_INFO, "Could not get common name of subject from certificate."); return TSI_NOT_FOUND; } - common_name_entry = X509_NAME_get_entry(subject_name, common_name_index); + auto* common_name_entry = + X509_NAME_get_entry(subject_name, common_name_index); if (common_name_entry == nullptr) { gpr_log(GPR_ERROR, "Could not get common name entry from certificate."); return TSI_INTERNAL_ERROR; } - common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); + auto* common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); if (common_name_asn1 == nullptr) { gpr_log(GPR_ERROR, "Could not get common name entry asn1 from certificate."); @@ -330,7 +331,7 @@ /* Gets the subject of an X509 cert as a tsi_peer_property. */ static tsi_result peer_property_from_x509_subject(X509* cert, tsi_peer_property* property) { - X509_NAME* subject_name = X509_get_subject_name(cert); + auto* subject_name = X509_get_subject_name(cert); if (subject_name == nullptr) { gpr_log(GPR_INFO, "Could not get subject name from certificate."); return TSI_NOT_FOUND; @@ -419,17 +420,30 @@ char ntop_buf[INET6_ADDRSTRLEN]; int af; +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + if (ASN1_STRING_length(subject_alt_name->d.iPAddress) == 4) { + af = AF_INET; + } else if (ASN1_STRING_length(subject_alt_name->d.iPAddress) == 16) { + af = AF_INET6; +#else if (subject_alt_name->d.iPAddress->length == 4) { af = AF_INET; } else if (subject_alt_name->d.iPAddress->length == 16) { af = AF_INET6; +#endif } else { gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP"); result = TSI_INTERNAL_ERROR; break; } +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const char* name = + inet_ntop(af, ASN1_STRING_get0_data(subject_alt_name->d.iPAddress), + ntop_buf, INET6_ADDRSTRLEN); +#else const char* name = inet_ntop(af, subject_alt_name->d.iPAddress->data, ntop_buf, INET6_ADDRSTRLEN); +#endif if (name == nullptr) { gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet."); result = TSI_INTERNAL_ERROR; @@ -776,13 +790,13 @@ break; /* We're at the end of stream. */ } if (root_names != nullptr) { - root_name = X509_get_subject_name(root); - if (root_name == nullptr) { + auto* root_subject = X509_get_subject_name(root); + if (root_subject == nullptr) { gpr_log(GPR_ERROR, "Could not get name from root certificate."); result = TSI_INVALID_ARGUMENT; break; } - root_name = X509_NAME_dup(root_name); + root_name = X509_NAME_dup(const_cast<X509_NAME*>(root_subject)); if (root_name == nullptr) { result = TSI_OUT_OF_RESOURCES; break;

