Skip to content

Commit 94e1d75

Browse files
author
Anthony Scarpino
committed
8211018: Session Resumption without Server-Side State
Reviewed-by: xuelei, jnimeh, jjiang
1 parent 9597144 commit 94e1d75

21 files changed

+1621
-151
lines changed

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

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import java.util.LinkedList;
3636
import java.util.List;
3737
import java.util.Locale;
38-
import java.util.Objects;
3938
import javax.net.ssl.SSLException;
4039
import javax.net.ssl.SSLHandshakeException;
4140
import javax.net.ssl.SSLPeerUnverifiedException;
@@ -969,11 +968,24 @@ public void consume(ConnectionContext context,
969968
}
970969
}
971970

972-
// Is it an abbreviated handshake?
973-
if (clientHello.sessionId.length() != 0) {
974-
SSLSessionImpl previous = ((SSLSessionContextImpl)shc.sslContext
975-
.engineGetServerSessionContext())
976-
.get(clientHello.sessionId.getId());
971+
// Consume a Session Ticket Extension if it exists
972+
SSLExtension[] ext = new SSLExtension[]{
973+
SSLExtension.CH_SESSION_TICKET
974+
};
975+
clientHello.extensions.consumeOnLoad(shc, ext);
976+
977+
// Does the client want to resume a session?
978+
if (clientHello.sessionId.length() != 0 || shc.statelessResumption) {
979+
SSLSessionContextImpl cache = (SSLSessionContextImpl)shc.sslContext
980+
.engineGetServerSessionContext();
981+
982+
SSLSessionImpl previous;
983+
// Use the stateless session ticket if provided
984+
if (shc.statelessResumption) {
985+
previous = shc.resumingSession;
986+
} else {
987+
previous = cache.get(clientHello.sessionId.getId());
988+
}
977989

978990
boolean resumingSession =
979991
(previous != null) && previous.isRejoinable();
@@ -1051,14 +1063,20 @@ public void consume(ConnectionContext context,
10511063
// the resuming options later.
10521064
shc.isResumption = resumingSession;
10531065
shc.resumingSession = resumingSession ? previous : null;
1066+
1067+
if (!resumingSession && SSLLogger.isOn &&
1068+
SSLLogger.isOn("ssl,handshake")) {
1069+
SSLLogger.fine("Session not resumed.");
1070+
}
10541071
}
10551072

10561073
// cache the client random number for further using
10571074
shc.clientHelloRandom = clientHello.clientRandom;
10581075

10591076
// Check and launch ClientHello extensions.
1060-
SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
1061-
SSLHandshake.CLIENT_HELLO);
1077+
SSLExtension[] extTypes = shc.sslConfig.getExclusiveExtensions(
1078+
SSLHandshake.CLIENT_HELLO,
1079+
Arrays.asList(SSLExtension.CH_SESSION_TICKET));
10621080
clientHello.extensions.consumeOnLoad(shc, extTypes);
10631081

10641082
//
@@ -1276,11 +1294,25 @@ public void consume(ConnectionContext context,
12761294
}
12771295
}
12781296

1279-
// Is it an abbreviated handshake?
1297+
1298+
// Does the client want to resume a session?
12801299
if (clientHello.sessionId.length() != 0) {
1281-
SSLSessionImpl previous = ((SSLSessionContextImpl)shc.sslContext
1282-
.engineGetServerSessionContext())
1283-
.get(clientHello.sessionId.getId());
1300+
SSLSessionContextImpl cache = (SSLSessionContextImpl)shc.sslContext
1301+
.engineGetServerSessionContext();
1302+
1303+
// Consume a Session Ticket Extension if it exists
1304+
SSLExtension[] ext = new SSLExtension[]{
1305+
SSLExtension.CH_SESSION_TICKET
1306+
};
1307+
clientHello.extensions.consumeOnLoad(shc, ext);
1308+
1309+
SSLSessionImpl previous;
1310+
// Use stateless session ticket if provided.
1311+
if (shc.statelessResumption) {
1312+
previous = shc.resumingSession;
1313+
} else {
1314+
previous = cache.get(clientHello.sessionId.getId());
1315+
}
12841316

12851317
boolean resumingSession =
12861318
(previous != null) && previous.isRejoinable();

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

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ private byte[] onProduceFinished(ClientHandshakeContext chc,
410410
chc.conContext.clientVerifyData = fm.verifyData;
411411
}
412412

413+
if (chc.statelessResumption) {
414+
chc.handshakeConsumers.put(
415+
SSLHandshake.NEW_SESSION_TICKET.id, SSLHandshake.NEW_SESSION_TICKET);
416+
}
413417
// update the consumers and producers
414418
if (!chc.isResumption) {
415419
chc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
@@ -441,6 +445,10 @@ private byte[] onProduceFinished(ClientHandshakeContext chc,
441445

442446
private byte[] onProduceFinished(ServerHandshakeContext shc,
443447
HandshakeMessage message) throws IOException {
448+
if (shc.statelessResumption) {
449+
NewSessionTicket.handshake12Producer.produce(shc, message);
450+
}
451+
444452
// Refresh handshake hash
445453
shc.handshakeHash.update();
446454

@@ -473,7 +481,8 @@ private byte[] onProduceFinished(ServerHandshakeContext shc,
473481
SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
474482
shc.conContext.inputRecord.expectingFinishFlight();
475483
} else {
476-
if (shc.handshakeSession.isRejoinable()) {
484+
if (shc.handshakeSession.isRejoinable() &&
485+
!shc.statelessResumption) {
477486
((SSLSessionContextImpl)shc.sslContext.
478487
engineGetServerSessionContext()).put(
479488
shc.handshakeSession);
@@ -591,7 +600,8 @@ private void onConsumeFinished(ServerHandshakeContext shc,
591600
}
592601

593602
if (shc.isResumption) {
594-
if (shc.handshakeSession.isRejoinable()) {
603+
if (shc.handshakeSession.isRejoinable() &&
604+
!shc.statelessResumption) {
595605
((SSLSessionContextImpl)shc.sslContext.
596606
engineGetServerSessionContext()).put(
597607
shc.handshakeSession);
@@ -915,9 +925,9 @@ private void onConsumeFinished(ClientHandshakeContext chc,
915925

916926
// save the session
917927
if (!chc.isResumption && chc.handshakeSession.isRejoinable()) {
918-
SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
919-
chc.sslContext.engineGetClientSessionContext();
920-
sessionContext.put(chc.handshakeSession);
928+
((SSLSessionContextImpl)chc.sslContext.
929+
engineGetClientSessionContext()).
930+
put(chc.handshakeSession);
921931
}
922932

923933
// derive salt secret
@@ -1028,10 +1038,11 @@ private void onConsumeFinished(ServerHandshakeContext shc,
10281038
shc.negotiatedProtocol);
10291039
}
10301040

1031-
// save the session
1032-
if (!shc.isResumption && shc.handshakeSession.isRejoinable()) {
1041+
// Save the session if possible and not stateless
1042+
if (!shc.statelessResumption && !shc.isResumption &&
1043+
shc.handshakeSession.isRejoinable()) {
10331044
SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
1034-
shc.sslContext.engineGetServerSessionContext();
1045+
shc.sslContext.engineGetServerSessionContext();
10351046
sessionContext.put(shc.handshakeSession);
10361047
}
10371048

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ abstract class HandshakeContext implements ConnectionContext {
102102
// Resumption
103103
boolean isResumption;
104104
SSLSessionImpl resumingSession;
105+
// Session is using stateless resumption
106+
boolean statelessResumption = false;
105107

106108
final Queue<Map.Entry<Byte, ByteBuffer>> delegatedActions;
107109
volatile boolean taskDelegated = false;
@@ -551,7 +553,7 @@ private static boolean isActivatable(CipherSuite suite,
551553

552554
List<SNIServerName> getRequestedServerNames() {
553555
if (requestedServerNames == null) {
554-
return Collections.<SNIServerName>emptyList();
556+
return Collections.emptyList();
555557
}
556558
return requestedServerNames;
557559
}

0 commit comments

Comments
 (0)