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
@ -31,7 +31,9 @@ import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -675,45 +677,86 @@ final class CertificateRequest {
|
||||
chc.peerRequestedSignatureSchemes = sss;
|
||||
chc.peerRequestedCertSignSchemes = sss; // use the same schemes
|
||||
chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
|
||||
chc.peerSupportedAuthorities = crm.getAuthorities();
|
||||
|
||||
X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
|
||||
String clientAlias = null;
|
||||
if (chc.conContext.transport instanceof SSLSocketImpl) {
|
||||
clientAlias = km.chooseClientAlias(crm.getKeyTypes(),
|
||||
crm.getAuthorities(), (SSLSocket)chc.conContext.transport);
|
||||
} else if (chc.conContext.transport instanceof SSLEngineImpl) {
|
||||
clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),
|
||||
crm.getAuthorities(), (SSLEngine)chc.conContext.transport);
|
||||
}
|
||||
|
||||
if (clientAlias == null) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.warning("No available client authentication");
|
||||
}
|
||||
// For TLS 1.2, we no longer use the certificate_types field
|
||||
// from the CertificateRequest message to directly determine
|
||||
// the SSLPossession. Instead, the choosePossession method
|
||||
// will use the accepted signature schemes in the message to
|
||||
// determine the set of acceptable certificate types to select from.
|
||||
SSLPossession pos = choosePossession(chc);
|
||||
if (pos == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
|
||||
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.handshakePossessions.add(pos);
|
||||
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
|
||||
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.net.ssl.SNIServerName;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
|
||||
import 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> peerRequestedCertSignSchemes;
|
||||
|
||||
// Known authorities
|
||||
X500Principal[] peerSupportedAuthorities = null;
|
||||
|
||||
// SupportedGroups
|
||||
List<NamedGroup> clientRequestedNamedGroups;
|
||||
|
||||
|
@ -170,7 +170,7 @@ enum X509Authentication implements SSLAuthentication {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Used by TLS 1.3 only.
|
||||
// Used by TLS 1.2 and TLS 1.3.
|
||||
private SSLPossession createClientPossession(
|
||||
ClientHandshakeContext chc, String keyType) {
|
||||
X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
|
||||
@ -178,11 +178,13 @@ enum X509Authentication implements SSLAuthentication {
|
||||
if (chc.conContext.transport instanceof SSLSocketImpl) {
|
||||
clientAlias = km.chooseClientAlias(
|
||||
new String[] { keyType },
|
||||
null, (SSLSocket)chc.conContext.transport);
|
||||
chc.peerSupportedAuthorities,
|
||||
(SSLSocket)chc.conContext.transport);
|
||||
} else if (chc.conContext.transport instanceof SSLEngineImpl) {
|
||||
clientAlias = km.chooseEngineClientAlias(
|
||||
new String[] { keyType },
|
||||
null, (SSLEngine)chc.conContext.transport);
|
||||
chc.peerSupportedAuthorities,
|
||||
(SSLEngine)chc.conContext.transport);
|
||||
}
|
||||
|
||||
if (clientAlias == null) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user