This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new 80293fe2d5 Avoid deprecated OpenSSL APIs 80293fe2d5 is described below commit 80293fe2d556d82a2c332e1ce5291220bfdae5c0 Author: remm <r...@apache.org> AuthorDate: Fri Sep 1 12:43:53 2023 +0200 Avoid deprecated OpenSSL APIs Not sure if this is fully identical to the previous code. A few oddities to investigate (EC with keystore ? DH auto use ?). Based on the mod_ssl rev 1908537. https://svn.apache.org/viewvc?view=revision&revision=1908537 Use @Deprecated in the generated classes to spot calls. Will be removed when regenerating, unfortunately. Since there is no rush, leave in the OpenSSL < 3.0 code for now. Verified with org.apache.tomcat.util.net.TestSSLHostConfigCompat --- .../ciphers/OpenSSLCipherConfigurationParser.java | 11 ++- .../util/net/openssl/panama/OpenSSLContext.java | 101 ++++++++++++++++----- .../util/net/openssl/panama/OpenSSLLibrary.java | 22 ++--- .../org/apache/tomcat/util/openssl/openssl_h.java | 14 +++ .../net/openssl/panama/LocalStrings.properties | 2 + 5 files changed, 113 insertions(+), 37 deletions(-) diff --git a/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java b/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java index 13be8d5eae..90d0eaca7e 100644 --- a/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java +++ b/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java @@ -712,7 +712,16 @@ public class OpenSSLCipherConfigurationParser { init(); } String[] elements = expression.split(SEPARATOR); - // TODO: Handle PROFILE= using OpenSSL (if present, otherwise warn), then replace elements with that + // Handle PROFILE= using OpenSSL (if present, otherwise warn), then replace elements with that + if (elements.length == 1 && elements[0].startsWith("PROFILE=")) { + // Only use with Panama and if OpenSSL has been successfully loaded before + /* FIXME: Merge OpenSSL code first + if (JreCompat.isJre22Available() && OpenSSLStatus.isLibraryInitialized()) { + List<String> cipherList = OpenSSLLibrary.findCiphers(elements[0]); + // Replace the original list with the profile contents + elements = cipherList.toArray(new String[0]); + }*/ + } LinkedHashSet<Cipher> ciphers = new LinkedHashSet<>(); Set<Cipher> removedCiphers = new HashSet<>(); for (String element : elements) { diff --git a/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java b/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java index c482025a79..343efb13a1 100644 --- a/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java +++ b/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java @@ -22,6 +22,7 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemorySegment; import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -1113,32 +1114,65 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext { // Try to read DH parameters from the (first) SSLCertificateFile if (index == SSL_AIDX_RSA) { bio = BIO_new_file(certificateFileNative, localArena.allocateFrom("r")); - var dh = PEM_read_bio_DHparams(bio, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); - BIO_free(bio); - // # define SSL_CTX_set_tmp_dh(sslCtx,dh) \ - // SSL_CTX_ctrl(sslCtx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh)) - if (!MemorySegment.NULL.equals(dh)) { - SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_TMP_DH(), 0, dh); - DH_free(dh); + if (OpenSSL_version_num() < 0x3000000fL) { + var dh = PEM_read_bio_DHparams(bio, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + BIO_free(bio); + // # define SSL_CTX_set_tmp_dh(sslCtx,dh) \ + // SSL_CTX_ctrl(sslCtx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh)) + if (!MemorySegment.NULL.equals(dh)) { + SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_TMP_DH(), 0, dh); + DH_free(dh); + } + } else { + var pkey = PEM_read_bio_Parameters(bio, MemorySegment.NULL); + if (!MemorySegment.NULL.equals(pkey)) { + int numBits = EVP_PKEY_get_bits(pkey); + if (SSL_CTX_set0_tmp_dh_pkey(state.sslCtx, pkey) <= 0) { + EVP_PKEY_free(pkey); + } else { + log.debug(sm.getString("openssl.setCustomDHParameters", numBits, certificate.getCertificateFile())); + } + } else { + SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_DH_AUTO(), 1, MemorySegment.NULL); + } } } // Similarly, try to read the ECDH curve name from SSLCertificateFile... bio = BIO_new_file(certificateFileNative, localArena.allocateFrom("r")); - var ecparams = PEM_read_bio_ECPKParameters(bio, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); - BIO_free(bio); - if (!MemorySegment.NULL.equals(ecparams)) { - int nid = EC_GROUP_get_curve_name(ecparams); - var eckey = EC_KEY_new_by_curve_name(nid); - // # define SSL_CTX_set_tmp_ecdh(sslCtx,ecdh) \ - // SSL_CTX_ctrl(sslCtx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh)) - SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_TMP_ECDH(), 0, eckey); - EC_KEY_free(eckey); - EC_GROUP_free(ecparams); + if (OpenSSL_version_num() < 0x3000000fL) { + var ecparams = PEM_read_bio_ECPKParameters(bio, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + BIO_free(bio); + if (!MemorySegment.NULL.equals(ecparams)) { + int nid = EC_GROUP_get_curve_name(ecparams); + var eckey = EC_KEY_new_by_curve_name(nid); + // # define SSL_CTX_set_tmp_ecdh(sslCtx,ecdh) \ + // SSL_CTX_ctrl(sslCtx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh)) + SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_TMP_ECDH(), 0, eckey); + EC_KEY_free(eckey); + EC_GROUP_free(ecparams); + } + // Set callback for DH parameters + var openSSLCallbackTmpDH = Linker.nativeLinker().upcallStub(openSSLCallbackTmpDHHandle, + openSSLCallbackTmpDHFunctionDescriptor, contextArena); + SSL_CTX_set_tmp_dh_callback(state.sslCtx, openSSLCallbackTmpDH); + } else { + var d2i_ECPKParameters = SymbolLookup.loaderLookup().find("d2i_ECPKParameters").get(); + var ecparams = PEM_ASN1_read_bio(d2i_ECPKParameters, + PEM_STRING_ECPARAMETERS(), bio, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + BIO_free(bio); + if (!MemorySegment.NULL.equals(ecparams)) { + int curveNid = EC_GROUP_get_curve_name(ecparams); + var curveNidAddress = localArena.allocateFrom(ValueLayout.JAVA_INT, curveNid); + // SSL_CTX_set1_curves(state.sslCtx, &curveNid, 1) + if (SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_GROUPS(), 1, curveNidAddress) <= 0) { + curveNid = 0; + } + if (log.isDebugEnabled()) { + log.debug(sm.getString("openssl.setECDHCurve", curveNid, certificate.getCertificateFile())); + } + EC_GROUP_free(ecparams); + } } - // Set callback for DH parameters - var openSSLCallbackTmpDH = Linker.nativeLinker().upcallStub(openSSLCallbackTmpDHHandle, - openSSLCallbackTmpDHFunctionDescriptor, contextArena); - SSL_CTX_set_tmp_dh_callback(state.sslCtx, openSSLCallbackTmpDH); // Set certificate chain file if (certificate.getCertificateChainFile() != null) { var certificateChainFileNative = @@ -1223,10 +1257,27 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext { logLastError(localArena, "openssl.errorPrivateKeyCheck"); return; } - // Set callback for DH parameters - var openSSLCallbackTmpDH = Linker.nativeLinker().upcallStub(openSSLCallbackTmpDHHandle, - openSSLCallbackTmpDHFunctionDescriptor, contextArena); - SSL_CTX_set_tmp_dh_callback(state.sslCtx, openSSLCallbackTmpDH); + if (OpenSSL_version_num() < 0x3000000fL) { + // Set callback for DH parameters + var openSSLCallbackTmpDH = Linker.nativeLinker().upcallStub(openSSLCallbackTmpDHHandle, + openSSLCallbackTmpDHFunctionDescriptor, contextArena); + SSL_CTX_set_tmp_dh_callback(state.sslCtx, openSSLCallbackTmpDH); + } else { + bio = BIO_new(BIO_s_mem()); + BIO_write(bio, rawKey, (int) rawKey.byteSize()); + var pkey = PEM_read_bio_Parameters(bio, MemorySegment.NULL); + if (!MemorySegment.NULL.equals(pkey)) { + int numBits = EVP_PKEY_get_bits(pkey); + if (SSL_CTX_set0_tmp_dh_pkey(state.sslCtx, pkey) <= 0) { + EVP_PKEY_free(pkey); + } else { + log.debug(sm.getString("openssl.setCustomDHParameters", numBits, certificate.getCertificateFile())); + } + } else { + SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_DH_AUTO(), 1, MemorySegment.NULL); + } + BIO_free(bio); + } for (int i = 1; i < chain.length; i++) { //SSLContext.addChainCertificateRaw(state.ctx, chain[i].getEncoded()); var rawCertificateChain = localArena.allocateFrom(ValueLayout.JAVA_BYTE, chain[i].getEncoded()); diff --git a/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java b/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java index 43da3c13c9..ba3a1007ff 100644 --- a/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java +++ b/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java @@ -39,8 +39,6 @@ import org.apache.tomcat.util.res.StringManager; * configuration parameters. * Using this from a listener is completely optional, but is needed for * configuration and full cleanup of a few native memory allocations. - * FIXME: OpenSSL 3 deprecation resolutions for the equivalent code: - * https://svn.apache.org/viewvc?view=revision&revision=1908537 */ public class OpenSSLLibrary { @@ -178,9 +176,12 @@ public class OpenSSLLibrary { // Main library init initLibrary(); + // OpenSSL 3 onwards uses providers + boolean usingProviders = (OpenSSL_version_num() >= 0x3000000fL); + // Setup engine String engineName = "on".equalsIgnoreCase(SSLEngine) ? null : SSLEngine; - if (engineName != null) { + if (!usingProviders && engineName != null) { if ("auto".equals(engineName)) { ENGINE_register_all_complete(); } else { @@ -224,10 +225,9 @@ public class OpenSSLLibrary { RAND_seed(memorySession.allocateFrom(ValueLayout.JAVA_BYTE, randomBytes), 128); } - initDHParameters(); - - // OpenSSL 3 onwards uses providers - boolean usingProviders = (OpenSSL_version_num() >= 0x3000000fL); + if (!usingProviders) { + initDHParameters(); + } if (usingProviders || !(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode))) { fipsModeActive = false; @@ -335,11 +335,11 @@ public class OpenSSLLibrary { OpenSSLStatus.setAvailable(false); try { - freeDHParameters(); - if (!MemorySegment.NULL.equals(enginePointer)) { - ENGINE_free(enginePointer); - } if (OpenSSL_version_num() < 0x3000000fL) { + freeDHParameters(); + if (!MemorySegment.NULL.equals(enginePointer)) { + ENGINE_free(enginePointer); + } FIPS_mode_set(0); } } finally { diff --git a/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/openssl/openssl_h.java b/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/openssl/openssl_h.java index 978e7551c4..fc5ad10d81 100644 --- a/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/openssl/openssl_h.java +++ b/modules/openssl-foreign/src/main/java/org/apache/tomcat/util/openssl/openssl_h.java @@ -1226,6 +1226,7 @@ public class openssl_h { * EC_KEY* EC_KEY_new_by_curve_name(int nid); * } */ + @Deprecated public static MemorySegment EC_KEY_new_by_curve_name(int nid) { var mh$ = EC_KEY_new_by_curve_name$MH(); try { @@ -1242,6 +1243,7 @@ public class openssl_h { * void EC_KEY_free(EC_KEY* key); * } */ + @Deprecated public static void EC_KEY_free(MemorySegment key) { var mh$ = EC_KEY_free$MH(); try { @@ -1258,6 +1260,7 @@ public class openssl_h { * DH* DH_new(); * } */ + @Deprecated public static MemorySegment DH_new() { var mh$ = DH_new$MH(); try { @@ -1274,6 +1277,7 @@ public class openssl_h { * void DH_free(DH* dh); * } */ + @Deprecated public static void DH_free(MemorySegment dh) { var mh$ = DH_free$MH(); try { @@ -1290,6 +1294,7 @@ public class openssl_h { * int DH_set0_pqg(DH* dh, BIGNUM* p, BIGNUM* q, BIGNUM* g); * } */ + @Deprecated public static int DH_set0_pqg(MemorySegment dh, MemorySegment p, MemorySegment q, MemorySegment g) { var mh$ = DH_set0_pqg$MH(); try { @@ -1642,6 +1647,7 @@ public class openssl_h { * EC_GROUP* PEM_read_bio_ECPKParameters(BIO* out, EC_GROUP** x, pem_password_cb* cb, void* u); * } */ + @Deprecated public static MemorySegment PEM_read_bio_ECPKParameters(MemorySegment out, MemorySegment x, MemorySegment cb, MemorySegment u) { var mh$ = PEM_read_bio_ECPKParameters$MH(); try { @@ -1658,6 +1664,7 @@ public class openssl_h { * DH* PEM_read_bio_DHparams(BIO* out, DH** x, pem_password_cb* cb, void* u); * } */ + @Deprecated public static MemorySegment PEM_read_bio_DHparams(MemorySegment out, MemorySegment x, MemorySegment cb, MemorySegment u) { var mh$ = PEM_read_bio_DHparams$MH(); try { @@ -2746,6 +2753,7 @@ public class openssl_h { * void SSL_CTX_set_tmp_dh_callback(SSL_CTX* ctx, DH* (*dh)(SSL*,int,int)); * } */ + @Deprecated public static void SSL_CTX_set_tmp_dh_callback(MemorySegment ctx, MemorySegment dh) { var mh$ = SSL_CTX_set_tmp_dh_callback$MH(); try { @@ -3066,6 +3074,7 @@ public class openssl_h { * ENGINE* ENGINE_by_id(char* id); * } */ + @Deprecated public static MemorySegment ENGINE_by_id(MemorySegment id) { var mh$ = ENGINE_by_id$MH(); try { @@ -3082,6 +3091,7 @@ public class openssl_h { * int ENGINE_register_all_complete(); * } */ + @Deprecated public static int ENGINE_register_all_complete() { var mh$ = ENGINE_register_all_complete$MH(); try { @@ -3098,6 +3108,7 @@ public class openssl_h { * int ENGINE_ctrl_cmd_string(ENGINE* e, char* cmd_name, char* arg, int cmd_optional); * } */ + @Deprecated public static int ENGINE_ctrl_cmd_string(MemorySegment e, MemorySegment cmd_name, MemorySegment arg, int cmd_optional) { var mh$ = ENGINE_ctrl_cmd_string$MH(); try { @@ -3114,6 +3125,7 @@ public class openssl_h { * int ENGINE_free(ENGINE* e); * } */ + @Deprecated public static int ENGINE_free(MemorySegment e) { var mh$ = ENGINE_free$MH(); try { @@ -3130,6 +3142,7 @@ public class openssl_h { * EVP_PKEY* ENGINE_load_private_key(ENGINE* e, char* key_id, UI_METHOD* ui_method, void* callback_data); * } */ + @Deprecated public static MemorySegment ENGINE_load_private_key(MemorySegment e, MemorySegment key_id, MemorySegment ui_method, MemorySegment callback_data) { var mh$ = ENGINE_load_private_key$MH(); try { @@ -3146,6 +3159,7 @@ public class openssl_h { * int ENGINE_set_default(ENGINE* e, unsigned int flags); * } */ + @Deprecated public static int ENGINE_set_default(MemorySegment e, int flags) { var mh$ = ENGINE_set_default$MH(); try { diff --git a/modules/openssl-foreign/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties b/modules/openssl-foreign/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties index b8b108272b..f1bff0a31a 100644 --- a/modules/openssl-foreign/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties +++ b/modules/openssl-foreign/src/main/resources/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties @@ -61,6 +61,8 @@ openssl.noCACerts=No CA certificates were configured openssl.nonJsseCertificate=The certificate [{0}] or its private key [{1}] could not be processed using a JSSE key manager and will be given directly to OpenSSL openssl.nonJsseChain=The certificate chain [{0}] was not specified or was not valid and JSSE requires a valid certificate chain so attempting to use OpenSSL directly openssl.passwordTooLong=The certificate password is too long +openssl.setCustomDHParameters=Setting custom DH parameters ([{0}] bits) for the key [{1}] +openssl.setECDHCurve=Setting ECDH curve ([{0}]) for the key [{1}] openssl.trustManagerMissing=No trust manager found opensslconf.applyCommand=OpenSSLConf applying command (name [{0}], value [{1}]) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org