While working on customer issue recently, I came across following scenario where there was a problem in connecting to the SQL Server from the IBM Java application (JDK 1.7) if we enable only TLS 1.2 protocol on both SQL and Application servers.

Let's say we have a simple java program build using the IBM JDK 1.7(pwa6470sr9fp50-20160720_02(SR9fp50)) to test the connectivity to the SQL Server by only enabling the TLS 1.2 protocol on both Application and SQL Server.

Java version as shown below.

Java Version

If we do a test connection to the SQL Server from the application server using the simple java program from the command prompt, it fails with the below error stack.

com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "SQL Server did not return a response. The connection has been closed. ClientConnectionId:7436e46e-1210-4052-92d2-0f2688b1e461".

at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1669)

at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1668) at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(SQLServerConnection.java:1325)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.login(SQLServerConnection.java:993)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(SQLServerConnection.java:829)

at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(SQLServerDriver.java:1012)

at DriverShim.connect(DriverShim.java:14)

at java.sql.DriverManager.getConnection(DriverManager.java:583)

at java.sql.DriverManager.getConnection(DriverManager.java:227)

at DBConnTest.main(DBConnTest.java:136)

Caused by: java.io.IOException: SQL Server did not return a response. The connection has been closed. ClientConnectionId:7436e46e-1210-4052-92d2-0f2688b1e461

at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.ensureSSLPayload(IOBuffer.java:651)

at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.readInternal(IOBuffer.java:708)

at com.microsoft.sqlserver.jdbc.TDSChannel$SSLHandshakeInputStream.read(IOBuffer.java:700)

at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.readInternal(IOBuffer.java:895)

at com.microsoft.sqlserver.jdbc.TDSChannel$ProxyInputStream.read(IOBuffer.java:883)

at com.ibm.jsse2.a.a(a.java:227)

at com.ibm.jsse2.a.a(a.java:269)

at com.ibm.jsse2.qc.a(qc.java:459)

at com.ibm.jsse2.qc.h(qc.java:275)

at com.ibm.jsse2.qc.a(qc.java:541)

at com.ibm.jsse2.qc.startHandshake(qc.java:89)

at com.microsoft.sqlserver.jdbc.TDSChannel.enableSSL(IOBuffer.java:1618)

... 8 more

All done

Note: In the above case we are using the IBM JDK 1.7 with Microsoft JDBC driver 4.1 and you will experience the same issue for latest JDBC drivers (4.2,6.0,6.2) as well.

In the network trace analysis, we see that client initiates TLS handshake with a TLS1.0 Client Hello as shown below screen shot.

Network Trace Sample

Cause:

IBM JDK 1.7 supports the TLS 1.2 but still by default it uses the TLS 1.0 and for that reason we see that client application initiates TLS 3-way handshake with a TLS 1.0 client hello and connections are failing.

The System property com.ibm.jsse2.overrideDefaultTLS is used to match the behavior of SSLContext.getInstance("TLS") in the IBM SDK.

com.ibm.jsse2.overrideDefaultTLS =[true|false]

To match the behavior of SSLContext.getInstance("TLS"), set this property to true. The default value is false.

Support

Solution:

We need to set the property com.ibm.jsse2.overrideDefaultTLS to True to enable the TLS 1.1 and TLS 1.2 in the IBM JDK.

To make a successful connection to the SQL Server from the application over TLS 1.2, we need to set the property com.ibm.jsse2.overrideDefaultTLS =true and pass it during run time as shown below.