8268205: Enhance DTLS client handshake

Reviewed-by: jnimeh, ahgross, rhalade
This commit is contained in:
Xue-Lei Andrew Fan 2021-07-08 04:37:39 +00:00 committed by Henry Jen
parent 365a2d428c
commit c714707eac

View File

@ -567,6 +567,9 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
HashMap<Byte, List<HoleDescriptor>> holesMap;
// A map used to check duplicated handshake messages.
HashMap<Byte, Integer> messageSeqMap;
HandshakeFlight() {
this.handshakeType = HF_UNKNOWN;
this.flightEpoch = 0;
@ -577,6 +580,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
this.maxRecordSeq = -1;
this.holesMap = new HashMap<>(5);
this.messageSeqMap = new HashMap<>(5);
}
boolean isRetransmitOf(HandshakeFlight hs) {
@ -598,6 +602,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
hf.maxRecordSeq = this.maxRecordSeq;
hf.holesMap = new HashMap<>(this.holesMap);
hf.messageSeqMap = new HashMap<>(this.messageSeqMap);
return hf;
}
@ -640,7 +645,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
// Queue up a handshake message.
void queueUpHandshake(HandshakeFragment hsf) {
void queueUpHandshake(HandshakeFragment hsf) throws SSLProtocolException {
if (!isDesirable(hsf)) {
// Not a dedired record, discard it.
return;
@ -707,6 +712,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
holes.add(new HoleDescriptor(0, hsf.messageLength));
}
handshakeFlight.holesMap.put(hsf.handshakeType, holes);
handshakeFlight.messageSeqMap.put(hsf.handshakeType, hsf.messageSeq);
} else if (holes.isEmpty()) {
// Have got the full handshake message. This record may be
// a handshake message retransmission. Discard this record.
@ -778,7 +784,8 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
}
// Queue up a ChangeCipherSpec message
void queueUpChangeCipherSpec(RecordFragment rf) {
void queueUpChangeCipherSpec(RecordFragment rf)
throws SSLProtocolException {
if (!isDesirable(rf)) {
// Not a dedired record, discard it.
return;
@ -807,7 +814,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Queue up a ciphertext message.
//
// Note: not yet be able to decrypt the message.
void queueUpFragment(RecordFragment rf) {
void queueUpFragment(RecordFragment rf) throws SSLProtocolException {
if (!isDesirable(rf)) {
// Not a dedired record, discard it.
return;
@ -895,7 +902,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// Is a desired record?
//
// Check for retransmission and lost records.
private boolean isDesirable(RecordFragment rf) {
private boolean isDesirable(RecordFragment rf) throws SSLProtocolException {
//
// Discard records old than the previous epoch.
//
@ -970,6 +977,25 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
return false;
}
// Unexpected duplicated handshake messages.
if (rf.recordEpoch == handshakeEpoch &&
// For handshake messages only.
rf instanceof HandshakeFragment hsf &&
// Check on the received handshake messages.
handshakeFlight.holesMap.containsKey(hsf.handshakeType)) {
Integer cachedMsgSeq = handshakeFlight.messageSeqMap.get(
hsf.handshakeType);
if (cachedMsgSeq != null && cachedMsgSeq != hsf.messageSeq) {
// Handshake messages of the same type but with different
// message sequence numbers are not allowed.
throw new SSLProtocolException(
"Two message sequence numbers are used for the "
+ "same handshake message ("
+ SSLHandshake.nameOf(hsf.handshakeType)
+ ")");
}
}
return true;
}
@ -1086,6 +1112,9 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
// cleanup holes map
handshakeFlight.holesMap.clear();
// cleanup handshake message sequence numbers map
handshakeFlight.messageSeqMap.clear();
// Ready to accept new input record.
flightIsReady = false;
needToCheckFlight = false;