8210989: RSASSA-PSS certificate cannot be selected for client auth on TLSv1.2
Reviewed-by: xuelei
This commit is contained in:
parent
a9b4ac9c37
commit
a40d0a0ee1
src/java.base/share/classes/sun/security/ssl
@ -31,7 +31,9 @@ import java.security.PrivateKey;
|
|||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -675,45 +677,86 @@ final class CertificateRequest {
|
|||||||
chc.peerRequestedSignatureSchemes = sss;
|
chc.peerRequestedSignatureSchemes = sss;
|
||||||
chc.peerRequestedCertSignSchemes = sss; // use the same schemes
|
chc.peerRequestedCertSignSchemes = sss; // use the same schemes
|
||||||
chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
|
chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
|
||||||
|
chc.peerSupportedAuthorities = crm.getAuthorities();
|
||||||
|
|
||||||
X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
|
// For TLS 1.2, we no longer use the certificate_types field
|
||||||
String clientAlias = null;
|
// from the CertificateRequest message to directly determine
|
||||||
if (chc.conContext.transport instanceof SSLSocketImpl) {
|
// the SSLPossession. Instead, the choosePossession method
|
||||||
clientAlias = km.chooseClientAlias(crm.getKeyTypes(),
|
// will use the accepted signature schemes in the message to
|
||||||
crm.getAuthorities(), (SSLSocket)chc.conContext.transport);
|
// determine the set of acceptable certificate types to select from.
|
||||||
} else if (chc.conContext.transport instanceof SSLEngineImpl) {
|
SSLPossession pos = choosePossession(chc);
|
||||||
clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),
|
if (pos == null) {
|
||||||
crm.getAuthorities(), (SSLEngine)chc.conContext.transport);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientAlias == null) {
|
|
||||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
|
||||||
SSLLogger.warning("No available client authentication");
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
|
chc.handshakePossessions.add(pos);
|
||||||
if (clientPrivateKey == null) {
|
|
||||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
|
||||||
SSLLogger.warning("No available client private key");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);
|
|
||||||
if ((clientCerts == null) || (clientCerts.length == 0)) {
|
|
||||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
|
||||||
SSLLogger.warning("No available client certificate");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chc.handshakePossessions.add(
|
|
||||||
new X509Possession(clientPrivateKey, clientCerts));
|
|
||||||
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
|
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
|
||||||
SSLHandshake.CERTIFICATE_VERIFY);
|
SSLHandshake.CERTIFICATE_VERIFY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static SSLPossession choosePossession(HandshakeContext hc)
|
||||||
|
throws IOException {
|
||||||
|
if (hc.peerRequestedCertSignSchemes == null ||
|
||||||
|
hc.peerRequestedCertSignSchemes.isEmpty()) {
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.warning("No signature and hash algorithms " +
|
||||||
|
"in CertificateRequest");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<String> checkedKeyTypes = new HashSet<>();
|
||||||
|
for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) {
|
||||||
|
if (checkedKeyTypes.contains(ss.keyAlgorithm)) {
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.warning(
|
||||||
|
"Unsupported authentication scheme: " + ss.name);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't select a signature scheme unless we will be able to
|
||||||
|
// produce a CertificateVerify message later
|
||||||
|
if (SignatureScheme.getPreferableAlgorithm(
|
||||||
|
hc.peerRequestedSignatureSchemes,
|
||||||
|
ss, hc.negotiatedProtocol) == null) {
|
||||||
|
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.warning(
|
||||||
|
"Unable to produce CertificateVerify for " +
|
||||||
|
"signature scheme: " + ss.name);
|
||||||
|
}
|
||||||
|
checkedKeyTypes.add(ss.keyAlgorithm);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLAuthentication ka = X509Authentication.valueOf(ss);
|
||||||
|
if (ka == null) {
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.warning(
|
||||||
|
"Unsupported authentication scheme: " + ss.name);
|
||||||
|
}
|
||||||
|
checkedKeyTypes.add(ss.keyAlgorithm);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLPossession pos = ka.createPossession(hc);
|
||||||
|
if (pos == null) {
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.warning(
|
||||||
|
"Unavailable authentication scheme: " + ss.name);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
|
SSLLogger.warning("No available authentication scheme");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,6 +43,7 @@ import java.util.Queue;
|
|||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.net.ssl.SNIServerName;
|
import javax.net.ssl.SNIServerName;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
import javax.security.auth.x500.X500Principal;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
|
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
|
import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
|
||||||
import static sun.security.ssl.SupportedGroupsExtension.NamedGroupType.*;
|
import static sun.security.ssl.SupportedGroupsExtension.NamedGroupType.*;
|
||||||
@ -136,6 +137,9 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
List<SignatureScheme> peerRequestedSignatureSchemes;
|
List<SignatureScheme> peerRequestedSignatureSchemes;
|
||||||
List<SignatureScheme> peerRequestedCertSignSchemes;
|
List<SignatureScheme> peerRequestedCertSignSchemes;
|
||||||
|
|
||||||
|
// Known authorities
|
||||||
|
X500Principal[] peerSupportedAuthorities = null;
|
||||||
|
|
||||||
// SupportedGroups
|
// SupportedGroups
|
||||||
List<NamedGroup> clientRequestedNamedGroups;
|
List<NamedGroup> clientRequestedNamedGroups;
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ enum X509Authentication implements SSLAuthentication {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by TLS 1.3 only.
|
// Used by TLS 1.2 and TLS 1.3.
|
||||||
private SSLPossession createClientPossession(
|
private SSLPossession createClientPossession(
|
||||||
ClientHandshakeContext chc, String keyType) {
|
ClientHandshakeContext chc, String keyType) {
|
||||||
X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
|
X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
|
||||||
@ -178,11 +178,13 @@ enum X509Authentication implements SSLAuthentication {
|
|||||||
if (chc.conContext.transport instanceof SSLSocketImpl) {
|
if (chc.conContext.transport instanceof SSLSocketImpl) {
|
||||||
clientAlias = km.chooseClientAlias(
|
clientAlias = km.chooseClientAlias(
|
||||||
new String[] { keyType },
|
new String[] { keyType },
|
||||||
null, (SSLSocket)chc.conContext.transport);
|
chc.peerSupportedAuthorities,
|
||||||
|
(SSLSocket)chc.conContext.transport);
|
||||||
} else if (chc.conContext.transport instanceof SSLEngineImpl) {
|
} else if (chc.conContext.transport instanceof SSLEngineImpl) {
|
||||||
clientAlias = km.chooseEngineClientAlias(
|
clientAlias = km.chooseEngineClientAlias(
|
||||||
new String[] { keyType },
|
new String[] { keyType },
|
||||||
null, (SSLEngine)chc.conContext.transport);
|
chc.peerSupportedAuthorities,
|
||||||
|
(SSLEngine)chc.conContext.transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientAlias == null) {
|
if (clientAlias == null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user