1

I know that a particular TLS version can be enforced with a global property, like so:

  • with code: System.setProperty("jdk.tls.client.protocols", "TLSv1.2");
  • or from the command line: java -Djdk.tls.client.protocols=TLSv1.2 ...

Is there a way to do that in a more refined, on SSL per-context/engine bases? For example, what if I want to prevent usage of TLSv1.3 in a particular context, and only allow protocols up to TLSv1.2?

I thought this was the way:

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
...
var sslContext = SSLContext.getInstance("TLSv1.2");
var sslEngine = sslContext.createSSLEngine();
...

but my tests still show TLSv1.3 creeping in the SSL handshake phase. Indeed, the Java 16+ java doc explains that the "protocol" parameter guarantees provider with support for the requested TLS version, but does not necessarily restrict the provider from going higher:

SSLContext.getProtocol(String protocol);

javadoc:

protocol – the standard name of the requested protocol. See the SSLContext section in the Java Security Standard Algorithm Names Specification for information about standard protocol names.

P.S: I found something closer to what I need answered here: Will SSLContext.getInstance("TLS") supports TLS v1.1 and TLS v1.2 also?

To use TLSv1.2 try to use below code:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);

Assuming the answer is correct(I think it is not), however I do want to initialize my context from specific trust store and key store managers, passing NULLs is not acceptable to me.

Hristo Stoyanov
  • 1,508
  • 3
  • 15
  • 24
  • If you are using the standard provider (SunJSSE), as Oracle and (all?) OpenJDK builds do by default (but you can change) `SSLContext("TLSv1.2")` should indeed support up to 1.2 but not 1.3 _unless changed by the code you omitted_. Look at `sslEngine.getEnabledProtocols()` immediately after creation, and again at the point you begin a connection.. However, 'up to' may be misleading because 8u231+ 11.0.11+ 16+ by default disable 1.0 and 1.1 in a security property, so unless you change or override that 'up to 1.2' is 'only 1.2'. ... – dave_thompson_085 Sep 27 '21 at 21:34
  • ... and yes protocol support is orthogonal to the trustmanager and keymanager, so you can use non-null entries on `SSLContext.init`; the A you link probably just gave that as the simplest example of a solution. – dave_thompson_085 Sep 27 '21 at 21:37
  • @dave_thompson_085 - thanks for taking the time. Not sure I understand. According to the [docs](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/javax/net/ssl/SSLContext.html#getInstance(java.lang.String)) ```sslContext = SSLContext.getInstance("TLSv1.2")``` will provide me a context that supports v1.2mfor sure, **but may also support v1.3**, which is what I see in my tests, but is not what I want? – Hristo Stoyanov Sep 27 '21 at 22:34
  • Just to give you background why I need this: https://github.com/microsoft/mssql-jdbc/issues/1653#issuecomment-927725351 – Hristo Stoyanov Sep 27 '21 at 22:36
  • Remove it from the enabled protocols at the `SSSocket` itself before you use it, or better still in the socket factory if that's possible. @dave_thompson_085 is not correct in asserting it should not support 1.3. It should, and the documentation says so. – user207421 Sep 28 '21 at 00:13
  • Sorry, I should have said 'default enabled on client' (which I guessed from your references to sysprops, but please confirm, _is_ this client?) not 'supported'. JSSE 11+ _supports_ SSL3 to TLS1.3 but different contexts don't default _enable_ all of them, and as I said secprop disables more. Note my comment was specifically for SunJSSE, not the API which allows other providers to be (slightly) different. @user207421: see https://github.com/openjdk/jdk/blob/jdk-16-ga/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java#L665 . Also OP is using engine not socket. – dave_thompson_085 Sep 28 '21 at 04:20
  • 3
    Use `SSLEngine::getEnabledProtocols` to get a list of supported protocols, then remove those you don't like, and use `SSLEngine::setEnabledProtocols` to change the engine to only support the protocols you like. https://docs.oracle.com/en/java/javase/17/docs/api/java.base/javax/net/ssl/SSLEngine.html#setEnabledProtocols(java.lang.String%5B%5D) – daniel Sep 28 '21 at 13:23
  • @daniel you have the right answer. Thanks! – Hristo Stoyanov Oct 12 '21 at 04:12

0 Answers0