Maintenance Notice

The bugs.java.com site will be undergoing maintenance on 15th Dec 2017 21:00 PST to 16th Dec 2017 1:00 AM PST.
JDK-8014618 : Need to strip leading zeros in TlsPremasterSecret of DHKeyAgreement
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Affected Version: 7u17,8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-03-26
  • Updated: 2016-04-29
  • Resolved: 2013-05-31
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availabitlity Release.

To download the current JDK release, click here.
JDK 6 JDK 7 JDK 8
6u115Fixed 7u51Fixed 8 b94Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version  " 1.7.0_17 " 
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) Client VM (build 23.7-b01, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Tested on Windows 7 (Microsoft Windows [Version 6.1.7601]), but occurs in e..g OpenJDK 7 as well.

A DESCRIPTION OF THE PROBLEM :
When performing Diffie-Hellman key agreement for SSL/TLS, the TLS specification (RFC 5246) says that  " Leading bytes of Z that contain all zero bits are stripped before it is used as the pre_master_secret. " 

However, com.sun.crypto.provider.DHKeyAgreement.java does not strip leading zero bytes. This causes approximately 1 out 256 SSL/TLS  handshakes with DH/DHE cipher suites to fail (when the leading byte happens, by chance, to be zero).


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Start a simple JSSE socket server with -Djavax.net.debug=all.

2. Connect to the server with e.g. OpenSSL command line tool, ensuring that DHE cipher suite gets selected (e.g.  " openssl s_client -cipher DHE-RSA-AES128-SHA -connect 192.168.81.1:9999 " ) repeatedly.  Other SSL clients can be used -- this is not an OpenSSL bug (see below).

3. Repeat the connection. After a couple of hundred successful connections, the connection will fail with handshake_failure alert.

4. Examine the JSSE debug logs produced by the server: the failed connection will have a PreMaster secret that begins with zero byte
(while all other connections have non-zero byte here). For example:

SESSION KEYGEN:
PreMaster Secret:
0000: 00 70 C5 7E 91 38 C8 DE   ED 75 3D 76 8A B5 44 69  .p...8...u=v..Di
0010: E7 32 1C EE 80 77 50 C7   A9 51 24 2E E3 15 11 30  .2...wP..Q$....0
0020: 9D F6 9F BC 9D EB 5C 18   F7 A4 19 ED 1A AC 2E 0C  ......\.........
0030: E3 18 C5 11 B1 80 07 7D   B1 C6 70 A8 D7 EB CF DD  ..........p.....
0040: 2D B5 1D BC 01 3E 28 2A   2B 5B 38 8F EB 20 F2 A2  -....>(*+[8.. ..
0050: 00 07 47 F7 87 B8 99 CB   EF B4 13 04 C8 8B 82 FB  ..G.............


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected result is that every connection succeed.
ACTUAL -
Roughly one out of 256 connections fail.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
Java server:

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;

public class TestServer {
    public static void main(String args[]) throws Exception {
SSLServerSocketFactory ssf = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket ss = (SSLServerSocket) ssf.createServerSocket(9999);
System.out.println( " Listening on port 9999 " );
for (String cs : ss.getEnabledCipherSuites()) {
    System.out.println(cs);
}
while (true) {
    SSLSocket s = (SSLSocket) ss.accept();
    System.out.println( " Connected with  " +s.getSession().getCipherSuite());
    s.close();
}
    }
}

Run as as follows:

keytool -storepass  " password "  -keypass  " password "  -genkey -keyalg RSA -keystore test_keystore.jks -dname CN=test
javac TestServer.java
java -Djavax.net.debug=all -Djavax.net.ssl.keyStore=./test_keystore.jks -Djavax.net.ssl.keyStorePassword=password TestServer

OpenSSL client:

set -e
while true; do
  openssl s_client -cipher DHE-RSA-AES128-SHA -connect 127.0.0.1:9999 -quiet -no_ign_eof < /dev/null
done



---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Disable Diffie-Hellman cipher suites.
Comments
Example stacktrace when error is seen (we should always include a stacktrace example for search ability) Java server: javax.net.ssl.SSLHandshakeException: Invalid Padding length: 121 at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:974) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:882) at sun.security.ssl.AppInputStream.read(AppInputStream.java:102) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.BufferedReader.fill(BufferedReader.java:154) at java.io.BufferedReader.readLine(BufferedReader.java:317) at java.io.BufferedReader.readLine(BufferedReader.java:382) at EchoServer.main(EchoServer.java:27) Caused by: javax.crypto.BadPaddingException: Invalid Padding length: 121 at sun.security.ssl.CipherBox.removePadding(CipherBox.java:684) at sun.security.ssl.CipherBox.decrypt(CipherBox.java:423) at sun.security.ssl.InputRecord.decrypt(InputRecord.java:154) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:969) I've just seen JDK-8013059 - I believe that's a duplicate and will close it out.
2013-10-25

com/sun/crypto/provider/TLS/TestLeadingZeroes.java sun/security/pkcs11/tls/TestLeadingZeroesP11.java have passed from B94 - B96
2013-07-01

The submitter has also submitted a patch to the bugzilla instance. OCA has been signed. https://bugs.openjdk.java.net/show_bug.cgi?id=100316
2013-05-15