This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 2ad4b3d7efad045746277de04cb079622f0dab19
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Sep 22 13:52:58 2026 +0100

    Expand the PSK support to cover OpenSSL-FFM
    
    Co-authored-by: GitHub Copilot (GPT-5.6 Sol) <[email protected]>
---
 .../net/openssl/panama/LocalStrings.properties     |   1 +
 .../util/net/openssl/panama/OpenSSLContext.java    | 125 ++++++++++++-
 .../util/net/openssl/panama/OpenSSLUtil.java       |   3 +
 .../util/openssl/SSL_psk_find_session_cb_func.java |  63 +++++++
 .../util/openssl/SSL_psk_server_cb_func.java       |  63 +++++++
 java/org/apache/tomcat/util/openssl/openssl_h.java | 202 ++++++++++++++++++++-
 res/openssl/openssl-tomcat.conf                    |  11 ++
 webapps/docs/changelog.xml                         |   4 +
 webapps/docs/config/http.xml                       |   5 +-
 9 files changed, 467 insertions(+), 10 deletions(-)

diff --git 
a/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties 
b/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties
index 758130a0c8..ad24091af1 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties
@@ -70,6 +70,7 @@ 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.pskTls13Unsupported=The OpenSSL implementation does not support TLS 
1.3 pre-shared keys
 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
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 48e4296632..26358d4d24 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
@@ -36,6 +36,7 @@ import java.util.Arrays;
 import java.util.Base64;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLEngine;
@@ -60,9 +61,11 @@ import org.apache.tomcat.util.net.SSLHostConfig;
 import org.apache.tomcat.util.net.SSLHostConfig.CertificateVerification;
 import org.apache.tomcat.util.net.SSLHostConfigCertificate;
 import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
+import org.apache.tomcat.util.net.SSLHostConfigPreSharedKey;
 import org.apache.tomcat.util.net.SSLUtilBase;
 import org.apache.tomcat.util.net.openssl.OpenSSLConf;
 import org.apache.tomcat.util.net.openssl.OpenSSLConfCmd;
+import org.apache.tomcat.util.net.openssl.OpenSSLPreSharedKeySelector;
 import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
 import org.apache.tomcat.util.net.openssl.OpenSSLUtil;
 import org.apache.tomcat.util.net.openssl.ciphers.Group;
@@ -70,6 +73,8 @@ 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_tmp_dh_callback$dh;
 import org.apache.tomcat.util.openssl.SSL_CTX_set_verify$callback;
+import org.apache.tomcat.util.openssl.SSL_psk_find_session_cb_func;
+import org.apache.tomcat.util.openssl.SSL_psk_server_cb_func;
 import org.apache.tomcat.util.openssl.openssl_h;
 import org.apache.tomcat.util.openssl.openssl_h_Compatibility;
 import org.apache.tomcat.util.openssl.pem_password_cb;
@@ -493,7 +498,7 @@ public class OpenSSLContext implements 
org.apache.tomcat.util.net.SSLContext {
             log.warn(sm.getString("openssl.doubleInit"));
             return;
         }
-        boolean success;
+        boolean success = true;
         Exception cause = null;
         try (var localArena = Arena.ofConfined()) {
             if (sslHostConfig.getInsecureRenegotiation()) {
@@ -557,12 +562,14 @@ public class OpenSSLContext implements 
org.apache.tomcat.util.net.SSLContext {
                 }
             }
 
-            // If there is no certificate file must be using a KeyStore so a 
KeyManager is required.
-            // If there is a certificate file a KeyManager is helpful but not 
strictly necessary.
-            certificate.setCertificateKeyManager(
-                    OpenSSLUtil.chooseKeyManager(kms, 
certificate.getCertificateFile() == null));
+            if (!sslHostConfig.isPreSharedKeyOnly()) {
+                // If there is no certificate file must be using a KeyStore so 
a KeyManager is required.
+                // If there is a certificate file a KeyManager is helpful but 
not strictly necessary.
+                certificate.setCertificateKeyManager(
+                        OpenSSLUtil.chooseKeyManager(kms, 
certificate.getCertificateFile() == null));
 
-            success = addCertificate(certificate, localArena);
+                success = addCertificate(certificate, localArena);
+            }
 
             // Client certificate verification
             int value = switch (sslHostConfig.getCertificateVerification()) {
@@ -640,6 +647,23 @@ public class OpenSSLContext implements 
org.apache.tomcat.util.net.SSLContext {
                 }
             }
 
+            Set<SSLHostConfigPreSharedKey> psks = 
sslHostConfig.getPreSharedKeys();
+            if (!psks.isEmpty()) {
+                OpenSSLPreSharedKeySelector selector = new 
OpenSSLPreSharedKeySelector(psks);
+                for (String protocol : sslHostConfig.getEnabledProtocols()) {
+                    if (Constants.SSL_PROTO_TLSv1_2.equals(protocol)) {
+                        SSL_CTX_set_psk_server_callback(state.sslCtx, 
SSL_psk_server_cb_func
+                                .allocate(new PskServerCallback(selector), 
contextArena));
+                    } else if (Constants.SSL_PROTO_TLSv1_3.equals(protocol)) {
+                        if (openssl_h_Compatibility.LIBRESSL) {
+                            throw new 
SSLException(sm.getString("openssl.pskTls13Unsupported"));
+                        }
+                        SSL_CTX_set_psk_find_session_callback(state.sslCtx, 
SSL_psk_find_session_cb_func
+                                .allocate(new 
PskFindSessionCallback(selector), contextArena));
+                    }
+                }
+            }
+
             if (negotiableProtocols != null && !negotiableProtocols.isEmpty()) 
{
                 SSL_CTX_set_alpn_select_cb(state.sslCtx, 
SSL_CTX_set_alpn_select_cb$cb
                         .allocate(new ALPNSelectCallback(negotiableProtocols), 
contextArena), state.sslCtx);
@@ -792,6 +816,95 @@ public class OpenSSLContext implements 
org.apache.tomcat.util.net.SSLContext {
         }
     }
 
+    private static class PskServerCallback implements 
SSL_psk_server_cb_func.Function {
+
+        private final OpenSSLPreSharedKeySelector selector;
+
+        PskServerCallback(OpenSSLPreSharedKeySelector selector) {
+            this.selector = selector;
+        }
+
+        @Override
+        public int apply(MemorySegment ssl, MemorySegment identity, 
MemorySegment psk, int maxPskLength) {
+            if (MemorySegment.NULL.equals(identity)) {
+                return 0;
+            }
+            byte[] key = selector.select(ssl.address(), identity.getString(0));
+            if (key == null || key.length == 0 || key.length > maxPskLength) {
+                return 0;
+            }
+            try (var localArena = Arena.ofConfined()) {
+                psk.reinterpret(key.length, localArena, 
null).copyFrom(MemorySegment.ofArray(key));
+            }
+            return key.length;
+        }
+    }
+
+    private static class PskFindSessionCallback implements 
SSL_psk_find_session_cb_func.Function {
+
+        private final OpenSSLPreSharedKeySelector selector;
+
+        PskFindSessionCallback(OpenSSLPreSharedKeySelector selector) {
+            this.selector = selector;
+        }
+
+        @Override
+        public int apply(MemorySegment ssl, MemorySegment identity, long 
identityLength, MemorySegment sessionPointer) {
+            try (var localArena = Arena.ofConfined()) {
+                MemorySegment sessionPointerSegment =
+                        
sessionPointer.reinterpret(ValueLayout.ADDRESS.byteSize(), localArena, null);
+                sessionPointerSegment.set(ValueLayout.ADDRESS, 0, 
MemorySegment.NULL);
+                if (MemorySegment.NULL.equals(identity) || identityLength < 0 
|| identityLength > Integer.MAX_VALUE) {
+                    return 0;
+                }
+
+                byte[] identityBytes =
+                        identity.reinterpret(identityLength, localArena, 
null).toArray(ValueLayout.JAVA_BYTE);
+                int[] cipherSuite = new int[1];
+                byte[] key = selector.select(ssl.address(), identityBytes, 
cipherSuite);
+                if (key == null) {
+                    return 1;
+                }
+                if (key.length == 0 || cipherSuite[0] <= 0 || cipherSuite[0] > 
0xFFFF) {
+                    return 0;
+                }
+
+                byte[] cipherId = new byte[] { (byte) (cipherSuite[0] >> 8), 
(byte) cipherSuite[0] };
+                MemorySegment cipher =
+                        SSL_CIPHER_find(ssl, 
localArena.allocateFrom(ValueLayout.JAVA_BYTE, cipherId));
+                if (MemorySegment.NULL.equals(cipher)
+                        || 
!Constants.SSL_PROTO_TLSv1_3.equals(SSL_CIPHER_get_version(cipher).getString(0)))
 {
+                    return 0;
+                }
+
+                MemorySegment session = SSL_SESSION_new();
+                if (MemorySegment.NULL.equals(session)) {
+                    return 0;
+                }
+                boolean success = false;
+                try {
+                    MemorySegment keySegment = 
localArena.allocateFrom(ValueLayout.JAVA_BYTE, key);
+                    try {
+                        if (SSL_SESSION_set1_master_key(session, keySegment, 
key.length) == 0 ||
+                                SSL_SESSION_set_cipher(session, cipher) == 0 ||
+                                SSL_SESSION_set_protocol_version(session, 
TLS1_3_VERSION()) == 0) {
+                            return 0;
+                        }
+                    } finally {
+                        keySegment.fill((byte) 0);
+                    }
+                    sessionPointerSegment.set(ValueLayout.ADDRESS, 0, session);
+                    success = true;
+                    return 1;
+                } finally {
+                    if (!success) {
+                        SSL_SESSION_free(session);
+                    }
+                }
+            }
+        }
+    }
+
 
     private static class CertVerifyCallback implements 
SSL_CTX_set_cert_verify_callback$cb.Function {
         private final X509TrustManager x509TrustManager;
diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java 
b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java
index ba26f0c758..16e46081e6 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java
@@ -76,6 +76,9 @@ public class OpenSSLUtil extends SSLUtilBase {
 
     @Override
     public KeyManager[] getKeyManagers() throws Exception {
+        if (sslHostConfig.isPreSharedKeyOnly()) {
+            return null;
+        }
         try {
             return super.getKeyManagers();
         } catch (IllegalArgumentException e) {
diff --git 
a/java/org/apache/tomcat/util/openssl/SSL_psk_find_session_cb_func.java 
b/java/org/apache/tomcat/util/openssl/SSL_psk_find_session_cb_func.java
new file mode 100644
index 0000000000..efee3fea8d
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_psk_find_session_cb_func.java
@@ -0,0 +1,63 @@
+/*
+ * 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.foreign.Arena;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.Linker;
+import java.lang.foreign.MemorySegment;
+import java.lang.invoke.MethodHandle;
+
+/**
+ * {@snippet lang = c : * SSL_psk_find_session_cb_func cb
+ * }
+ */
+@SuppressWarnings("javadoc")
+public class SSL_psk_find_session_cb_func {
+
+    public interface Function {
+        int apply(MemorySegment ssl, MemorySegment identity, long 
identityLength, MemorySegment session);
+    }
+
+    private static final FunctionDescriptor $DESC = 
FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER,
+            openssl_h.C_POINTER, openssl_h.C_LONG, openssl_h.C_POINTER);
+
+    public static FunctionDescriptor descriptor() {
+        return $DESC;
+    }
+
+    private static final MethodHandle UP$MH =
+            
openssl_h.upcallHandle(SSL_psk_find_session_cb_func.Function.class, "apply", 
$DESC);
+
+    public static MemorySegment allocate(SSL_psk_find_session_cb_func.Function 
fi, Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, 
scope);
+    }
+
+    private static final MethodHandle DOWN$MH = 
Linker.nativeLinker().downcallHandle($DESC);
+
+    public static int invoke(MemorySegment funcPtr, MemorySegment ssl, 
MemorySegment identity, long identityLength,
+            MemorySegment session) {
+        try {
+            return (int) DOWN$MH.invokeExact(funcPtr, ssl, identity, 
identityLength, session);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+}
diff --git a/java/org/apache/tomcat/util/openssl/SSL_psk_server_cb_func.java 
b/java/org/apache/tomcat/util/openssl/SSL_psk_server_cb_func.java
new file mode 100644
index 0000000000..a7eaf9585d
--- /dev/null
+++ b/java/org/apache/tomcat/util/openssl/SSL_psk_server_cb_func.java
@@ -0,0 +1,63 @@
+/*
+ * 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.foreign.Arena;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.Linker;
+import java.lang.foreign.MemorySegment;
+import java.lang.invoke.MethodHandle;
+
+/**
+ * {@snippet lang = c : * SSL_psk_server_cb_func cb
+ * }
+ */
+@SuppressWarnings("javadoc")
+public class SSL_psk_server_cb_func {
+
+    public interface Function {
+        int apply(MemorySegment ssl, MemorySegment identity, MemorySegment 
psk, int maxPskLength);
+    }
+
+    private static final FunctionDescriptor $DESC = 
FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER,
+            openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT);
+
+    public static FunctionDescriptor descriptor() {
+        return $DESC;
+    }
+
+    private static final MethodHandle UP$MH =
+            openssl_h.upcallHandle(SSL_psk_server_cb_func.Function.class, 
"apply", $DESC);
+
+    public static MemorySegment allocate(SSL_psk_server_cb_func.Function fi, 
Arena scope) {
+        return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, 
scope);
+    }
+
+    private static final MethodHandle DOWN$MH = 
Linker.nativeLinker().downcallHandle($DESC);
+
+    public static int invoke(MemorySegment funcPtr, MemorySegment ssl, 
MemorySegment identity, MemorySegment psk,
+            int maxPskLength) {
+        try {
+            return (int) DOWN$MH.invokeExact(funcPtr, ssl, identity, psk, 
maxPskLength);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+}
diff --git a/java/org/apache/tomcat/util/openssl/openssl_h.java 
b/java/org/apache/tomcat/util/openssl/openssl_h.java
index 518bd7fb58..41bc06b18c 100644
--- a/java/org/apache/tomcat/util/openssl/openssl_h.java
+++ b/java/org/apache/tomcat/util/openssl/openssl_h.java
@@ -5373,6 +5373,57 @@ public class openssl_h {
         }
     }
 
+    private static class SSL_CIPHER_get_version {
+        public static final FunctionDescriptor DESC = 
FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER);
+
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_CIPHER_get_version");
+
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    /**
+     * Function descriptor for:
+     * {@snippet lang = c : * const char *SSL_CIPHER_get_version(const 
SSL_CIPHER *c)
+     * }
+     */
+    public static FunctionDescriptor SSL_CIPHER_get_version$descriptor() {
+        return SSL_CIPHER_get_version.DESC;
+    }
+
+    /**
+     * Downcall method handle for:
+     * {@snippet lang = c : * const char *SSL_CIPHER_get_version(const 
SSL_CIPHER *c)
+     * }
+     */
+    public static MethodHandle SSL_CIPHER_get_version$handle() {
+        return SSL_CIPHER_get_version.HANDLE;
+    }
+
+    /**
+     * Address for:
+     * {@snippet lang = c : * const char *SSL_CIPHER_get_version(const 
SSL_CIPHER *c)
+     * }
+     */
+    public static MemorySegment SSL_CIPHER_get_version$address() {
+        return SSL_CIPHER_get_version.ADDR;
+    }
+
+    /**
+     * {@snippet lang = c : * const char *SSL_CIPHER_get_version(const 
SSL_CIPHER *c)
+     * }
+     */
+    public static MemorySegment SSL_CIPHER_get_version(MemorySegment c) {
+        var mh$ = SSL_CIPHER_get_version.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_CIPHER_get_version", c);
+            }
+            return (MemorySegment) mh$.invokeExact(c);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
     private static class SSL_CIPHER_get_kx_nid {
         public static final FunctionDescriptor DESC = 
FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER);
 
@@ -10213,5 +10264,154 @@ public class openssl_h {
     public static long SSL_OP_ALL() {
         return SSL_OP_ALL;
     }
-}
 
+    private static class SSL_CIPHER_find {
+        public static final FunctionDescriptor DESC =
+                FunctionDescriptor.of(openssl_h.C_POINTER, 
openssl_h.C_POINTER, openssl_h.C_POINTER);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_CIPHER_find");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static MemorySegment SSL_CIPHER_find(MemorySegment ssl, 
MemorySegment ptr) {
+        var mh$ = SSL_CIPHER_find.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_CIPHER_find", ssl, ptr);
+            }
+            return (MemorySegment) mh$.invokeExact(ssl, ptr);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_CTX_set_psk_server_callback {
+        public static final FunctionDescriptor DESC =
+                FunctionDescriptor.ofVoid(openssl_h.C_POINTER, 
openssl_h.C_POINTER);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_CTX_set_psk_server_callback");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static void SSL_CTX_set_psk_server_callback(MemorySegment ctx, 
MemorySegment callback) {
+        var mh$ = SSL_CTX_set_psk_server_callback.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_CTX_set_psk_server_callback", ctx, 
callback);
+            }
+            mh$.invokeExact(ctx, callback);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_CTX_set_psk_find_session_callback {
+        public static final FunctionDescriptor DESC =
+                FunctionDescriptor.ofVoid(openssl_h.C_POINTER, 
openssl_h.C_POINTER);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_CTX_set_psk_find_session_callback");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static void SSL_CTX_set_psk_find_session_callback(MemorySegment 
ctx, MemorySegment callback) {
+        var mh$ = SSL_CTX_set_psk_find_session_callback.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_CTX_set_psk_find_session_callback", ctx, 
callback);
+            }
+            mh$.invokeExact(ctx, callback);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_SESSION_new {
+        public static final FunctionDescriptor DESC = 
FunctionDescriptor.of(openssl_h.C_POINTER);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_SESSION_new");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static MemorySegment SSL_SESSION_new() {
+        var mh$ = SSL_SESSION_new.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_SESSION_new");
+            }
+            return (MemorySegment) mh$.invokeExact();
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_SESSION_free {
+        public static final FunctionDescriptor DESC = 
FunctionDescriptor.ofVoid(openssl_h.C_POINTER);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_SESSION_free");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static void SSL_SESSION_free(MemorySegment session) {
+        var mh$ = SSL_SESSION_free.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_SESSION_free", session);
+            }
+            mh$.invokeExact(session);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_SESSION_set1_master_key {
+        public static final FunctionDescriptor DESC = 
FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER,
+                openssl_h.C_POINTER, openssl_h.C_LONG);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_SESSION_set1_master_key");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static int SSL_SESSION_set1_master_key(MemorySegment session, 
MemorySegment key, long keyLength) {
+        var mh$ = SSL_SESSION_set1_master_key.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_SESSION_set1_master_key", session, key, 
keyLength);
+            }
+            return (int) mh$.invokeExact(session, key, keyLength);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_SESSION_set_cipher {
+        public static final FunctionDescriptor DESC =
+                FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, 
openssl_h.C_POINTER);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_SESSION_set_cipher");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static int SSL_SESSION_set_cipher(MemorySegment session, 
MemorySegment cipher) {
+        var mh$ = SSL_SESSION_set_cipher.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_SESSION_set_cipher", session, cipher);
+            }
+            return (int) mh$.invokeExact(session, cipher);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+
+    private static class SSL_SESSION_set_protocol_version {
+        public static final FunctionDescriptor DESC =
+                FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, 
openssl_h.C_INT);
+        public static final MemorySegment ADDR = 
openssl_h.findOrThrow("SSL_SESSION_set_protocol_version");
+        public static final MethodHandle HANDLE = 
Linker.nativeLinker().downcallHandle(ADDR, DESC);
+    }
+
+    public static int SSL_SESSION_set_protocol_version(MemorySegment session, 
int version) {
+        var mh$ = SSL_SESSION_set_protocol_version.HANDLE;
+        try {
+            if (TRACE_DOWNCALLS) {
+                traceDowncall("SSL_SESSION_set_protocol_version", session, 
version);
+            }
+            return (int) mh$.invokeExact(session, version);
+        } catch (Throwable ex$) {
+            throw new AssertionError("should not reach here", ex$);
+        }
+    }
+}
diff --git a/res/openssl/openssl-tomcat.conf b/res/openssl/openssl-tomcat.conf
index e37bade4ef..ce3b0f853a 100644
--- a/res/openssl/openssl-tomcat.conf
+++ b/res/openssl/openssl-tomcat.conf
@@ -166,10 +166,14 @@
 
 #### Extracted from: /usr/include/openssl/ssl.h
 
+--include-typedef SSL_psk_find_session_cb_func
+--include-typedef SSL_psk_server_cb_func
 --include-function OPENSSL_init_ssl                              # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CIPHER_get_auth_nid                       # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_CIPHER_find                               # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CIPHER_get_kx_nid                         # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CIPHER_get_name                           # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_CIPHER_get_version                        # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CONF_CTX_finish                           # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CONF_CTX_free                             # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CONF_CTX_new                              # header: 
/usr/include/openssl/ssl.h
@@ -197,6 +201,8 @@
 --include-function SSL_CTX_set_default_passwd_cb                 # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CTX_set_default_verify_paths              # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CTX_set_options                           # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_CTX_set_psk_find_session_callback         # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_CTX_set_psk_server_callback               # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CTX_set_session_id_context                # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CTX_set_timeout                           # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_CTX_set_tmp_dh_callback                   # deprecated 
header: /usr/include/openssl/ssl.h
@@ -207,6 +213,11 @@
 --include-function SSL_CTX_use_PrivateKey                        # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_SESSION_get_id                            # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_SESSION_get_time                          # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_SESSION_free                              # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_SESSION_new                               # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_SESSION_set1_master_key                   # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_SESSION_set_cipher                        # header: 
/usr/include/openssl/ssl.h
+--include-function SSL_SESSION_set_protocol_version              # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_add_file_cert_subjects_to_stack           # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_do_handshake                              # header: 
/usr/include/openssl/ssl.h
 --include-function SSL_free                                      # header: 
/usr/include/openssl/ssl.h
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index d7ff714eb2..0a5343b1dd 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -137,6 +137,10 @@
         Add support for configuring TLS pre-shared keys under an
         <code>SSLHostConfig</code>. (markt)
       </add>
+      <add>
+        Add TLS pre-shared key support to the OpenSSL FFM implementation.
+        (markt)
+      </add>
       <add>
         Add the Jakarta EE 12 XML schemas. (markt)
       </add>
diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml
index 3c7512b4aa..434d35aadc 100644
--- a/webapps/docs/config/http.xml
+++ b/webapps/docs/config/http.xml
@@ -1254,9 +1254,8 @@
 
   <p>Each <strong>SSLHostConfig</strong> must in turn define at least one
   <strong>Certificate</strong> or <strong>PreSharedKey</strong>. A 
configuration
-  with no <strong>Certificate</strong> requires the Tomcat Native OpenSSL
-  implementation. The types of the <strong>Certificate</strong>s must be
-  unique.</p>
+  with no <strong>Certificate</strong> requires an OpenSSL-based 
implementation.
+  The types of the <strong>Certificate</strong>s must be unique.</p>
 
   <p>In addition to the standard TLS related request attributes defined in
   section 3.10 of the Servlet specification, Tomcat supports a number of


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to