8357033: Reduce stateless session ticket size
Reviewed-by: wetmore, djelinski, ascarpino
This commit is contained in:
parent
26275a10b2
commit
99048c3d4a
@ -443,12 +443,6 @@ final class PreSharedKeyExtension {
|
|||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure that the server handshake context's
|
|
||||||
// localSupportedCertSignAlgs field is populated. This is particularly
|
|
||||||
// important when client authentication was used in an initial session,
|
|
||||||
// and it is now being resumed.
|
|
||||||
SignatureScheme.updateHandshakeLocalSupportedAlgs(shc);
|
|
||||||
|
|
||||||
// Validate the required client authentication.
|
// Validate the required client authentication.
|
||||||
if (result &&
|
if (result &&
|
||||||
(shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
|
(shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
|
||||||
@ -464,7 +458,9 @@ final class PreSharedKeyExtension {
|
|||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the list of supported signature algorithms matches
|
// Make sure the list of supported signature algorithms matches.
|
||||||
|
// HandshakeContext's localSupportedCertSignAlgs has been already
|
||||||
|
// updated when we set the negotiated protocol.
|
||||||
Collection<SignatureScheme> sessionSigAlgs =
|
Collection<SignatureScheme> sessionSigAlgs =
|
||||||
s.getLocalSupportedSignatureSchemes();
|
s.getLocalSupportedSignatureSchemes();
|
||||||
if (result &&
|
if (result &&
|
||||||
|
@ -24,34 +24,33 @@
|
|||||||
*/
|
*/
|
||||||
package sun.security.ssl;
|
package sun.security.ssl;
|
||||||
|
|
||||||
import sun.security.provider.X509Factory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.zip.Adler32;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.net.ssl.ExtendedSSLSession;
|
import javax.net.ssl.ExtendedSSLSession;
|
||||||
import javax.net.ssl.SNIHostName;
|
import javax.net.ssl.SNIHostName;
|
||||||
import javax.net.ssl.SNIServerName;
|
import javax.net.ssl.SNIServerName;
|
||||||
import javax.net.ssl.SSLException;
|
|
||||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||||
import javax.net.ssl.SSLSessionBindingEvent;
|
import javax.net.ssl.SSLSessionBindingEvent;
|
||||||
import javax.net.ssl.SSLSessionBindingListener;
|
import javax.net.ssl.SSLSessionBindingListener;
|
||||||
import javax.net.ssl.SSLSessionContext;
|
import javax.net.ssl.SSLSessionContext;
|
||||||
|
import sun.security.provider.X509Factory;
|
||||||
|
import sun.security.ssl.X509Authentication.X509Possession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the SSL session interface, and exposes the session context
|
* Implements the SSL session interface, and exposes the session context
|
||||||
@ -256,59 +255,51 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Reassemble new session ticket.
|
||||||
|
* <p>
|
||||||
* < 2 bytes > protocolVersion
|
* < 2 bytes > protocolVersion
|
||||||
* < 2 bytes > cipherSuite
|
* < 2 bytes > cipherSuite
|
||||||
* < 1 byte > localSupportedSignAlgs entries
|
* < 1 byte > localSupportedSignAlgs entries
|
||||||
* < 2 bytes per entries > localSupportedSignAlgs
|
* < 2 bytes per entries > localSupportedSignAlgs
|
||||||
* < 1 bytes > peerSupportedSignAlgs entries
|
* select (protocolVersion)
|
||||||
* < 2 bytes per entries > peerSupportedSignAlgs
|
* case TLS13Plus:
|
||||||
* < 2 bytes > preSharedKey length
|
* < 2 bytes > preSharedKey length
|
||||||
* < length in bytes > preSharedKey
|
* < length in bytes > preSharedKey
|
||||||
* < 1 byte > pskIdentity length
|
* case non-TLS13Plus:
|
||||||
* < length in bytes > pskIdentity
|
* < 2 bytes > masterSecretKey length
|
||||||
* < 1 byte > masterSecret length
|
* < length in bytes> masterSecretKey
|
||||||
* < 1 byte > masterSecret algorithm length
|
* < 1 byte > useExtendedMasterSecret
|
||||||
* < length in bytes > masterSecret algorithm
|
|
||||||
* < 2 bytes > masterSecretKey length
|
|
||||||
* < length in bytes> masterSecretKey
|
|
||||||
* < 1 byte > useExtendedMasterSecret
|
|
||||||
* < 1 byte > identificationProtocol length
|
* < 1 byte > identificationProtocol length
|
||||||
* < length in bytes > identificationProtocol
|
* < length in bytes > identificationProtocol
|
||||||
* < 1 byte > serverNameIndication length
|
* < 1 byte > serverNameIndication length
|
||||||
* < length in bytes > serverNameIndication
|
* < length in bytes > serverNameIndication
|
||||||
* < 1 byte > Number of requestedServerNames entries
|
* < 1 byte > Number of requestedServerNames entries
|
||||||
* < 1 byte > ServerName length
|
* For each entry {
|
||||||
* < length in bytes > ServerName
|
* < 1 byte > ServerName length
|
||||||
|
* < length in bytes > ServerName
|
||||||
|
* }
|
||||||
* < 4 bytes > maximumPacketSize
|
* < 4 bytes > maximumPacketSize
|
||||||
* < 4 bytes > negotiatedMaxFragSize
|
* < 4 bytes > negotiatedMaxFragSize
|
||||||
* < 4 bytes > creationTime
|
* < 4 bytes > creationTime
|
||||||
* < 2 byte > status response length
|
|
||||||
* < 2 byte > status response entry length
|
|
||||||
* < length in byte > status response entry
|
|
||||||
* < 1 byte > Length of peer host
|
* < 1 byte > Length of peer host
|
||||||
* < length in bytes > peer host
|
* < length in bytes > peer host
|
||||||
* < 2 bytes> peer port
|
* < 2 bytes> peer port
|
||||||
* < 1 byte > Number of peerCerts entries
|
* < 1 byte > Number of Peer Certificate entries
|
||||||
* < 4 byte > peerCert length
|
* For each entry {
|
||||||
* < length in bytes > peerCert
|
* < 4 bytes > Peer certificate length
|
||||||
* < 1 byte > localCerts type (Cert, PSK, Anonymous)
|
* < length in bytes> Peer certificate
|
||||||
* Certificate
|
* }
|
||||||
* < 1 byte > Number of Certificate entries
|
* < 1 byte > Number of Local Certificate entries
|
||||||
* < 4 byte> Certificate length
|
* For each entry {
|
||||||
* < length in bytes> Certificate
|
* < 1 byte > Local Certificate algorithm length
|
||||||
* PSK
|
* < length in bytes> Local Certificate algorithm
|
||||||
* < 1 byte > Number of PSK entries
|
* < 4 bytes > Certificate checksum
|
||||||
* < 1 bytes > PSK algorithm length
|
* }
|
||||||
* < length in bytes > PSK algorithm string
|
|
||||||
* < 4 bytes > PSK key length
|
|
||||||
* < length in bytes> PSK key
|
|
||||||
* < 4 bytes > PSK identity length
|
|
||||||
* < length in bytes> PSK identity
|
|
||||||
* Anonymous
|
|
||||||
* < 1 byte >
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SSLSessionImpl(HandshakeContext hc, ByteBuffer buf) throws IOException {
|
SSLSessionImpl(HandshakeContext hc, ByteBuffer buf) throws IOException {
|
||||||
|
int len;
|
||||||
|
byte[] b;
|
||||||
boundValues = new ConcurrentHashMap<>();
|
boundValues = new ConcurrentHashMap<>();
|
||||||
this.protocolVersion =
|
this.protocolVersion =
|
||||||
ProtocolVersion.valueOf(Record.getInt16(buf));
|
ProtocolVersion.valueOf(Record.getInt16(buf));
|
||||||
@ -321,51 +312,36 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
CipherSuite.valueOf(Record.getInt16(buf));
|
CipherSuite.valueOf(Record.getInt16(buf));
|
||||||
|
|
||||||
// Local Supported signature algorithms
|
// Local Supported signature algorithms
|
||||||
ArrayList<SignatureScheme> list = new ArrayList<>();
|
List<SignatureScheme> list = new ArrayList<>();
|
||||||
int i = Record.getInt8(buf);
|
len = Record.getInt8(buf);
|
||||||
while (i-- > 0) {
|
while (len-- > 0) {
|
||||||
list.add(SignatureScheme.valueOf(
|
list.add(SignatureScheme.valueOf(
|
||||||
Record.getInt16(buf)));
|
Record.getInt16(buf)));
|
||||||
}
|
}
|
||||||
this.localSupportedSignAlgs = Collections.unmodifiableCollection(list);
|
this.localSupportedSignAlgs = Collections.unmodifiableCollection(list);
|
||||||
|
|
||||||
// Peer Supported signature algorithms
|
if (protocolVersion.useTLS13PlusSpec()) {
|
||||||
i = Record.getInt8(buf);
|
// PSK
|
||||||
list.clear();
|
|
||||||
while (i-- > 0) {
|
|
||||||
list.add(SignatureScheme.valueOf(
|
|
||||||
Record.getInt16(buf)));
|
|
||||||
}
|
|
||||||
this.peerSupportedSignAlgs = Collections.unmodifiableCollection(list);
|
|
||||||
|
|
||||||
// PSK
|
|
||||||
byte[] b = Record.getBytes16(buf);
|
|
||||||
if (b.length > 0) {
|
|
||||||
b = Record.getBytes16(buf);
|
b = Record.getBytes16(buf);
|
||||||
this.preSharedKey = new SecretKeySpec(b, "TlsMasterSecret");
|
if (b.length > 0) {
|
||||||
} else {
|
this.preSharedKey = new SecretKeySpec(b, "TlsMasterSecret");
|
||||||
this.preSharedKey = null;
|
} else {
|
||||||
}
|
this.preSharedKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
// PSK identity
|
this.useExtendedMasterSecret = false;
|
||||||
b = Record.getBytes8(buf);
|
|
||||||
if (b.length > 0) {
|
|
||||||
this.pskIdentity = b;
|
|
||||||
} else {
|
} else {
|
||||||
this.pskIdentity = null;
|
// Master secret
|
||||||
}
|
|
||||||
|
|
||||||
// Master secret length of secret key algorithm (one byte)
|
|
||||||
b = Record.getBytes8(buf);
|
|
||||||
if (b.length > 0) {
|
|
||||||
b = Record.getBytes16(buf);
|
b = Record.getBytes16(buf);
|
||||||
this.masterSecret = new SecretKeySpec(b, "TlsMasterSecret");
|
if (b.length > 0) {
|
||||||
} else {
|
this.masterSecret = new SecretKeySpec(b, "TlsMasterSecret");
|
||||||
this.masterSecret = null;
|
} else {
|
||||||
}
|
this.masterSecret = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Use extended master secret
|
// Extended master secret usage.
|
||||||
this.useExtendedMasterSecret = (Record.getInt8(buf) != 0);
|
this.useExtendedMasterSecret = (Record.getInt8(buf) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Identification Protocol
|
// Identification Protocol
|
||||||
b = Record.getBytes8(buf);
|
b = Record.getBytes8(buf);
|
||||||
@ -384,7 +360,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List of SNIServerName
|
// List of SNIServerName
|
||||||
int len = Record.getInt16(buf);
|
len = Record.getInt16(buf);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
this.requestedServerNames = Collections.emptyList();
|
this.requestedServerNames = Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
@ -401,20 +377,6 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
// Get creation time
|
// Get creation time
|
||||||
this.creationTime = buf.getLong();
|
this.creationTime = buf.getLong();
|
||||||
|
|
||||||
// Get Buffer sizes
|
|
||||||
|
|
||||||
// Status Response
|
|
||||||
len = Record.getInt16(buf);
|
|
||||||
if (len == 0) {
|
|
||||||
statusResponses = Collections.emptyList();
|
|
||||||
} else {
|
|
||||||
statusResponses = new ArrayList<>();
|
|
||||||
}
|
|
||||||
while (len-- > 0) {
|
|
||||||
b = Record.getBytes16(buf);
|
|
||||||
statusResponses.add(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Peer host & port
|
// Get Peer host & port
|
||||||
b = Record.getBytes8(buf);
|
b = Record.getBytes8(buf);
|
||||||
if (b.length == 0) {
|
if (b.length == 0) {
|
||||||
@ -424,71 +386,89 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
}
|
}
|
||||||
this.port = Record.getInt16(buf);
|
this.port = Record.getInt16(buf);
|
||||||
|
|
||||||
// Peer certs
|
// Peer certs.
|
||||||
i = Record.getInt8(buf);
|
len = Record.getInt8(buf);
|
||||||
if (i == 0) {
|
if (len == 0) {
|
||||||
this.peerCerts = null;
|
this.peerCerts = null;
|
||||||
} else {
|
} else {
|
||||||
this.peerCerts = new X509Certificate[i];
|
this.peerCerts = new X509Certificate[len];
|
||||||
int j = 0;
|
for (int i = 0; len > i; i++) {
|
||||||
while (i > j) {
|
|
||||||
b = new byte[buf.getInt()];
|
b = new byte[buf.getInt()];
|
||||||
buf.get(b);
|
buf.get(b);
|
||||||
try {
|
try {
|
||||||
this.peerCerts[j] = X509Factory.cachedGetX509Cert(b);
|
this.peerCerts[i] = X509Factory.cachedGetX509Cert(b);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
j++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get local certs of PSK
|
// Restore local certificates if cert algorithm(s) present.
|
||||||
switch (Record.getInt8(buf)) {
|
len = Record.getInt8(buf);
|
||||||
case 0:
|
if (len == 0) {
|
||||||
break;
|
this.localCerts = null;
|
||||||
case 1:
|
} else {
|
||||||
// number of certs
|
String[] certAlgs = new String[len];
|
||||||
len = buf.get();
|
int[] certCheckSums = new int[len];
|
||||||
this.localCerts = new X509Certificate[len];
|
|
||||||
i = 0;
|
for (int i = 0; len > i; i++) {
|
||||||
while (len > i) {
|
certAlgs[i] = new String(Record.getBytes8(buf));
|
||||||
b = new byte[buf.getInt()];
|
certCheckSums[i] = Record.getInt32(buf);
|
||||||
buf.get(b);
|
}
|
||||||
|
|
||||||
|
SSLPossession pos = X509Authentication.createPossession(
|
||||||
|
hc, certAlgs);
|
||||||
|
boolean same = false;
|
||||||
|
|
||||||
|
if (pos instanceof X509Possession x509Pos
|
||||||
|
&& x509Pos.popCerts != null
|
||||||
|
&& x509Pos.popCerts.length == len) {
|
||||||
|
// Make sure we got the exact same cert chain.
|
||||||
|
for (int i = 0; i < x509Pos.popCerts.length; i++) {
|
||||||
try {
|
try {
|
||||||
this.localCerts[i] = X509Factory.cachedGetX509Cert(b);
|
byte[] encoded = x509Pos.popCerts[i].getEncoded();
|
||||||
|
String popAlg = x509Pos.popCerts[i]
|
||||||
|
.getPublicKey().getAlgorithm();
|
||||||
|
|
||||||
|
if (certCheckSums[i] == getChecksum(encoded)
|
||||||
|
&& certAlgs[i].equals(popAlg)) {
|
||||||
|
// Use certs from cache.
|
||||||
|
x509Pos.popCerts[i] =
|
||||||
|
X509Factory.cachedGetX509Cert(encoded);
|
||||||
|
same = true;
|
||||||
|
} else {
|
||||||
|
same = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException(e);
|
throw new IOException(e);
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 2:
|
|
||||||
// pre-shared key
|
if (same) {
|
||||||
// Length of pre-shared key algorithm (one byte)
|
this.localCerts = ((X509Possession) pos).popCerts;
|
||||||
b = Record.getBytes8(buf);
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,session")) {
|
||||||
String alg = new String(b);
|
SSLLogger.fine("Restored " + len
|
||||||
// Get encoding
|
+ " local certificates from session ticket"
|
||||||
b = Record.getBytes16(buf);
|
+ " for algorithms " + Arrays.toString(certAlgs));
|
||||||
this.preSharedKey = new SecretKeySpec(b, alg);
|
|
||||||
// Get identity len
|
|
||||||
i = Record.getInt8(buf);
|
|
||||||
if (i > 0) {
|
|
||||||
this.pskIdentity = Record.getBytes8(buf);
|
|
||||||
} else {
|
|
||||||
this.pskIdentity = null;
|
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
this.localCerts = null;
|
||||||
throw new SSLException("Failed local certs of session.");
|
this.invalidated = true;
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,session")) {
|
||||||
|
SSLLogger.warning("Local certificates can not be restored "
|
||||||
|
+ "from session ticket "
|
||||||
|
+ "for algorithms " + Arrays.toString(certAlgs));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context = (SSLSessionContextImpl)
|
this.context = (SSLSessionContextImpl)
|
||||||
hc.sslContext.engineGetServerSessionContext();
|
hc.sslContext.engineGetServerSessionContext();
|
||||||
this.lastUsedTime = System.currentTimeMillis();
|
this.lastUsedTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Some situations we cannot provide a stateless ticket, but after it
|
// Some situations we cannot provide a stateless ticket, but after it
|
||||||
// has been negotiated
|
// has been negotiated
|
||||||
boolean isStatelessable() {
|
boolean isStatelessable() {
|
||||||
@ -529,49 +509,25 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
hos.putInt16(s.id);
|
hos.putInt16(s.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer Supported signature algorithms
|
// PreSharedKey is only needed by TLSv1.3,
|
||||||
hos.putInt8(peerSupportedSignAlgs.size());
|
// masterSecret is only needed by pre-TLSv1.3.
|
||||||
for (SignatureScheme s : peerSupportedSignAlgs) {
|
if (protocolVersion.useTLS13PlusSpec()) {
|
||||||
hos.putInt16(s.id);
|
// PSK
|
||||||
}
|
if (preSharedKey == null) {
|
||||||
|
hos.putInt16(0);
|
||||||
// PSK
|
} else {
|
||||||
if (preSharedKey == null ||
|
hos.putBytes16(preSharedKey.getEncoded());
|
||||||
preSharedKey.getAlgorithm() == null) {
|
|
||||||
hos.putInt16(0);
|
|
||||||
} else {
|
|
||||||
hos.putInt16(preSharedKey.getAlgorithm().length());
|
|
||||||
if (preSharedKey.getAlgorithm().length() != 0) {
|
|
||||||
hos.write(preSharedKey.getAlgorithm().getBytes());
|
|
||||||
}
|
}
|
||||||
b = preSharedKey.getEncoded();
|
|
||||||
hos.putInt16(b.length);
|
|
||||||
hos.write(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PSK Identity
|
|
||||||
if (pskIdentity == null) {
|
|
||||||
hos.putInt8(0);
|
|
||||||
} else {
|
} else {
|
||||||
hos.putInt8(pskIdentity.length);
|
// Master Secret
|
||||||
hos.write(pskIdentity, 0, pskIdentity.length);
|
if (getMasterSecret() == null) {
|
||||||
}
|
hos.putInt16(0);
|
||||||
|
} else {
|
||||||
// Master Secret
|
hos.putBytes16(masterSecret.getEncoded());
|
||||||
if (getMasterSecret() == null ||
|
|
||||||
getMasterSecret().getAlgorithm() == null) {
|
|
||||||
hos.putInt8(0);
|
|
||||||
} else {
|
|
||||||
hos.putInt8(getMasterSecret().getAlgorithm().length());
|
|
||||||
if (getMasterSecret().getAlgorithm().length() != 0) {
|
|
||||||
hos.write(getMasterSecret().getAlgorithm().getBytes());
|
|
||||||
}
|
}
|
||||||
b = getMasterSecret().getEncoded();
|
|
||||||
hos.putInt16(b.length);
|
|
||||||
hos.write(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
hos.putInt8(useExtendedMasterSecret ? 1 : 0);
|
hos.putInt8(useExtendedMasterSecret ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
// Identification Protocol
|
// Identification Protocol
|
||||||
if (identificationProtocol == null) {
|
if (identificationProtocol == null) {
|
||||||
@ -605,20 +561,11 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
hos.putInt32(maximumPacketSize);
|
hos.putInt32(maximumPacketSize);
|
||||||
hos.putInt32(negotiatedMaxFragLen);
|
hos.putInt32(negotiatedMaxFragLen);
|
||||||
|
|
||||||
// creation time
|
// Creation time
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
|
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
|
||||||
hos.writeBytes(buffer.putLong(creationTime).array());
|
hos.writeBytes(buffer.putLong(creationTime).array());
|
||||||
|
|
||||||
// Status Responses
|
// Peer Host & Port
|
||||||
List<byte[]> list = getStatusResponses();
|
|
||||||
int l = list.size();
|
|
||||||
hos.putInt16(l);
|
|
||||||
for (byte[] e : list) {
|
|
||||||
hos.putInt16(e.length);
|
|
||||||
hos.write(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// peer Host & Port
|
|
||||||
if (host == null || host.length() == 0) {
|
if (host == null || host.length() == 0) {
|
||||||
hos.putInt8(0);
|
hos.putInt8(0);
|
||||||
} else {
|
} else {
|
||||||
@ -627,7 +574,7 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
}
|
}
|
||||||
hos.putInt16(port);
|
hos.putInt16(port);
|
||||||
|
|
||||||
// Peer cert
|
// Peer certs.
|
||||||
if (peerCerts == null || peerCerts.length == 0) {
|
if (peerCerts == null || peerCerts.length == 0) {
|
||||||
hos.putInt8(0);
|
hos.putInt8(0);
|
||||||
} else {
|
} else {
|
||||||
@ -639,34 +586,28 @@ final class SSLSessionImpl extends ExtendedSSLSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client identity
|
// Local certificates' algorithms and checksums.
|
||||||
if (localCerts != null && localCerts.length > 0) {
|
// We don't include the complete local certificates in a session ticket
|
||||||
// certificate based
|
// to decrease the size of ClientHello message.
|
||||||
hos.putInt8(1);
|
if (localCerts == null || localCerts.length == 0) {
|
||||||
|
hos.putInt8(0);
|
||||||
|
} else {
|
||||||
hos.putInt8(localCerts.length);
|
hos.putInt8(localCerts.length);
|
||||||
for (X509Certificate c : localCerts) {
|
for (X509Certificate c : localCerts) {
|
||||||
b = c.getEncoded();
|
hos.putBytes8(c.getPublicKey().getAlgorithm().getBytes());
|
||||||
hos.putInt32(b.length);
|
hos.putInt32(getChecksum(c.getEncoded()));
|
||||||
hos.writeBytes(b);
|
|
||||||
}
|
}
|
||||||
} else if (preSharedKey != null) {
|
|
||||||
// pre-shared key
|
|
||||||
hos.putInt8(2);
|
|
||||||
hos.putInt8(preSharedKey.getAlgorithm().length());
|
|
||||||
hos.write(preSharedKey.getAlgorithm().getBytes());
|
|
||||||
b = preSharedKey.getEncoded();
|
|
||||||
hos.putInt32(b.length);
|
|
||||||
hos.writeBytes(b);
|
|
||||||
hos.putInt32(pskIdentity.length);
|
|
||||||
hos.writeBytes(pskIdentity);
|
|
||||||
} else {
|
|
||||||
// anonymous
|
|
||||||
hos.putInt8(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hos.toByteArray();
|
return hos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getChecksum(byte[] input) {
|
||||||
|
Adler32 adler32 = new Adler32();
|
||||||
|
adler32.update(input);
|
||||||
|
return (int) adler32.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
void setMasterSecret(SecretKey secret) {
|
void setMasterSecret(SecretKey secret) {
|
||||||
masterSecret = secret;
|
masterSecret = secret;
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,16 @@
|
|||||||
|
|
||||||
package sun.security.ssl;
|
package sun.security.ssl;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.KeyGenerator;
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
@ -70,6 +74,9 @@ final class SessionTicketExtension {
|
|||||||
new T12SHSessionTicketConsumer();
|
new T12SHSessionTicketConsumer();
|
||||||
|
|
||||||
static final SSLStringizer steStringizer = new SessionTicketStringizer();
|
static final SSLStringizer steStringizer = new SessionTicketStringizer();
|
||||||
|
// No need to compress a ticket if it can fit in a single packet.
|
||||||
|
// Besides, small buffers often end up to be larger when compressed.
|
||||||
|
static final int MIN_COMPRESS_SIZE = 600;
|
||||||
|
|
||||||
// Time in milliseconds until key is changed for encrypting session state
|
// Time in milliseconds until key is changed for encrypting session state
|
||||||
private static final int TIMEOUT_DEFAULT = 3600 * 1000;
|
private static final int TIMEOUT_DEFAULT = 3600 * 1000;
|
||||||
@ -196,7 +203,7 @@ final class SessionTicketExtension {
|
|||||||
data = buf;
|
data = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] encrypt(HandshakeContext hc, SSLSessionImpl session) {
|
byte[] encrypt(HandshakeContext hc, SSLSessionImpl session) {
|
||||||
byte[] encrypted;
|
byte[] encrypted;
|
||||||
|
|
||||||
if (!hc.statelessResumption ||
|
if (!hc.statelessResumption ||
|
||||||
@ -213,26 +220,34 @@ final class SessionTicketExtension {
|
|||||||
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
|
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
c.init(Cipher.ENCRYPT_MODE, key.key,
|
c.init(Cipher.ENCRYPT_MODE, key.key,
|
||||||
new GCMParameterSpec(GCM_TAG_LEN, iv));
|
new GCMParameterSpec(GCM_TAG_LEN, iv));
|
||||||
c.updateAAD(new byte[] {
|
|
||||||
(byte)(key.num >>> 24),
|
|
||||||
(byte)(key.num >>> 16),
|
|
||||||
(byte)(key.num >>> 8),
|
|
||||||
(byte)(key.num)}
|
|
||||||
);
|
|
||||||
byte[] data = session.write();
|
byte[] data = session.write();
|
||||||
if (data.length == 0) {
|
if (data.length == 0) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compress the session before encryption if needed.
|
||||||
|
byte compressed = 0;
|
||||||
|
if (data.length >= MIN_COMPRESS_SIZE) {
|
||||||
|
data = compress(data);
|
||||||
|
compressed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer aad = ByteBuffer.allocate(Integer.BYTES + 1);
|
||||||
|
aad.putInt(key.num).put(compressed);
|
||||||
|
c.updateAAD(aad);
|
||||||
|
|
||||||
encrypted = c.doFinal(data);
|
encrypted = c.doFinal(data);
|
||||||
byte[] result = new byte[encrypted.length + Integer.BYTES +
|
byte[] result = new byte[encrypted.length + Integer.BYTES +
|
||||||
iv.length];
|
iv.length + 1];
|
||||||
result[0] = (byte)(key.num >>> 24);
|
result[0] = (byte)(key.num >>> 24);
|
||||||
result[1] = (byte)(key.num >>> 16);
|
result[1] = (byte)(key.num >>> 16);
|
||||||
result[2] = (byte)(key.num >>> 8);
|
result[2] = (byte)(key.num >>> 8);
|
||||||
result[3] = (byte)(key.num);
|
result[3] = (byte)(key.num);
|
||||||
System.arraycopy(iv, 0, result, Integer.BYTES, iv.length);
|
System.arraycopy(iv, 0, result, Integer.BYTES, iv.length);
|
||||||
|
result[Integer.BYTES + iv.length] = compressed;
|
||||||
System.arraycopy(encrypted, 0, result,
|
System.arraycopy(encrypted, 0, result,
|
||||||
Integer.BYTES + iv.length, encrypted.length);
|
Integer.BYTES + iv.length + 1, encrypted.length);
|
||||||
return result;
|
return result;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
@ -257,26 +272,67 @@ final class SessionTicketExtension {
|
|||||||
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
|
Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
c.init(Cipher.DECRYPT_MODE, key.key,
|
c.init(Cipher.DECRYPT_MODE, key.key,
|
||||||
new GCMParameterSpec(GCM_TAG_LEN, iv));
|
new GCMParameterSpec(GCM_TAG_LEN, iv));
|
||||||
c.updateAAD(new byte[] {
|
|
||||||
(byte)(keyID >>> 24),
|
|
||||||
(byte)(keyID >>> 16),
|
|
||||||
(byte)(keyID >>> 8),
|
|
||||||
(byte)(keyID)}
|
|
||||||
);
|
|
||||||
|
|
||||||
ByteBuffer out;
|
byte compressed = data.get();
|
||||||
out = ByteBuffer.allocate(data.remaining() - GCM_TAG_LEN / 8);
|
ByteBuffer aad = ByteBuffer.allocate(Integer.BYTES + 1);
|
||||||
|
aad.putInt(keyID).put(compressed);
|
||||||
|
c.updateAAD(aad);
|
||||||
|
|
||||||
|
ByteBuffer out = ByteBuffer.allocate(
|
||||||
|
data.remaining() - GCM_TAG_LEN / 8);
|
||||||
c.doFinal(data, out);
|
c.doFinal(data, out);
|
||||||
out.flip();
|
out.flip();
|
||||||
|
|
||||||
|
// Decompress the session after decryption if needed.
|
||||||
|
if (compressed == 1) {
|
||||||
|
out = decompress(out);
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
SSLLogger.fine("Decryption failed." + e.getMessage());
|
SSLLogger.fine("Decryption failed." + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static byte[] compress(byte[] input) throws IOException {
|
||||||
|
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
GZIPOutputStream gos = new GZIPOutputStream(baos)) {
|
||||||
|
final int decompressedLen = input.length;
|
||||||
|
gos.write(input, 0, decompressedLen);
|
||||||
|
gos.finish();
|
||||||
|
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.fine("decompressed bytes: " + decompressedLen
|
||||||
|
+ "; compressed bytes: " + baos.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteBuffer decompress(ByteBuffer input)
|
||||||
|
throws IOException {
|
||||||
|
final int compressedLen = input.remaining();
|
||||||
|
byte[] bytes = new byte[compressedLen];
|
||||||
|
input.get(bytes);
|
||||||
|
|
||||||
|
try (GZIPInputStream gis = new GZIPInputStream(
|
||||||
|
new ByteArrayInputStream(bytes))) {
|
||||||
|
byte[] out = gis.readAllBytes();
|
||||||
|
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.fine("compressed bytes: " + compressedLen
|
||||||
|
+ "; decompressed bytes: " + out.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ByteBuffer.wrap(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
byte[] getEncoded() {
|
byte[] getEncoded() {
|
||||||
byte[] out = new byte[data.capacity()];
|
byte[] out = new byte[data.capacity()];
|
||||||
data.duplicate().get(out);
|
data.duplicate().get(out);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,6 +26,7 @@
|
|||||||
* @bug 8206929
|
* @bug 8206929
|
||||||
* @summary ensure that server only resumes a session if certain properties
|
* @summary ensure that server only resumes a session if certain properties
|
||||||
* of the session are compatible with the new connection
|
* of the session are compatible with the new connection
|
||||||
|
* @modules java.base/sun.security.x509
|
||||||
* @library /javax/net/ssl/templates
|
* @library /javax/net/ssl/templates
|
||||||
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=false ResumeChecksServer BASIC
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=false -Djdk.tls.client.enableSessionTicketExtension=false ResumeChecksServer BASIC
|
||||||
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=false ResumeChecksServer BASIC
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.2 -Djdk.tls.server.enableSessionTicketExtension=true -Djdk.tls.client.enableSessionTicketExtension=false ResumeChecksServer BASIC
|
||||||
@ -48,6 +49,7 @@ import java.io.*;
|
|||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import sun.security.x509.X509CertImpl;
|
||||||
|
|
||||||
public class ResumeChecksServer extends SSLContextTemplate {
|
public class ResumeChecksServer extends SSLContextTemplate {
|
||||||
|
|
||||||
@ -57,7 +59,8 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
VERSION_2_TO_3,
|
VERSION_2_TO_3,
|
||||||
VERSION_3_TO_2,
|
VERSION_3_TO_2,
|
||||||
CIPHER_SUITE,
|
CIPHER_SUITE,
|
||||||
SIGNATURE_SCHEME
|
SIGNATURE_SCHEME,
|
||||||
|
LOCAL_CERTS
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
@ -71,6 +74,7 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void run() throws Exception {
|
private void run() throws Exception {
|
||||||
|
SSLSession firstSession;
|
||||||
SSLSession secondSession = null;
|
SSLSession secondSession = null;
|
||||||
|
|
||||||
SSLContext sslContext = createServerSSLContext();
|
SSLContext sslContext = createServerSSLContext();
|
||||||
@ -81,7 +85,7 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
Client client = startClient(ssock.getLocalPort());
|
Client client = startClient(ssock.getLocalPort());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connect(client, ssock, testMode, false);
|
firstSession = connect(client, ssock, testMode, null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
@ -89,7 +93,7 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
long secondStartTime = System.currentTimeMillis();
|
long secondStartTime = System.currentTimeMillis();
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
try {
|
try {
|
||||||
secondSession = connect(client, ssock, testMode, true);
|
secondSession = connect(client, ssock, testMode, firstSession);
|
||||||
} catch (SSLHandshakeException ex) {
|
} catch (SSLHandshakeException ex) {
|
||||||
// this is expected
|
// this is expected
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -105,6 +109,14 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
if (secondSession.getCreationTime() > secondStartTime) {
|
if (secondSession.getCreationTime() > secondStartTime) {
|
||||||
throw new RuntimeException("Session was not reused");
|
throw new RuntimeException("Session was not reused");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fail if session's certificates are not restored correctly.
|
||||||
|
if (!java.util.Arrays.equals(
|
||||||
|
firstSession.getLocalCertificates(),
|
||||||
|
secondSession.getLocalCertificates())) {
|
||||||
|
throw new RuntimeException("Certificates do not match");
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case CLIENT_AUTH:
|
case CLIENT_AUTH:
|
||||||
// throws an exception if the client is not authenticated
|
// throws an exception if the client is not authenticated
|
||||||
@ -114,6 +126,7 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
case VERSION_3_TO_2:
|
case VERSION_3_TO_2:
|
||||||
case CIPHER_SUITE:
|
case CIPHER_SUITE:
|
||||||
case SIGNATURE_SCHEME:
|
case SIGNATURE_SCHEME:
|
||||||
|
case LOCAL_CERTS:
|
||||||
// fail if a new session is not created
|
// fail if a new session is not created
|
||||||
if (secondSession.getCreationTime() <= secondStartTime) {
|
if (secondSession.getCreationTime() <= secondStartTime) {
|
||||||
throw new RuntimeException("Existing session was used");
|
throw new RuntimeException("Existing session was used");
|
||||||
@ -153,7 +166,9 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static SSLSession connect(Client client, SSLServerSocket ssock,
|
private static SSLSession connect(Client client, SSLServerSocket ssock,
|
||||||
TestMode mode, boolean second) throws Exception {
|
TestMode mode, SSLSession firstSession) throws Exception {
|
||||||
|
|
||||||
|
boolean second = firstSession != null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client.signal();
|
client.signal();
|
||||||
@ -200,9 +215,22 @@ public class ResumeChecksServer extends SSLContextTemplate {
|
|||||||
AlgorithmConstraints constraints =
|
AlgorithmConstraints constraints =
|
||||||
params.getAlgorithmConstraints();
|
params.getAlgorithmConstraints();
|
||||||
if (second) {
|
if (second) {
|
||||||
params.setAlgorithmConstraints(new NoSig("ecdsa"));
|
params.setAlgorithmConstraints(
|
||||||
|
new NoSig("ecdsa_secp384r1_sha384"));
|
||||||
} else {
|
} else {
|
||||||
params.setAlgorithmConstraints(new NoSig("rsa"));
|
params.setAlgorithmConstraints(
|
||||||
|
new NoSig("ecdsa_secp521r1_sha512"));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOCAL_CERTS:
|
||||||
|
if (second) {
|
||||||
|
// Add first session's certificate signature
|
||||||
|
// algorithm to constraints so local certificates
|
||||||
|
// can't be restored from the session ticket.
|
||||||
|
params.setAlgorithmConstraints(
|
||||||
|
new NoSig(X509CertImpl.toImpl((X509CertImpl)
|
||||||
|
firstSession.getLocalCertificates()[0])
|
||||||
|
.getSigAlgName()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,9 +23,10 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8211018
|
* @bug 8211018 8357033
|
||||||
* @summary ensure that server only resumes a session if certain properties
|
* @summary ensure that server only resumes a session if certain properties
|
||||||
* of the session are compatible with the new connection
|
* of the session are compatible with the new connection
|
||||||
|
* @modules java.base/sun.security.x509
|
||||||
* @library /javax/net/ssl/templates
|
* @library /javax/net/ssl/templates
|
||||||
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer BASIC
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer BASIC
|
||||||
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer CLIENT_AUTH
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer CLIENT_AUTH
|
||||||
@ -33,4 +34,5 @@
|
|||||||
* @run main/othervm ResumeChecksServer VERSION_3_TO_2
|
* @run main/othervm ResumeChecksServer VERSION_3_TO_2
|
||||||
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer CIPHER_SUITE
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer CIPHER_SUITE
|
||||||
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer SIGNATURE_SCHEME
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer SIGNATURE_SCHEME
|
||||||
|
* @run main/othervm -Djdk.tls.client.protocols=TLSv1.3 ResumeChecksServer LOCAL_CERTS
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user