You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2023/12/11 10:29:44 UTC

(tomcat) branch main updated: Use generated callback helpers

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 0170417668 Use generated callback helpers
0170417668 is described below

commit 01704176689c8a6bcdfd053e7709ef5ef22861cc
Author: remm <re...@apache.org>
AuthorDate: Mon Dec 11 11:29:19 2023 +0100

    Use generated callback helpers
    
    After careful review and testing, the helpers can reduce the amount of
    declarations and reflection looking code.
    The scary looking bindTo can cause problems but this will not happen if
    using a new instance that does not keep any references to what needs to
    be GCed (which is the same as before basically).
    Add back the helpers generated by jextract (with cleanup though).
---
 .../util/net/openssl/panama/OpenSSLContext.java    | 309 +++++++++------------
 .../util/net/openssl/panama/OpenSSLEngine.java     |  59 ++--
 .../openssl/SSL_CTX_set_alpn_select_cb$cb.java     |  57 ++++
 .../SSL_CTX_set_cert_verify_callback$cb.java       |  54 ++++
 .../openssl/SSL_CTX_set_default_passwd_cb$cb.java  |  55 ++++
 .../openssl/SSL_CTX_set_tmp_dh_callback$dh.java    |  54 ++++
 .../util/openssl/SSL_CTX_set_verify$callback.java  |  54 ++++
 .../util/openssl/SSL_set_info_callback$cb.java     |  54 ++++
 .../util/openssl/SSL_set_verify$callback.java      |  54 ++++
 9 files changed, 540 insertions(+), 210 deletions(-)

diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
index 4d087cf2b1..46c7a8ef39 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
@@ -21,15 +21,10 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.lang.foreign.Arena;
-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;
-import java.lang.invoke.MethodType;
 import java.lang.ref.Cleaner;
 import java.lang.ref.Cleaner.Cleanable;
 import java.nio.charset.StandardCharsets;
@@ -72,6 +67,11 @@ import org.apache.tomcat.util.net.openssl.OpenSSLConf;
 import org.apache.tomcat.util.net.openssl.OpenSSLConfCmd;
 import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
 import org.apache.tomcat.util.net.openssl.OpenSSLUtil;
+import org.apache.tomcat.util.openssl.SSL_CTX_set_alpn_select_cb$cb;
+import org.apache.tomcat.util.openssl.SSL_CTX_set_cert_verify_callback$cb;
+import org.apache.tomcat.util.openssl.SSL_CTX_set_default_passwd_cb$cb;
+import org.apache.tomcat.util.openssl.SSL_CTX_set_tmp_dh_callback$dh;
+import org.apache.tomcat.util.openssl.SSL_CTX_set_verify$callback;
 import org.apache.tomcat.util.res.StringManager;
 
 public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
@@ -118,46 +118,6 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
         }
     }
 
-    private static final MethodHandle openSSLCallbackVerifyHandle;
-    private static final MethodHandle openSSLCallbackPasswordHandle;
-    private static final MethodHandle openSSLCallbackCertVerifyHandle;
-    private static final MethodHandle openSSLCallbackAlpnSelectProtoHandle;
-    private static final MethodHandle openSSLCallbackTmpDHHandle;
-
-    private static final FunctionDescriptor openSSLCallbackVerifyFunctionDescriptor =
-            FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
-    private static final FunctionDescriptor openSSLCallbackPasswordFunctionDescriptor =
-            FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_INT,
-            ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
-    private static final FunctionDescriptor openSSLCallbackCertVerifyFunctionDescriptor =
-            FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
-    private static final FunctionDescriptor openSSLCallbackAlpnSelectProtoFunctionDescriptor =
-            FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS,
-            ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.ADDRESS,
-            ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
-    private static final FunctionDescriptor openSSLCallbackTmpDHFunctionDescriptor =
-            FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS,
-            ValueLayout.JAVA_INT, ValueLayout.JAVA_INT);
-
-    static {
-        MethodHandles.Lookup lookup = MethodHandles.lookup();
-        try {
-            openSSLCallbackVerifyHandle = lookup.findStatic(OpenSSLContext.class, "openSSLCallbackVerify",
-                    MethodType.methodType(int.class, int.class, MemorySegment.class));
-            openSSLCallbackPasswordHandle = lookup.findStatic(OpenSSLContext.class, "openSSLCallbackPassword",
-                    MethodType.methodType(int.class, MemorySegment.class, int.class, int.class, MemorySegment.class));
-            openSSLCallbackCertVerifyHandle = lookup.findStatic(OpenSSLContext.class, "openSSLCallbackCertVerify",
-                    MethodType.methodType(int.class, MemorySegment.class, MemorySegment.class));
-            openSSLCallbackAlpnSelectProtoHandle = lookup.findStatic(OpenSSLContext.class, "openSSLCallbackAlpnSelectProto",
-                    MethodType.methodType(int.class, MemorySegment.class, MemorySegment.class,
-                            MemorySegment.class, MemorySegment.class, int.class, MemorySegment.class));
-            openSSLCallbackTmpDHHandle = lookup.findStatic(OpenSSLContext.class, "openSSLCallbackTmpDH",
-                    MethodType.methodType(MemorySegment.class, MemorySegment.class, int.class, int.class));
-        } catch (Exception e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
     static final boolean OPENSSL_3 = (OpenSSL_version_num() >= 0x3000000fL);
 
     private final SSLHostConfig sslHostConfig;
@@ -328,9 +288,7 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
             // Probably not needed
 
             // Set int pem_password_cb(char *buf, int size, int rwflag, void *u) callback
-            openSSLCallbackPassword =
-                    Linker.nativeLinker().upcallStub(openSSLCallbackPasswordHandle,
-                    openSSLCallbackPasswordFunctionDescriptor, contextArena);
+            openSSLCallbackPassword = SSL_CTX_set_default_passwd_cb$cb.allocate(new PasswordCallback(), contextArena);
             SSL_CTX_set_default_passwd_cb(sslCtx, openSSLCallbackPassword);
 
             if (negotiableProtocols != null && negotiableProtocols.size() > 0) {
@@ -606,20 +564,16 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
             }
 
             // Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback
-            var openSSLCallbackVerify =
-                    Linker.nativeLinker().upcallStub(openSSLCallbackVerifyHandle,
-                    openSSLCallbackVerifyFunctionDescriptor, contextArena);
             // Leave this just in case but in Tomcat this is always set again by the engine
-            SSL_CTX_set_verify(state.sslCtx, value, openSSLCallbackVerify);
+            SSL_CTX_set_verify(state.sslCtx, value,
+                    SSL_CTX_set_verify$callback.allocate(new VerifyCallback(), contextArena));
 
             // Trust and certificate verification
             if (tms != null) {
                 // Client certificate verification based on custom trust managers
                 state.x509TrustManager = chooseTrustManager(tms);
-                var openSSLCallbackCertVerify =
-                        Linker.nativeLinker().upcallStub(openSSLCallbackCertVerifyHandle,
-                                openSSLCallbackCertVerifyFunctionDescriptor, contextArena);
-                SSL_CTX_set_cert_verify_callback(state.sslCtx, openSSLCallbackCertVerify, state.sslCtx);
+                SSL_CTX_set_cert_verify_callback(state.sslCtx,
+                        SSL_CTX_set_cert_verify_callback$cb.allocate(new CertVerifyCallback(), contextArena), state.sslCtx);
 
                 // Pass along the DER encoded certificates of the accepted client
                 // certificate issuers, so that their subjects can be presented
@@ -674,10 +628,8 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
             if (state.negotiableProtocols != null && state.negotiableProtocols.size() > 0) {
                 // int openSSLCallbackAlpnSelectProto(MemoryAddress ssl, MemoryAddress out, MemoryAddress outlen,
                 //        MemoryAddress in, int inlen, MemoryAddress arg
-                var openSSLCallbackAlpnSelectProto =
-                        Linker.nativeLinker().upcallStub(openSSLCallbackAlpnSelectProtoHandle,
-                        openSSLCallbackAlpnSelectProtoFunctionDescriptor, contextArena);
-                SSL_CTX_set_alpn_select_cb(state.sslCtx, openSSLCallbackAlpnSelectProto, state.sslCtx);
+                SSL_CTX_set_alpn_select_cb(state.sslCtx,
+                        SSL_CTX_set_alpn_select_cb$cb.allocate(new ALPNSelectCallback(), contextArena), state.sslCtx);
             }
 
             // Apply OpenSSLConfCmd if used
@@ -756,116 +708,129 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
     }
 
     // DH *(*tmp_dh_callback)(SSL *ssl, int is_export, int keylength)
-    public static MemorySegment openSSLCallbackTmpDH(MemorySegment ssl, @SuppressWarnings("unused") int isExport,
-            @SuppressWarnings("unused") int keylength) {
-        var pkey = SSL_get_privatekey(ssl);
-        int type = (MemorySegment.NULL.equals(pkey)) ? EVP_PKEY_NONE() : EVP_PKEY_base_id(pkey);
-        /*
-         * OpenSSL will call us with either keylen == 512 or keylen == 1024
-         * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
-         * Adjust the DH parameter length according to the size of the
-         * RSA/DSA private key used for the current connection, and always
-         * use at least 1024-bit parameters.
-         * Note: This may cause interoperability issues with implementations
-         * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
-         * In this case, SSLCertificateFile can be used to specify fixed
-         * 1024-bit DH parameters (with the effect that OpenSSL skips this
-         * callback).
-         */
-        int keylen = 0;
-        if (type == EVP_PKEY_RSA() || type == EVP_PKEY_DSA()) {
-            keylen = EVP_PKEY_bits(pkey);
-        }
-        for (int i = 0; i < OpenSSLLibrary.dhParameters.length; i++) {
-            if (keylen >= OpenSSLLibrary.dhParameters[i].min) {
-                return OpenSSLLibrary.dhParameters[i].dh;
+    private static class TmpDHCallback implements SSL_CTX_set_tmp_dh_callback$dh {
+        @Override
+        public MemorySegment apply(MemorySegment ssl, @SuppressWarnings("unused") int isExport,
+                @SuppressWarnings("unused") int keylength) {
+            var pkey = SSL_get_privatekey(ssl);
+            int type = (MemorySegment.NULL.equals(pkey)) ? EVP_PKEY_NONE() : EVP_PKEY_base_id(pkey);
+            /*
+             * OpenSSL will call us with either keylen == 512 or keylen == 1024
+             * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h).
+             * Adjust the DH parameter length according to the size of the
+             * RSA/DSA private key used for the current connection, and always
+             * use at least 1024-bit parameters.
+             * Note: This may cause interoperability issues with implementations
+             * which limit their DH support to 1024 bit - e.g. Java 7 and earlier.
+             * In this case, SSLCertificateFile can be used to specify fixed
+             * 1024-bit DH parameters (with the effect that OpenSSL skips this
+             * callback).
+             */
+            int keylen = 0;
+            if (type == EVP_PKEY_RSA() || type == EVP_PKEY_DSA()) {
+                keylen = EVP_PKEY_bits(pkey);
             }
+            for (int i = 0; i < OpenSSLLibrary.dhParameters.length; i++) {
+                if (keylen >= OpenSSLLibrary.dhParameters[i].min) {
+                    return OpenSSLLibrary.dhParameters[i].dh;
+                }
+            }
+            return MemorySegment.NULL;
         }
-        return MemorySegment.NULL;
     }
 
     // int SSL_callback_alpn_select_proto(SSL* ssl, const unsigned char **out, unsigned char *outlen,
     //        const unsigned char *in, unsigned int inlen, void *arg)
-    public static int openSSLCallbackAlpnSelectProto(@SuppressWarnings("unused") MemorySegment ssl, MemorySegment out,
-            MemorySegment outlen, MemorySegment in, int inlen, MemorySegment arg) {
-        ContextState state = getState(arg);
-        if (state == null) {
-            log.warn(sm.getString("context.noSSL", Long.valueOf(arg.address())));
-            return SSL_TLSEXT_ERR_NOACK();
-        }
-        try (var localArena = Arena.ofConfined()) {
-            MemorySegment inSeg = in.reinterpret(inlen, localArena, null);
-            byte[] advertisedBytes = inSeg.toArray(ValueLayout.JAVA_BYTE);
-            for (byte[] negotiableProtocolBytes : state.negotiableProtocols) {
-                for (int i = 0; i <= advertisedBytes.length - negotiableProtocolBytes.length; i++) {
-                    if (advertisedBytes[i] == negotiableProtocolBytes[0]) {
-                        for (int j = 0; j < negotiableProtocolBytes.length; j++) {
-                            if (advertisedBytes[i + j] == negotiableProtocolBytes[j]) {
-                                if (j == negotiableProtocolBytes.length - 1) {
-                                    // Match
-                                    MemorySegment outSeg = out.reinterpret(ValueLayout.ADDRESS.byteSize(), localArena, null);
-                                    outSeg.set(ValueLayout.ADDRESS, 0, inSeg.asSlice(i));
-                                    MemorySegment outlenSeg = outlen.reinterpret(ValueLayout.JAVA_BYTE.byteSize(), localArena, null);
-                                    outlenSeg.set(ValueLayout.JAVA_BYTE, 0, (byte) negotiableProtocolBytes.length);
-                                    return SSL_TLSEXT_ERR_OK();
+    private static class ALPNSelectCallback implements SSL_CTX_set_alpn_select_cb$cb {
+        @Override
+        public int apply(@SuppressWarnings("unused") MemorySegment ssl, MemorySegment out,
+                MemorySegment outlen, MemorySegment in, int inlen, MemorySegment arg) {
+            ContextState state = getState(arg);
+            if (state == null) {
+                log.warn(sm.getString("context.noSSL", Long.valueOf(arg.address())));
+                return SSL_TLSEXT_ERR_NOACK();
+            }
+            try (var localArena = Arena.ofConfined()) {
+                MemorySegment inSeg = in.reinterpret(inlen, localArena, null);
+                byte[] advertisedBytes = inSeg.toArray(ValueLayout.JAVA_BYTE);
+                for (byte[] negotiableProtocolBytes : state.negotiableProtocols) {
+                    for (int i = 0; i <= advertisedBytes.length - negotiableProtocolBytes.length; i++) {
+                        if (advertisedBytes[i] == negotiableProtocolBytes[0]) {
+                            for (int j = 0; j < negotiableProtocolBytes.length; j++) {
+                                if (advertisedBytes[i + j] == negotiableProtocolBytes[j]) {
+                                    if (j == negotiableProtocolBytes.length - 1) {
+                                        // Match
+                                        MemorySegment outSeg = out.reinterpret(ValueLayout.ADDRESS.byteSize(), localArena, null);
+                                        outSeg.set(ValueLayout.ADDRESS, 0, inSeg.asSlice(i));
+                                        MemorySegment outlenSeg = outlen.reinterpret(ValueLayout.JAVA_BYTE.byteSize(), localArena, null);
+                                        outlenSeg.set(ValueLayout.JAVA_BYTE, 0, (byte) negotiableProtocolBytes.length);
+                                        return SSL_TLSEXT_ERR_OK();
+                                    }
+                                } else {
+                                    break;
                                 }
-                            } else {
-                                break;
                             }
                         }
                     }
                 }
             }
+            return SSL_TLSEXT_ERR_NOACK();
         }
-        return SSL_TLSEXT_ERR_NOACK();
     }
 
-    public static int openSSLCallbackVerify(int preverify_ok, MemorySegment /*X509_STORE_CTX*/ x509ctx) {
-        return OpenSSLEngine.openSSLCallbackVerify(preverify_ok, x509ctx);
+
+    private static class VerifyCallback implements SSL_CTX_set_verify$callback {
+        @Override
+        public int apply(int preverify_ok, MemorySegment /*X509_STORE_CTX*/ x509ctx) {
+            return OpenSSLEngine.openSSLCallbackVerify(preverify_ok, x509ctx);
+        }
     }
 
 
-    public static int openSSLCallbackCertVerify(MemorySegment /*X509_STORE_CTX*/ x509_ctx, MemorySegment param) {
-        if (log.isDebugEnabled()) {
-            log.debug("Certificate verification");
-        }
-        if (MemorySegment.NULL.equals(param)) {
-            return 0;
-        }
-        ContextState state = getState(param);
-        if (state == null) {
-            log.warn(sm.getString("context.noSSL", Long.valueOf(param.address())));
-            return 0;
-        }
-        MemorySegment ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
-        MemorySegment /*STACK_OF(X509)*/ sk = X509_STORE_CTX_get0_untrusted(x509_ctx);
-        int len = OPENSSL_sk_num(sk);
-        byte[][] certificateChain = new byte[len][];
-        try (var localArena = Arena.ofConfined()) {
-            for (int i = 0; i < len; i++) {
-                MemorySegment/*(X509*)*/ x509 = OPENSSL_sk_value(sk, i);
-                MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL);
-                int length = i2d_X509(x509, bufPointer);
-                if (length < 0) {
-                    certificateChain[i] = new byte[0];
-                    continue;
-                }
-                MemorySegment buf = bufPointer.get(ValueLayout.ADDRESS, 0);
-                certificateChain[i] = buf.reinterpret(length, localArena, null).toArray(ValueLayout.JAVA_BYTE);
-                OPENSSL_free(buf);
+    private static class CertVerifyCallback implements SSL_CTX_set_cert_verify_callback$cb {
+        @Override
+        public int apply(MemorySegment /*X509_STORE_CTX*/ x509_ctx, MemorySegment param) {
+            if (log.isDebugEnabled()) {
+                log.debug("Certificate verification");
             }
-            MemorySegment cipher = SSL_get_current_cipher(ssl);
-            String authMethod = (MemorySegment.NULL.equals(cipher)) ? "UNKNOWN"
-                    : getCipherAuthenticationMethod(SSL_CIPHER_get_auth_nid(cipher), SSL_CIPHER_get_kx_nid(cipher));
-            X509Certificate[] peerCerts = certificates(certificateChain);
-            try {
-                state.x509TrustManager.checkClientTrusted(peerCerts, authMethod);
-                return 1;
-            } catch (Exception e) {
-                log.debug(sm.getString("openssl.certificateVerificationFailed"), e);
+            if (MemorySegment.NULL.equals(param)) {
+                return 0;
             }
+            ContextState state = getState(param);
+            if (state == null) {
+                log.warn(sm.getString("context.noSSL", Long.valueOf(param.address())));
+                return 0;
+            }
+            MemorySegment ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+            MemorySegment /*STACK_OF(X509)*/ sk = X509_STORE_CTX_get0_untrusted(x509_ctx);
+            int len = OPENSSL_sk_num(sk);
+            byte[][] certificateChain = new byte[len][];
+            try (var localArena = Arena.ofConfined()) {
+                for (int i = 0; i < len; i++) {
+                    MemorySegment/*(X509*)*/ x509 = OPENSSL_sk_value(sk, i);
+                    MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL);
+                    int length = i2d_X509(x509, bufPointer);
+                    if (length < 0) {
+                        certificateChain[i] = new byte[0];
+                        continue;
+                    }
+                    MemorySegment buf = bufPointer.get(ValueLayout.ADDRESS, 0);
+                    certificateChain[i] = buf.reinterpret(length, localArena, null).toArray(ValueLayout.JAVA_BYTE);
+                    OPENSSL_free(buf);
+                }
+                MemorySegment cipher = SSL_get_current_cipher(ssl);
+                String authMethod = (MemorySegment.NULL.equals(cipher)) ? "UNKNOWN"
+                        : getCipherAuthenticationMethod(SSL_CIPHER_get_auth_nid(cipher), SSL_CIPHER_get_kx_nid(cipher));
+                X509Certificate[] peerCerts = certificates(certificateChain);
+                try {
+                    state.x509TrustManager.checkClientTrusted(peerCerts, authMethod);
+                    return 1;
+                } catch (Exception e) {
+                    log.debug(sm.getString("openssl.certificateVerificationFailed"), e);
+                }
+            }
+            return 0;
         }
-        return 0;
     }
 
     private static final int NID_kx_rsa = 1037/*NID_kx_rsa()*/;
@@ -953,26 +918,29 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
 
     private static ThreadLocal<String> callbackPasswordTheadLocal = new ThreadLocal<>();
 
-    public static int openSSLCallbackPassword(MemorySegment /*char **/ buf, int bufsiz,
-            @SuppressWarnings("unused") int verify, @SuppressWarnings("unused") MemorySegment /*void **/ cb) {
-        if (log.isDebugEnabled()) {
-            log.debug("Return password for certificate");
-        }
-        String callbackPassword = callbackPasswordTheadLocal.get();
-        if (callbackPassword != null && callbackPassword.length() > 0) {
-            try (var localArena = Arena.ofConfined()) {
-                MemorySegment callbackPasswordNative = localArena.allocateFrom(callbackPassword);
-                if (callbackPasswordNative.byteSize() > bufsiz) {
-                    // The password is too long
-                    log.error(sm.getString("openssl.passwordTooLong"));
-                } else {
-                    MemorySegment bufSegment = buf.reinterpret(bufsiz, localArena, null);
-                    bufSegment.copyFrom(callbackPasswordNative);
-                    return (int) callbackPasswordNative.byteSize();
+    private static class PasswordCallback implements SSL_CTX_set_default_passwd_cb$cb {
+        @Override
+        public int apply(MemorySegment /*char **/ buf, int bufsiz,
+                @SuppressWarnings("unused") int verify, @SuppressWarnings("unused") MemorySegment /*void **/ cb) {
+            if (log.isDebugEnabled()) {
+                log.debug("Return password for certificate");
+            }
+            String callbackPassword = callbackPasswordTheadLocal.get();
+            if (callbackPassword != null && callbackPassword.length() > 0) {
+                try (var localArena = Arena.ofConfined()) {
+                    MemorySegment callbackPasswordNative = localArena.allocateFrom(callbackPassword);
+                    if (callbackPasswordNative.byteSize() > bufsiz) {
+                        // The password is too long
+                        log.error(sm.getString("openssl.passwordTooLong"));
+                    } else {
+                        MemorySegment bufSegment = buf.reinterpret(bufsiz, localArena, null);
+                        bufSegment.copyFrom(callbackPasswordNative);
+                        return (int) callbackPasswordNative.byteSize();
+                    }
                 }
             }
+            return 0;
         }
-        return 0;
     }
 
 
@@ -1176,9 +1144,7 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
                         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);
+                    SSL_CTX_set_tmp_dh_callback(state.sslCtx, SSL_CTX_set_tmp_dh_callback$dh.allocate(new TmpDHCallback(), contextArena));
                 } else {
                     var d2i_ECPKParameters = SymbolLookup.loaderLookup().find("d2i_ECPKParameters").get();
                     var ecparams = PEM_ASN1_read_bio(d2i_ECPKParameters,
@@ -1309,9 +1275,8 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
                 }
                 if (!OPENSSL_3) {
                     // Set callback for DH parameters
-                    var openSSLCallbackTmpDH = Linker.nativeLinker().upcallStub(openSSLCallbackTmpDHHandle,
-                            openSSLCallbackTmpDHFunctionDescriptor, contextArena);
-                    SSL_CTX_set_tmp_dh_callback(state.sslCtx, openSSLCallbackTmpDH);
+                    SSL_CTX_set_tmp_dh_callback(state.sslCtx,
+                            SSL_CTX_set_tmp_dh_callback$dh.allocate(new TmpDHCallback(), contextArena));
                 } else {
                     BIO_reset(keyBIO);
                     var pkey = PEM_read_bio_Parameters(keyBIO, MemorySegment.NULL);
diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
index 2f20bd80cf..9bbd9881e9 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
@@ -19,13 +19,8 @@ package org.apache.tomcat.util.net.openssl.panama;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
 import java.lang.foreign.Arena;
-import java.lang.foreign.FunctionDescriptor;
-import java.lang.foreign.Linker;
 import java.lang.foreign.MemorySegment;
 import java.lang.foreign.ValueLayout;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
 import java.lang.ref.Cleaner;
 import java.lang.ref.Cleaner.Cleanable;
 import java.net.HttpURLConnection;
@@ -67,6 +62,8 @@ import org.apache.tomcat.util.buf.Asn1Parser;
 import org.apache.tomcat.util.net.Constants;
 import org.apache.tomcat.util.net.SSLUtil;
 import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser;
+import org.apache.tomcat.util.openssl.SSL_set_info_callback$cb;
+import org.apache.tomcat.util.openssl.SSL_set_verify$callback;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -85,29 +82,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
 
     public static final Set<String> IMPLEMENTED_PROTOCOLS_SET;
 
-    private static final MethodHandle openSSLCallbackInfoHandle;
-    private static final MethodHandle openSSLCallbackVerifyHandle;
-
-    private static final FunctionDescriptor openSSLCallbackInfoFunctionDescriptor =
-            FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.JAVA_INT);
-    private static final FunctionDescriptor openSSLCallbackVerifyFunctionDescriptor =
-            FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT, ValueLayout.ADDRESS);
-
     static {
-        MethodHandles.Lookup lookup = MethodHandles.lookup();
-        try {
-            openSSLCallbackInfoHandle = lookup.findStatic(OpenSSLEngine.class, "openSSLCallbackInfo",
-                    MethodType.methodType(void.class, MemorySegment.class, int.class, int.class));
-            openSSLCallbackVerifyHandle = lookup.findStatic(OpenSSLEngine.class, "openSSLCallbackVerify",
-                    MethodType.methodType(int.class, int.class, MemorySegment.class));
-        } catch (Exception e) {
-            throw new IllegalStateException(e);
-        }
-
         final Set<String> availableCipherSuites = new LinkedHashSet<>(128);
         availableCipherSuites.addAll(OpenSSLLibrary.findCiphers("ALL"));
         AVAILABLE_CIPHER_SUITES = Collections.unmodifiableSet(availableCipherSuites);
-
         HashSet<String> protocols = new HashSet<>();
         protocols.add(Constants.SSL_PROTO_SSLv2Hello);
         protocols.add(Constants.SSL_PROTO_SSLv2);
@@ -212,9 +190,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
         session = new OpenSSLSession();
         var ssl = SSL_new(sslCtx);
         // Set ssl_info_callback
-        var openSSLCallbackInfo = Linker.nativeLinker().upcallStub(openSSLCallbackInfoHandle,
-                openSSLCallbackInfoFunctionDescriptor, engineArena);
-        SSL_set_info_callback(ssl, openSSLCallbackInfo);
+        SSL_set_info_callback(ssl, SSL_set_info_callback$cb.allocate(new InfoCallback(), engineArena));
         if (clientMode) {
             SSL_set_connect_state(ssl);
         } else {
@@ -1159,27 +1135,34 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
             };
             // SSL.setVerify(state.ssl, value, certificateVerificationDepth);
             // Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback
-            var openSSLCallbackVerify =
-                    Linker.nativeLinker().upcallStub(openSSLCallbackVerifyHandle,
-                    openSSLCallbackVerifyFunctionDescriptor, engineArena);
             int value = switch (mode) {
                 case NONE -> SSL_VERIFY_NONE();
                 case REQUIRE -> SSL_VERIFY_PEER() | SSL_VERIFY_FAIL_IF_NO_PEER_CERT();
                 case OPTIONAL -> SSL_VERIFY_PEER();
             };
-            SSL_set_verify(state.ssl, value, openSSLCallbackVerify);
+            SSL_set_verify(state.ssl, value, SSL_set_verify$callback.allocate(new VerifyCallback(), engineArena));
             clientAuth = mode;
         }
     }
 
-    public static void openSSLCallbackInfo(MemorySegment ssl, int where, @SuppressWarnings("unused") int ret) {
-        EngineState state = getState(ssl);
-        if (state == null) {
-            log.warn(sm.getString("engine.noSSL", Long.valueOf(ssl.address())));
-            return;
+    private static class InfoCallback implements SSL_set_info_callback$cb {
+        @Override
+        public void apply(MemorySegment ssl, int where, @SuppressWarnings("unused") int ret) {
+            EngineState state = getState(ssl);
+            if (state == null) {
+                log.warn(sm.getString("engine.noSSL", Long.valueOf(ssl.address())));
+                return;
+            }
+            if (0 != (where & SSL_CB_HANDSHAKE_DONE())) {
+                state.handshakeCount++;
+            }
         }
-        if (0 != (where & SSL_CB_HANDSHAKE_DONE())) {
-            state.handshakeCount++;
+    }
+
+    private static class VerifyCallback implements SSL_set_verify$callback {
+        @Override
+        public int apply(int preverify_ok, MemorySegment /*X509_STORE_CTX*/ x509ctx) {
+            return openSSLCallbackVerify(preverify_ok, x509ctx);
         }
     }
 
diff --git a/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java
new file mode 100644
index 0000000000..1ace09bee7
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c
+ * : * int (*SSL_CTX_set_alpn_select_cb$cb)(struct ssl_st*,unsigned char**,unsigned char*,unsigned char*,unsigned int,void*);
+ * }
+ */
+public interface SSL_CTX_set_alpn_select_cb$cb {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.of(JAVA_INT, openssl_h.C_POINTER, openssl_h.C_POINTER,
+            openssl_h.C_POINTER, openssl_h.C_POINTER, JAVA_INT, openssl_h.C_POINTER);
+
+    int apply(MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, MemorySegment _x3, int _x4, MemorySegment _x5);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_alpn_select_cb$cb.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_CTX_set_alpn_select_cb$cb fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_CTX_set_alpn_select_cb$cb ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (MemorySegment __x0, MemorySegment __x1, MemorySegment __x2, MemorySegment __x3, int __x4,
+                MemorySegment __x5) -> {
+            try {
+                return (int) DOWN$MH.invokeExact(symbol, __x0, __x1, __x2, __x3, __x4, __x5);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java
new file mode 100644
index 0000000000..40f20e3c34
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c : * int (*SSL_CTX_set_cert_verify_callback$cb)(struct x509_store_ctx_st*,void*);
+ * }
+ */
+public interface SSL_CTX_set_cert_verify_callback$cb {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.of(JAVA_INT, openssl_h.C_POINTER, openssl_h.C_POINTER);
+
+    int apply(MemorySegment _x0, MemorySegment _x1);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_cert_verify_callback$cb.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_CTX_set_cert_verify_callback$cb fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_CTX_set_cert_verify_callback$cb ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (MemorySegment __x0, MemorySegment __x1) -> {
+            try {
+                return (int) DOWN$MH.invokeExact(symbol, __x0, __x1);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/openssl/SSL_CTX_set_default_passwd_cb$cb.java b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_default_passwd_cb$cb.java
new file mode 100644
index 0000000000..2d12398c98
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_default_passwd_cb$cb.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c : * int (*SSL_CTX_set_default_passwd_cb$cb)(char*,int,int,void*);
+ * }
+ */
+public interface SSL_CTX_set_default_passwd_cb$cb {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.of(JAVA_INT, openssl_h.C_POINTER, JAVA_INT, JAVA_INT,
+            openssl_h.C_POINTER);
+
+    int apply(MemorySegment _x0, int _x1, int _x2, MemorySegment _x3);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_default_passwd_cb$cb.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_CTX_set_default_passwd_cb$cb fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_CTX_set_default_passwd_cb$cb ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (MemorySegment __x0, int __x1, int __x2, MemorySegment __x3) -> {
+            try {
+                return (int) DOWN$MH.invokeExact(symbol, __x0, __x1, __x2, __x3);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java
new file mode 100644
index 0000000000..3062227589
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c : * struct dh_st* (*SSL_CTX_set_tmp_dh_callback$dh)(struct ssl_st*,int,int);
+ * }
+ */
+public interface SSL_CTX_set_tmp_dh_callback$dh {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, JAVA_INT, JAVA_INT);
+
+    MemorySegment apply(MemorySegment _x0, int _x1, int _x2);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_tmp_dh_callback$dh.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_CTX_set_tmp_dh_callback$dh fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_CTX_set_tmp_dh_callback$dh ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (MemorySegment __x0, int __x1, int __x2) -> {
+            try {
+                return (MemorySegment) DOWN$MH.invokeExact(symbol, __x0, __x1, __x2);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java
new file mode 100644
index 0000000000..cffcc12233
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c : * int (*SSL_CTX_set_verify$callback)(int,struct x509_store_ctx_st*);
+ * }
+ */
+public interface SSL_CTX_set_verify$callback {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, openssl_h.C_POINTER);
+
+    int apply(int _x0, MemorySegment _x1);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_verify$callback.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_CTX_set_verify$callback fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_CTX_set_verify$callback ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (int __x0, MemorySegment __x1) -> {
+            try {
+                return (int) DOWN$MH.invokeExact(symbol, __x0, __x1);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java b/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java
new file mode 100644
index 0000000000..d746b82e5c
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c : * void (*SSL_set_info_callback$cb)(struct ssl_st*,int,int);
+ * }
+ */
+public interface SSL_set_info_callback$cb {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER, JAVA_INT, JAVA_INT);
+
+    void apply(MemorySegment _x0, int _x1, int _x2);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_set_info_callback$cb.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_set_info_callback$cb fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_set_info_callback$cb ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (MemorySegment __x0, int __x1, int __x2) -> {
+            try {
+                DOWN$MH.invokeExact(symbol, __x0, __x1, __x2);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java b/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java
new file mode 100644
index 0000000000..a5bd44c14a
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Generated by jextract
+
+package org.apache.tomcat.util.openssl;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.foreign.*;
+import static java.lang.foreign.ValueLayout.*;
+
+/**
+ * {@snippet lang = c : * int (*SSL_set_verify$callback)(int,struct x509_store_ctx_st*);
+ * }
+ */
+public interface SSL_set_verify$callback {
+
+    FunctionDescriptor $DESC = FunctionDescriptor.of(JAVA_INT, JAVA_INT, openssl_h.C_POINTER);
+
+    int apply(int _x0, MemorySegment _x1);
+
+    MethodHandle UP$MH = openssl_h.upcallHandle(SSL_set_verify$callback.class, "apply", $DESC);
+
+    static MemorySegment allocate(SSL_set_verify$callback fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
+    }
+
+    MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);
+
+    static SSL_set_verify$callback ofAddress(MemorySegment addr, Arena arena) {
+        MemorySegment symbol = addr.reinterpret(arena, null);
+        return (int __x0, MemorySegment __x1) -> {
+            try {
+                return (int) DOWN$MH.invokeExact(symbol, __x0, __x1);
+            } catch (Throwable ex$) {
+                throw new AssertionError("should not reach here", ex$);
+            }
+        };
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org