Skip to content

Commit 8254723

Browse files
committed
First draft of more correct check of tls version
1 parent 3434f76 commit 8254723

File tree

8 files changed

+70
-7
lines changed

8 files changed

+70
-7
lines changed

src/java.base/share/classes/sun/security/ssl/ClientHello.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,11 @@ public void consume(ConnectionContext context,
11441144
"The ClientHello.legacy_version field is not TLS 1.2");
11451145
}
11461146

1147+
if (shc.conContext.inputRecord.t13keyChangeHsExceedsRecordBoundary()) {
1148+
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
1149+
"CLIENT_HELLO messages must align with a record boundary");
1150+
}
1151+
11471152
// The client may send a dummy change_cipher_spec record
11481153
// immediately after the first ClientHello.
11491154
shc.conContext.consumers.putIfAbsent(

src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ Plaintext[] decode(ByteBuffer packet) throws SSLProtocolException {
170170

171171
// Buffer next epoch message if necessary.
172172
if (this.readEpoch < recordEpoch) {
173-
// Discard the record younger than the current epcoh if:
173+
// Discard the record younger than the current epoch if:
174174
// 1. it is not a handshake message, or
175175
// 3. it is not of next epoch.
176176
if ((contentType != ContentType.HANDSHAKE.id &&
@@ -310,6 +310,12 @@ int bytesInCompletePacket(
310310
return bytesInCompletePacket(srcs[srcsOffset]);
311311
}
312312

313+
@Override
314+
public boolean t13keyChangeHsExceedsRecordBoundary() {
315+
// DTLS 1.3 is not supported
316+
return false;
317+
}
318+
313319
private int bytesInCompletePacket(ByteBuffer packet) throws SSLException {
314320

315321
// DTLS length field is in bytes 11/12

src/java.base/share/classes/sun/security/ssl/Finished.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,11 @@ private void onConsumeFinished(ClientHandshakeContext chc,
935935
"Consuming server Finished handshake message", fm);
936936
}
937937

938+
if (chc.conContext.inputRecord.t13keyChangeHsExceedsRecordBoundary()) {
939+
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
940+
"FINISHED messages must align with a record boundary");
941+
}
942+
938943
// Save client verify data for secure renegotiation.
939944
if (chc.conContext.secureRenegotiation) {
940945
chc.conContext.serverVerifyData = fm.verifyData;
@@ -1078,6 +1083,11 @@ private void onConsumeFinished(ServerHandshakeContext shc,
10781083
"Consuming client Finished handshake message", fm);
10791084
}
10801085

1086+
if (shc.conContext.inputRecord.t13keyChangeHsExceedsRecordBoundary()) {
1087+
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
1088+
"FINISHED messages must align with a record boundary");
1089+
}
1090+
10811091
if (shc.conContext.secureRenegotiation) {
10821092
shc.conContext.clientVerifyData = fm.verifyData;
10831093
}

src/java.base/share/classes/sun/security/ssl/InputRecord.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ int bytesInCompletePacket() throws IOException {
150150
throw new UnsupportedOperationException();
151151
}
152152

153+
public abstract boolean t13keyChangeHsExceedsRecordBoundary();
154+
153155
// apply to SSLSocket only
154156
void setReceiverStream(InputStream inputStream) {
155157
throw new UnsupportedOperationException();

src/java.base/share/classes/sun/security/ssl/KeyUpdate.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ public void consume(ConnectionContext context,
196196
"Consuming KeyUpdate post-handshake message", km);
197197
}
198198

199+
if (hc.negotiatedProtocol.useTLS13PlusSpec() && hc.conContext.inputRecord.t13keyChangeHsExceedsRecordBoundary()) {
200+
throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
201+
"KEYUPDATE messages must align with a record boundary");
202+
}
203+
199204
// Update read key and IV.
200205
SSLTrafficKeyDerivation kdg =
201206
SSLTrafficKeyDerivation.valueOf(hc.conContext.protocolVersion);

src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ final class SSLEngineInputRecord extends InputRecord implements SSLRecord {
4444
// Cache for incomplete handshake messages.
4545
private ByteBuffer handshakeBuffer = null;
4646

47+
// mark for possible TLS13 RFC violation, if messages preceding key change do not align with record bounds
48+
private boolean t13keyChangeHsExceedsRecordBoundary = false;
49+
4750
SSLEngineInputRecord(HandshakeHash handshakeHash) {
4851
super(handshakeHash, SSLReadCipher.nullTlsReadCipher());
4952
}
@@ -64,6 +67,11 @@ int bytesInCompletePacket(
6467
return bytesInCompletePacket(srcs[srcsOffset]);
6568
}
6669

70+
@Override
71+
public boolean t13keyChangeHsExceedsRecordBoundary() {
72+
return t13keyChangeHsExceedsRecordBoundary;
73+
}
74+
6775
private int bytesInCompletePacket(ByteBuffer packet) throws SSLException {
6876
/*
6977
* SSLv2 length field is in bytes 0/1
@@ -338,6 +346,20 @@ private Plaintext[] decodeInputRecord(ByteBuffer packet)
338346
handshakeHash.receive(handshakeFrag);
339347
}
340348

349+
// From RFC 8446:
350+
// "Implementations MUST verify that all messages immediately preceding a key change
351+
// align with a record boundary; if not, then they MUST terminate the
352+
// connection with an "unexpected_message" alert. Because the
353+
// ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate
354+
// messages can immediately precede a key change, implementations
355+
// MUST send these messages in alignment with a record boundary."
356+
//
357+
// this check must be done here, as the handshakeBuffer is not accessible to the outer scope,
358+
// therefore there is no way to check whether the handshake message was aligned with the boundary
359+
if (nextPos < fragLim && SSLHandshake.precedesKeyChange(handshakeType)) {
360+
t13keyChangeHsExceedsRecordBoundary = true;
361+
}
362+
341363
plaintexts.add(
342364
new Plaintext(contentType, majorVersion, minorVersion,
343365
-1, -1L, handshakeFrag.slice())

src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ final class SSLSocketInputRecord extends InputRecord implements SSLRecord {
5959
// Cache for incomplete handshake messages.
6060
private ByteBuffer handshakeBuffer = null;
6161

62+
// mark for possible TLS13 RFC violation, if messages preceding key change do not align with record bounds
63+
private boolean t13keyChangeHsExceedsRecordBoundary = false;
64+
6265
SSLSocketInputRecord(HandshakeHash handshakeHash) {
6366
super(handshakeHash, SSLReadCipher.nullTlsReadCipher());
6467
}
@@ -193,6 +196,11 @@ Plaintext[] decode(ByteBuffer[] srcs, int srcsOffset,
193196
return plaintext;
194197
}
195198

199+
@Override
200+
public boolean t13keyChangeHsExceedsRecordBoundary() {
201+
return t13keyChangeHsExceedsRecordBoundary;
202+
}
203+
196204
@Override
197205
void setReceiverStream(InputStream inputStream) {
198206
this.is = inputStream;
@@ -372,12 +380,11 @@ private Plaintext[] decodeInputRecord() throws IOException, BadPaddingException
372380
// ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate
373381
// messages can immediately precede a key change, implementations
374382
// MUST send these messages in alignment with a record boundary."
375-
if (helloVersion.useTLS13PlusSpec() &&
376-
nextPos < fragLim && SSLHandshake.precedesKeyChange(handshakeType)) {
377-
throw new SSLProtocolException(
378-
"The handshake message of type " + SSLHandshake.nameOf(handshakeType) +
379-
" must end on a Record boundary."
380-
);
383+
//
384+
// this check must be done here, as the handshakeBuffer is not accessible to the outer scope,
385+
// therefore there is no way to check whether the handshake message was aligned with the boundary
386+
if (nextPos < fragLim && SSLHandshake.precedesKeyChange(handshakeType)) {
387+
t13keyChangeHsExceedsRecordBoundary = true;
381388
}
382389

383390
handshakeFrag.position(nextPos);

src/java.base/share/classes/sun/security/ssl/ServerHello.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,12 @@ public void consume(ConnectionContext context,
12391239
"The ServerHello.legacy_version field is not TLS 1.2");
12401240
}
12411241

1242+
if (chc.conContext.inputRecord.t13keyChangeHsExceedsRecordBoundary()) {
1243+
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
1244+
"CLIENT_HELLO messages must align with a record boundary");
1245+
}
1246+
1247+
12421248
chc.negotiatedCipherSuite = serverHello.cipherSuite;
12431249
chc.handshakeHash.determine(
12441250
chc.negotiatedProtocol, chc.negotiatedCipherSuite);

0 commit comments

Comments
 (0)