--- a/src/java.base/share/classes/sun/security/ssl/CertStatusExtension.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/CertStatusExtension.java Thu Jun 07 21:16:21 2018 -0700
@@ -612,7 +612,8 @@
// Update the context.
shc.handshakeExtensions.put(CH_STATUS_REQUEST, spec);
- if (!shc.negotiatedProtocol.useTLS13PlusSpec()) {
+ if (!shc.isResumption &&
+ !shc.negotiatedProtocol.useTLS13PlusSpec()) {
shc.handshakeProducers.put(SSLHandshake.CERTIFICATE_STATUS.id,
SSLHandshake.CERTIFICATE_STATUS);
} // Otherwise, the certificate status presents in server cert.
@@ -969,9 +970,12 @@
// Update the context.
shc.handshakeExtensions.put(CH_STATUS_REQUEST_V2, spec);
- shc.handshakeProducers.putIfAbsent(
- SSLHandshake.CERTIFICATE_STATUS.id,
- SSLHandshake.CERTIFICATE_STATUS);
+ if (!shc.isResumption) {
+ shc.handshakeProducers.putIfAbsent(
+ SSLHandshake.CERTIFICATE_STATUS.id,
+ SSLHandshake.CERTIFICATE_STATUS);
+ }
+
// No impact on session resumption.
}
}
--- a/src/java.base/share/classes/sun/security/ssl/ClientHello.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHello.java Thu Jun 07 21:16:21 2018 -0700
@@ -1092,12 +1092,30 @@
ContentType.CHANGE_CIPHER_SPEC.id,
ChangeCipherSpec.t13Consumer);
- //
- // validate
+ // Is it a resumption?
//
- // Check and launch ClientHello extensions.
- SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
- SSLHandshake.CLIENT_HELLO);
+ // Check and launch the "psk_key_exchange_modes" and
+ // "pre_shared_key" extensions first, which will reset the
+ // resuming session, no matter the extensions present or not.
+ shc.isResumption = true;
+ SSLExtension[] extTypes = new SSLExtension[] {
+ SSLExtension.PSK_KEY_EXCHANGE_MODES,
+ SSLExtension.CH_PRE_SHARED_KEY
+ };
+ clientHello.extensions.consumeOnLoad(shc, extTypes);
+
+ // Check and launch ClientHello extensions other than
+ // "psk_key_exchange_modes", "pre_shared_key", "protocol_version"
+ // and "key_share" extensions.
+ //
+ // These extensions may discard session resumption, or ask for
+ // hello retry.
+ extTypes = shc.sslConfig.getExclusiveExtensions(
+ SSLHandshake.CLIENT_HELLO,
+ Arrays.asList(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES,
+ SSLExtension.CH_PRE_SHARED_KEY,
+ SSLExtension.CH_SUPPORTED_VERSIONS));
clientHello.extensions.consumeOnLoad(shc, extTypes);
if (!shc.handshakeProducers.isEmpty()) {
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java Thu Jun 07 21:16:21 2018 -0700
@@ -152,8 +152,6 @@
List<SNIServerName> requestedServerNames;
SNIServerName negotiatedServerName;
- List<PskKeyExchangeMode> pskKeyExchangeModes = new ArrayList<>();
-
// OCSP Stapling info
boolean staplingActive = false;
--- a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java Thu Jun 07 21:16:21 2018 -0700
@@ -35,6 +35,7 @@
import java.util.Optional;
import javax.crypto.SecretKey;
import javax.net.ssl.SSLHandshakeException;
+import sun.security.ssl.PskKeyExchangeModesExtension.PskKeyExchangeModesSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage;
@@ -42,8 +43,7 @@
* Pack of the NewSessionTicket handshake message.
*/
final class NewSessionTicket {
-
- private static final int SEVEN_DAYS_IN_SECONDS = 604800;
+ private static final int MAX_TICKET_LIFETIME = 604800; // seconds, 7 days
static final SSLConsumer handshakeConsumer =
new NewSessionTicketConsumer();
@@ -78,24 +78,42 @@
ByteBuffer m) throws IOException {
super(context);
+ // struct {
+ // uint32 ticket_lifetime;
+ // uint32 ticket_age_add;
+ // opaque ticket_nonce<0..255>;
+ // opaque ticket<1..2^16-1>;
+ // Extension extensions<0..2^16-2>;
+ // } NewSessionTicket;
+ if (m.remaining() < 14) {
+ context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+ "Invalid NewSessionTicket message: no sufficient data");
+ }
+
this.ticketLifetime = Record.getInt32(m);
this.ticketAgeAdd = Record.getInt32(m);
this.ticketNonce = Record.getBytes8(m);
+
+ if (m.remaining() < 5) {
+ context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+ "Invalid NewSessionTicket message: no sufficient data");
+ }
+
this.ticket = Record.getBytes16(m);
- if (this.ticket.length == 0) {
+ if (ticket.length == 0) {
context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "No ticket in the NewSessionTicket handshake message");
+ "No ticket in the NewSessionTicket handshake message");
+ }
+
+ if (m.remaining() < 2) {
+ context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
+ "Invalid NewSessionTicket message: no sufficient data");
}
SSLExtension[] supportedExtensions =
context.sslConfig.getEnabledExtensions(
SSLHandshake.NEW_SESSION_TICKET);
- if (m.hasRemaining()) {
- this.extensions =
- new SSLExtensions(this, m, supportedExtensions);
- } else {
- this.extensions = new SSLExtensions(this);
- }
+ this.extensions = new SSLExtensions(this, m, supportedExtensions);
}
@Override
@@ -138,14 +156,14 @@
" \"ticket_nonce\" : \"{2}\",\n" +
" \"ticket\" : \"{3}\",\n" +
" \"extensions\" : [\n" +
- "{5}\n" +
+ "{4}\n" +
" ]\n" +
"'}'",
Locale.ENGLISH);
Object[] messageFields = {
ticketLifetime,
- "omitted", //ticketAgeAdd should not be logged
+ "<omitted>", //ticketAgeAdd should not be logged
Utilities.toHexString(ticketNonce),
Utilities.toHexString(ticket),
Utilities.indent(extensions.toString(), " ")
@@ -171,17 +189,32 @@
private static final
class NewSessionTicketKickstartProducer implements SSLProducer {
+ // Prevent instantiation of this class.
+ private NewSessionTicketKickstartProducer() {
+ // blank
+ }
+
@Override
public byte[] produce(ConnectionContext context) throws IOException {
// The producing happens in server side only.
ServerHandshakeContext shc = (ServerHandshakeContext)context;
- if (shc.pskKeyExchangeModes.isEmpty()) {
- // client doesn't support PSK
+ // Is this session resumable?
+ if (!shc.handshakeSession.isRejoinable()) {
return null;
}
- if (!shc.handshakeSession.isRejoinable()) {
+ // What's the requested PSK key exchange modes?
+ //
+ // Note that currently, the NewSessionTicket post-handshake is
+ // produced and delivered only in the current handshake context
+ // if required.
+ PskKeyExchangeModesSpec pkemSpec =
+ (PskKeyExchangeModesSpec)shc.handshakeExtensions.get(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES);
+ if (pkemSpec == null || !pkemSpec.contains(
+ PskKeyExchangeModesExtension.PskKeyExchangeMode.PSK_DHE_KE)) {
+ // Client doesn't support PSK with (EC)DHE key establishment.
return null;
}
@@ -209,7 +242,7 @@
resumptionMasterSecret.get(), nonceArr);
int sessionTimeoutSeconds = sessionCache.getSessionTimeout();
- if (sessionTimeoutSeconds > SEVEN_DAYS_IN_SECONDS) {
+ if (sessionTimeoutSeconds > MAX_TICKET_LIFETIME) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Session timeout is too long. No ticket sent.");
@@ -268,8 +301,6 @@
}
}
-
-
private static final
class NewSessionTicketConsumer implements SSLConsumer {
// Prevent instantiation of this class.
@@ -280,9 +311,21 @@
@Override
public void consume(ConnectionContext context,
ByteBuffer message) throws IOException {
- // The consuming happens in client side only.
- PostHandshakeContext hc = (PostHandshakeContext) context;
- NewSessionTicketMessage nstm = new NewSessionTicketMessage(hc, message);
+
+ // Note: Although the resumption master secret depends on the
+ // client's second flight, servers which do not request client
+ // authentication MAY compute the remainder of the transcript
+ // independently and then send a NewSessionTicket immediately
+ // upon sending its Finished rather than waiting for the client
+ // Finished.
+ //
+ // The consuming happens in client side only. As the server
+ // may send the NewSessionTicket before handshake complete, the
+ // context may be a PostHandshakeContext or HandshakeContext
+ // instance.
+ HandshakeContext hc = (HandshakeContext)context;
+ NewSessionTicketMessage nstm =
+ new NewSessionTicketMessage(hc, message);
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Consuming NewSessionTicket message", nstm);
@@ -290,7 +333,7 @@
// discard tickets with timeout 0
if (nstm.ticketLifetime <= 0 ||
- nstm.ticketLifetime > SEVEN_DAYS_IN_SECONDS) {
+ nstm.ticketLifetime > MAX_TICKET_LIFETIME) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Discarding NewSessionTicket with lifetime "
@@ -302,7 +345,7 @@
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
hc.sslContext.engineGetClientSessionContext();
- if (sessionCache.getSessionTimeout() > SEVEN_DAYS_IN_SECONDS) {
+ if (sessionCache.getSessionTimeout() > MAX_TICKET_LIFETIME) {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine(
"Session cache lifetime is too long. Discarding ticket.");
--- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java Thu Jun 07 21:16:21 2018 -0700
@@ -305,13 +305,12 @@
return; // fatal() always throws, make the compiler happy.
}
- if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
- SSLLogger.fine("Received PSK extension: ", pskSpec);
- }
-
- if (shc.pskKeyExchangeModes.isEmpty()) {
+ // The "psk_key_exchange_modes" extension should have been loaded.
+ if (!shc.handshakeExtensions.containsKey(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES)) {
shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
- "Client sent PSK but does not support PSK modes");
+ "Client sent PSK but not PSK modes, or the PSK " +
+ "extension is not the last extension");
}
// error if id and binder lists are not the same length
@@ -320,7 +319,7 @@
"PSK extension has incorrect number of binders");
}
- if (shc.isResumption && shc.resumingSession != null) {
+ if (shc.isResumption) { // resumingSession may not be set
SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
shc.sslContext.engineGetServerSessionContext();
int idIndex = 0;
--- a/src/java.base/share/classes/sun/security/ssl/PskKeyExchangeModesExtension.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/PskKeyExchangeModesExtension.java Thu Jun 07 21:16:21 2018 -0700
@@ -28,6 +28,7 @@
import java.nio.ByteBuffer;
import java.text.MessageFormat;
import java.util.*;
+import javax.net.ssl.SSLProtocolException;
import sun.security.ssl.SSLExtension.ExtensionConsumer;
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
@@ -41,88 +42,129 @@
new PskKeyExchangeModesProducer();
static final ExtensionConsumer chOnLoadConsumer =
new PskKeyExchangeModesConsumer();
+ static final HandshakeAbsence chOnLoadAbsence =
+ new PskKeyExchangeModesOnLoadAbsence();
+ static final HandshakeAbsence chOnTradeAbsence =
+ new PskKeyExchangeModesOnTradeAbsence();
+
+ static final SSLStringize pkemStringize =
+ new PskKeyExchangeModesStringize();
enum PskKeyExchangeMode {
- PSK_KE(0),
- PSK_DHE_KE(1);
+ PSK_KE ((byte)0, "psk_ke"),
+ PSK_DHE_KE ((byte)1, "psk_dhe_ke");
- private final int v;
+ final byte id;
+ final String name;
- PskKeyExchangeMode(int v) {
- this.v = v;
+ PskKeyExchangeMode(byte id, String name) {
+ this.id = id;
+ this.name = name;
}
- static PskKeyExchangeMode ofInt(int v) throws IOException {
- for(PskKeyExchangeMode mode : values()) {
- if (mode.v == v) {
- return mode;
+ static PskKeyExchangeMode valueOf(byte id) {
+ for(PskKeyExchangeMode pkem : values()) {
+ if (pkem.id == id) {
+ return pkem;
}
}
- throw new IOException("invalid key exchange mode: " + v);
+ return null;
+ }
+
+ static String nameOf(byte id) {
+ for (PskKeyExchangeMode pkem : PskKeyExchangeMode.values()) {
+ if (pkem.id == id) {
+ return pkem.name;
+ }
+ }
+
+ return "<UNKNOWN PskKeyExchangeMode TYPE: " + (id & 0x0FF) + ">";
}
}
- private static final class PskKeyExchangeModesSpec implements SSLExtensionSpec {
-
+ static final
+ class PskKeyExchangeModesSpec implements SSLExtensionSpec {
+ private static final PskKeyExchangeModesSpec DEFAULT =
+ new PskKeyExchangeModesSpec(new byte[] {
+ PskKeyExchangeMode.PSK_DHE_KE.id});
- final List<PskKeyExchangeMode> modes;
+ final byte[] modes;
- PskKeyExchangeModesSpec(List<PskKeyExchangeMode> modes) {
+ PskKeyExchangeModesSpec(byte[] modes) {
this.modes = modes;
}
PskKeyExchangeModesSpec(ByteBuffer m) throws IOException {
+ if (m.remaining() < 2) {
+ throw new SSLProtocolException(
+ "Invalid psk_key_exchange_modes extension: " +
+ "insufficient data");
+ }
- modes = new ArrayList<>();
- int modesEncodedLength = Record.getInt8(m);
- int modesReadLength = 0;
- while (modesReadLength < modesEncodedLength) {
- int mode = Record.getInt8(m);
- modes.add(PskKeyExchangeMode.ofInt(mode));
- modesReadLength += 1;
- }
+ this.modes = Record.getBytes8(m);
}
- byte[] getEncoded() throws IOException {
-
- int encodedLength = modes.size() + 1;
- byte[] buffer = new byte[encodedLength];
- ByteBuffer m = ByteBuffer.wrap(buffer);
- Record.putInt8(m, modes.size());
- for(PskKeyExchangeMode curMode : modes) {
- Record.putInt8(m, curMode.v);
+ boolean contains(PskKeyExchangeMode mode) {
+ if (modes != null) {
+ for (byte m : modes) {
+ if (mode.id == m) {
+ return true;
+ }
+ }
}
- return buffer;
+ return false;
}
@Override
public String toString() {
MessageFormat messageFormat = new MessageFormat(
- "\"PskKeyExchangeModes\": '{'\n" +
- " \"ke_modes\" : \"{0}\",\n" +
- "'}'",
- Locale.ENGLISH);
-
- Object[] messageFields = {
- Utilities.indent(modesString()),
- };
+ "\"ke_modes\": '['{0}']'", Locale.ENGLISH);
+ if (modes == null || modes.length == 0) {
+ Object[] messageFields = {
+ "<no PSK key exchange modes specified>"
+ };
+ return messageFormat.format(messageFields);
+ } else {
+ StringBuilder builder = new StringBuilder(64);
+ boolean isFirst = true;
+ for (byte mode : modes) {
+ if (isFirst) {
+ isFirst = false;
+ } else {
+ builder.append(", ");
+ }
- return messageFormat.format(messageFields);
- }
+ builder.append(PskKeyExchangeMode.nameOf(mode));
+ }
- String modesString() {
- StringBuilder result = new StringBuilder();
- for(PskKeyExchangeMode curMode : modes) {
- result.append(curMode.toString() + "\n");
+ Object[] messageFields = {
+ builder.toString()
+ };
+
+ return messageFormat.format(messageFields);
}
-
- return result.toString();
}
}
+ private static final
+ class PskKeyExchangeModesStringize implements SSLStringize {
+ @Override
+ public String toString(ByteBuffer buffer) {
+ try {
+ return (new PskKeyExchangeModesSpec(buffer)).toString();
+ } catch (IOException ioe) {
+ // For debug logging only, so please swallow exceptions.
+ return ioe.getMessage();
+ }
+ }
+ }
+ /**
+ * Network data consumer of a "psk_key_exchange_modes" extension in
+ * the ClientHello handshake message.
+ */
private static final
class PskKeyExchangeModesConsumer implements ExtensionConsumer {
// Prevent instantiation of this class.
@@ -134,28 +176,66 @@
public void consume(ConnectionContext context,
HandshakeMessage message, ByteBuffer buffer) throws IOException {
- ServerHandshakeContext shc =
- (ServerHandshakeContext) message.handshakeContext;
+ // The comsuming happens in server side only.
+ ServerHandshakeContext shc = (ServerHandshakeContext)context;
+
+ // Is it a supported and enabled extension?
+ if (!shc.sslConfig.isAvailable(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES)) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.fine(
+ "Ignore unavailable psk_key_exchange_modes extension");
+ }
- PskKeyExchangeModesSpec modes = new PskKeyExchangeModesSpec(buffer);
- if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
- SSLLogger.fine(
- "Received PskKeyExchangeModes extension: ", modes);
+ // No session resumption is allowed.
+ if (shc.isResumption && shc.resumingSession != null) {
+ shc.isResumption = false;
+ shc.resumingSession = null;
+ }
+
+ return; // ignore the extension
+ }
+
+ // Parse the extension.
+ PskKeyExchangeModesSpec spec;
+ try {
+ spec = new PskKeyExchangeModesSpec(buffer);
+ } catch (IOException ioe) {
+ shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
+ return; // fatal() always throws, make the compiler happy.
}
- shc.pskKeyExchangeModes = modes.modes;
+ // Update the context.
+ shc.handshakeExtensions.put(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES, spec);
+
+ // Impact on session resumption.
+ //
+ // Do the requested modes support session resumption?
+ if (shc.isResumption) { // resumingSession may not be set
+ // Note: psk_dhe_ke is the only supported mode now. If the
+ // psk_ke mode is supported in the future, may need an update
+ // here.
+ if (!spec.contains(PskKeyExchangeMode.PSK_DHE_KE)) {
+ shc.isResumption = false;
+ shc.resumingSession = null;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.fine(
+ "abort session resumption, " +
+ "no supported psk_dhe_ke PSK key exchange mode");
+ }
+ }
+ }
}
-
}
+ /**
+ * Network data producer of a "psk_key_exchange_modes" extension in the
+ * ClientHello handshake message.
+ */
private static final
class PskKeyExchangeModesProducer implements HandshakeProducer {
- static final List<PskKeyExchangeMode> MODES =
- List.of(PskKeyExchangeMode.PSK_DHE_KE);
- static final PskKeyExchangeModesSpec MODES_MSG =
- new PskKeyExchangeModesSpec(MODES);
-
// Prevent instantiation of this class.
private PskKeyExchangeModesProducer() {
// blank
@@ -164,10 +244,90 @@
@Override
public byte[] produce(ConnectionContext context,
HandshakeMessage message) throws IOException {
+ // The producing happens in client side only.
+ ClientHandshakeContext chc = (ClientHandshakeContext)context;
- return MODES_MSG.getEncoded();
+ // Is it a supported and enabled extension?
+ if (!chc.sslConfig.isAvailable(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES)) {
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.warning(
+ "Ignore unavailable psk_key_exchange_modes extension");
+ }
+
+ return null;
+ }
+
+ byte[] extData = new byte[] {0x01, 0x01}; // psk_dhe_ke
+
+ // Update the context.
+ chc.handshakeExtensions.put(
+ SSLExtension.PSK_KEY_EXCHANGE_MODES,
+ PskKeyExchangeModesSpec.DEFAULT);
+
+ return extData;
+ }
+ }
+ /**
+ * The absence processing if a "psk_key_exchange_modes" extension is
+ * not present in the ClientHello handshake message.
+ */
+ private static final
+ class PskKeyExchangeModesOnLoadAbsence implements HandshakeAbsence {
+
+ // Prevent instantiation of this class.
+ private PskKeyExchangeModesOnLoadAbsence() {
+ // blank
}
+ @Override
+ public void absent(ConnectionContext context,
+ HandshakeMessage message) throws IOException {
+ // The comsuming happens in server side only.
+ ServerHandshakeContext shc = (ServerHandshakeContext)context;
+
+ // No session resumptio is allowed.
+ if (shc.isResumption) { // resumingSession may not be set
+ shc.isResumption = false;
+ shc.resumingSession = null;
+ if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
+ SSLLogger.fine(
+ "abort session resumption, " +
+ "no supported psk_dhe_ke PSK key exchange mode");
+ }
+ }
+ }
+ }
+
+ /**
+ * The absence processing if a "signature_algorithms" extension is
+ * not present in the ClientHello handshake message.
+ */
+ private static final
+ class PskKeyExchangeModesOnTradeAbsence implements HandshakeAbsence {
+
+ // Prevent instantiation of this class.
+ private PskKeyExchangeModesOnTradeAbsence() {
+ // blank
+ }
+
+ @Override
+ public void absent(ConnectionContext context,
+ HandshakeMessage message) throws IOException {
+ // The comsuming happens in server side only.
+ ServerHandshakeContext shc = (ServerHandshakeContext)context;
+
+ // A client MUST provide a "psk_key_exchange_modes" extension if
+ // it offers a "pre_shared_key" extension. If clients offer
+ // "pre_shared_key" without a "psk_key_exchange_modes" extension,
+ // servers MUST abort the handshake.
+ SSLExtensionSpec spec =
+ shc.handshakeExtensions.get(SSLExtension.CH_PRE_SHARED_KEY);
+ if (spec == null) {
+ shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
+ "pre_shared_key key extension is offered " +
+ "without a psk_key_exchange_modes extension");
+ }
+ }
}
}
-
--- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java Thu Jun 07 21:16:21 2018 -0700
@@ -342,6 +342,26 @@
}
/**
+ * Get the enabled extensions for the specific handshake message, excluding
+ * the specified extensions.
+ *
+ * Used to consume handshake extensions.
+ */
+ SSLExtension[] getExclusiveExtensions(SSLHandshake handshakeType,
+ List<SSLExtension> excluded) {
+ List<SSLExtension> extensions = new ArrayList<>();
+ for (SSLExtension extension : SSLExtension.values()) {
+ if (extension.handshakeType == handshakeType) {
+ if (isAvailable(extension) && !excluded.contains(extension)) {
+ extensions.add(extension);
+ }
+ }
+ }
+
+ return extensions.toArray(new SSLExtension[0]);
+ }
+
+ /**
* Get the enabled extensions for the specific handshake message
* and the specific protocol version.
*
--- a/src/java.base/share/classes/sun/security/ssl/SSLExtension.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/SSLExtension.java Thu Jun 07 21:16:21 2018 -0700
@@ -383,7 +383,10 @@
ProtocolVersion.PROTOCOLS_OF_13,
PskKeyExchangeModesExtension.chNetworkProducer,
PskKeyExchangeModesExtension.chOnLoadConsumer,
- null, null, null, null),
+ PskKeyExchangeModesExtension.chOnLoadAbsence,
+ null,
+ PskKeyExchangeModesExtension.chOnTradeAbsence,
+ PskKeyExchangeModesExtension.pkemStringize),
CERTIFICATE_AUTHORITIES (0x002F, "certificate_authorities"),
OID_FILTERS (0x0030, "oid_filters"),
POST_HANDSHAKE_AUTH (0x0030, "post_handshake_auth"),
--- a/src/java.base/share/classes/sun/security/ssl/ServerHello.java Fri Jun 08 11:10:40 2018 +0800
+++ b/src/java.base/share/classes/sun/security/ssl/ServerHello.java Thu Jun 07 21:16:21 2018 -0700
@@ -872,7 +872,7 @@
ServerHelloMessage helloRetryRequest) throws IOException {
// Negotiate protocol version.
//
- // Check and lanuch SupportedVersions.
+ // Check and launch SupportedVersions.
SSLExtension[] extTypes = new SSLExtension[] {
SSLExtension.HRR_SUPPORTED_VERSIONS
};
@@ -924,7 +924,7 @@
ServerHelloMessage serverHello) throws IOException {
// Negotiate protocol version.
//
- // Check and lanuch SupportedVersions.
+ // Check and launch SupportedVersions.
SSLExtension[] extTypes = new SSLExtension[] {
SSLExtension.SH_SUPPORTED_VERSIONS
};
@@ -1023,7 +1023,7 @@
// validate
//
- // Check and lanuch the "renegotiation_info" extension.
+ // Check and launch the "renegotiation_info" extension.
SSLExtension[] extTypes = new SSLExtension[] {
SSLExtension.SH_RENEGOTIATION_INFO
};