Due to our need to use certain TLS cipher suites which are not supported by the SunJSSE provider by Oracle, we have created an own implementation of a JSSE provider. In Tomcat 7, we are able to use it easily by registering our provider in the JRE and configuring <Connector port="..." protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" keystoreFile="..." keystorePass="..." sslProtocol="TLSPSK" ciphers="TLS_RSA_PSK_WITH_AES_256_GCM_SHA384" clientAuth="false" /> where "TLSPSK" is the name of our SSLContext implementation. However we are unable to use it in Tomcat 9 (or 8.5). Startup of Tomcat 9 (with same connector configuration) results in following exception: Caused by: java.lang.IllegalArgumentException: Keine der spezifizierten [ciphers] wird von der SSL Engine unterstützt: [[TLS_RSA_PSK_WITH_AES_256_GCM_SHA384]] at org.apache.tomcat.util.net.SSLUtilBase.getEnabled(SSLUtilBase.java:151) at org.apache.tomcat.util.net.SSLUtilBase.<init>(SSLUtilBase.java:125) at org.apache.tomcat.util.net.jsse.JSSEUtil.<init>(JSSEUtil.java:113) at org.apache.tomcat.util.net.jsse.JSSEUtil.<init>(JSSEUtil.java:108) at org.apache.tomcat.util.net.jsse.JSSEImplementation.getSSLUtil(JSSEImplementation.java:50) at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:88) at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71) at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:218) at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1124) at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1137) at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:574) at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74) at org.apache.catalina.connector.Connector.initInternal(Connector.java:980) meaning given ciphers not supported. An investigation showed us that SSLUtilBase.getEnabled always produces an empty list with operations enabled.addAll(configured); enabled.retainAll(implemented); where "configured" holds exactly the ciphers we give in the config, and "implemented" holds a number of ciphers but not ours. Tracking down where "implemented" comes from led us to JSSEUtil static initializer SSLContext context; try { context = new JSSESSLContext(Constants.SSL_PROTO_TLS); ... and later String[] implementedCipherSuiteArray = context.getSupportedSSLParameters().getCipherSuites(); So, the "implemented" ciphers are always taken from the SSLContext one receives from SSLContext.getInstance("TLS") which is usually the SunJSSE implementation, essentially locking out all other ciphers. A workaround by naming our SSLContext "TLS" and assigning it higher priority than SunJSSE, so JSSEUtil would then always use ours, is not feasible as we also need SunJSSE (on other connectors).
Fixed in: - master for 9.0.23 onwards - 8.5.x for 8.5.44 onwards I have refactored the initialisation so it uses the sslProtocol value from the SSLHostContext.