8268205: Enhance DTLS client handshake
Reviewed-by: jnimeh, ahgross, rhalade
This commit is contained in:
parent
365a2d428c
commit
c714707eac
@ -567,6 +567,9 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
|
|
||||||
HashMap<Byte, List<HoleDescriptor>> holesMap;
|
HashMap<Byte, List<HoleDescriptor>> holesMap;
|
||||||
|
|
||||||
|
// A map used to check duplicated handshake messages.
|
||||||
|
HashMap<Byte, Integer> messageSeqMap;
|
||||||
|
|
||||||
HandshakeFlight() {
|
HandshakeFlight() {
|
||||||
this.handshakeType = HF_UNKNOWN;
|
this.handshakeType = HF_UNKNOWN;
|
||||||
this.flightEpoch = 0;
|
this.flightEpoch = 0;
|
||||||
@ -577,6 +580,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
this.maxRecordSeq = -1;
|
this.maxRecordSeq = -1;
|
||||||
|
|
||||||
this.holesMap = new HashMap<>(5);
|
this.holesMap = new HashMap<>(5);
|
||||||
|
this.messageSeqMap = new HashMap<>(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isRetransmitOf(HandshakeFlight hs) {
|
boolean isRetransmitOf(HandshakeFlight hs) {
|
||||||
@ -598,6 +602,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
hf.maxRecordSeq = this.maxRecordSeq;
|
hf.maxRecordSeq = this.maxRecordSeq;
|
||||||
|
|
||||||
hf.holesMap = new HashMap<>(this.holesMap);
|
hf.holesMap = new HashMap<>(this.holesMap);
|
||||||
|
hf.messageSeqMap = new HashMap<>(this.messageSeqMap);
|
||||||
|
|
||||||
return hf;
|
return hf;
|
||||||
}
|
}
|
||||||
@ -640,7 +645,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Queue up a handshake message.
|
// Queue up a handshake message.
|
||||||
void queueUpHandshake(HandshakeFragment hsf) {
|
void queueUpHandshake(HandshakeFragment hsf) throws SSLProtocolException {
|
||||||
if (!isDesirable(hsf)) {
|
if (!isDesirable(hsf)) {
|
||||||
// Not a dedired record, discard it.
|
// Not a dedired record, discard it.
|
||||||
return;
|
return;
|
||||||
@ -707,6 +712,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
holes.add(new HoleDescriptor(0, hsf.messageLength));
|
holes.add(new HoleDescriptor(0, hsf.messageLength));
|
||||||
}
|
}
|
||||||
handshakeFlight.holesMap.put(hsf.handshakeType, holes);
|
handshakeFlight.holesMap.put(hsf.handshakeType, holes);
|
||||||
|
handshakeFlight.messageSeqMap.put(hsf.handshakeType, hsf.messageSeq);
|
||||||
} else if (holes.isEmpty()) {
|
} else if (holes.isEmpty()) {
|
||||||
// Have got the full handshake message. This record may be
|
// Have got the full handshake message. This record may be
|
||||||
// a handshake message retransmission. Discard this record.
|
// a handshake message retransmission. Discard this record.
|
||||||
@ -778,7 +784,8 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Queue up a ChangeCipherSpec message
|
// Queue up a ChangeCipherSpec message
|
||||||
void queueUpChangeCipherSpec(RecordFragment rf) {
|
void queueUpChangeCipherSpec(RecordFragment rf)
|
||||||
|
throws SSLProtocolException {
|
||||||
if (!isDesirable(rf)) {
|
if (!isDesirable(rf)) {
|
||||||
// Not a dedired record, discard it.
|
// Not a dedired record, discard it.
|
||||||
return;
|
return;
|
||||||
@ -807,7 +814,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
// Queue up a ciphertext message.
|
// Queue up a ciphertext message.
|
||||||
//
|
//
|
||||||
// Note: not yet be able to decrypt the message.
|
// Note: not yet be able to decrypt the message.
|
||||||
void queueUpFragment(RecordFragment rf) {
|
void queueUpFragment(RecordFragment rf) throws SSLProtocolException {
|
||||||
if (!isDesirable(rf)) {
|
if (!isDesirable(rf)) {
|
||||||
// Not a dedired record, discard it.
|
// Not a dedired record, discard it.
|
||||||
return;
|
return;
|
||||||
@ -895,7 +902,7 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
// Is a desired record?
|
// Is a desired record?
|
||||||
//
|
//
|
||||||
// Check for retransmission and lost records.
|
// 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.
|
// Discard records old than the previous epoch.
|
||||||
//
|
//
|
||||||
@ -970,6 +977,25 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,6 +1112,9 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord {
|
|||||||
// cleanup holes map
|
// cleanup holes map
|
||||||
handshakeFlight.holesMap.clear();
|
handshakeFlight.holesMap.clear();
|
||||||
|
|
||||||
|
// cleanup handshake message sequence numbers map
|
||||||
|
handshakeFlight.messageSeqMap.clear();
|
||||||
|
|
||||||
// Ready to accept new input record.
|
// Ready to accept new input record.
|
||||||
flightIsReady = false;
|
flightIsReady = false;
|
||||||
needToCheckFlight = false;
|
needToCheckFlight = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user