ADDITIONAL SYSTEM INFORMATION :
Linux 64-bit. Originally discovered with OpenJDK 11.0.2, but I can reproduce it with the tip of http://hg.openjdk.java.net/jdk-updates/jdk12u/
A DESCRIPTION OF THE PROBLEM :
The TLSv1.3 spec has this to say about the allowed length of TLSInnerPlaintext:
The presence of padding does not change the overall record size
limitations - the full encoded TLSInnerPlaintext MUST NOT exceed 2^14
+ 1 octets. If the maximum fragment length is reduced, as for
example by the max_fragment_length extension from [RFC6066], then the
reduced limit applies to the full plaintext, including the content
type and padding.
However, t13Encrypt in src/java.base/share/classes/sun/security/ssl/OutputRecord.java will always append 16 padding bytes to the fragment, without taking into account its original size:
private static final class T13PaddingHolder {
private static final byte[] zeros = new byte[16];
}
private long t13Encrypt(
SSLWriteCipher encCipher, byte contentType, int headerSize) {
if (!encCipher.isNullCipher()) {
// inner plaintext
write(contentType);
write(T13PaddingHolder.zeros, 0, T13PaddingHolder.zeros.length);
}
...
This causes trouble with TLSv1.3 servers because we set Record.maxDataSize to 2^14, and so the added 1 + 16 bytes may cause the resulting TLSInnerPlaintext to go over the length limit.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run Test.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The test TLSv1.3 server page at https://tls13.crypto.mozilla.org/ should be printed to console.
ACTUAL -
https://tls13.crypto.mozilla.org/ returns a "record_overflow" error.
---------- BEGIN SOURCE ----------
import javax.net.ssl.HttpsURLConnection;
import java.net.URL;
import java.io.*;
import java.nio.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class Test {
public static void main(String[] args) throws Exception {
StringBuilder data = new StringBuilder();
data.append("----abc\r\n")
.append("Content-Disposition: form-data; name=\"json_file\"; filename=\"test.json\"\r\n")
.append("Content-Type: application/octet-stream\r\n")
.append("\r\n");
for (int i = 0; i < 325717; i++)
data.append("a");
data.append("----abc--");
URL url = new URL("https://tls13.crypto.mozilla.org/");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=--abc");
OutputStreamWriter osw = new OutputStreamWriter(connection.getOutputStream());
osw.write(data.toString());
osw.flush();
osw.close();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Disabling TLSv1.3 support by setting jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"