JDK-8217611 : PKCS11 module unable to negotiate TLSv1.3 with RSASSA-PSS
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.crypto:pkcs11
  • Affected Version: 11.0.1
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86_64
  • Submitted: 2019-01-21
  • Updated: 2023-12-12
  • Resolved: 2019-06-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 13
13Resolved
Related Reports
Duplicate :  
Description
ADDITIONAL SYSTEM INFORMATION :
MacOS X 10.11, but also CentOS 7.
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)

A DESCRIPTION OF THE PROBLEM :
Using a PKCS11 module like NSS or SoftHSM to store keys, prevents TLSv1.3 clients to connect, while clients using TLSv1.2 succeed.

I noticed as a provider, PKCS11 does not expose RSASSA-PSS as SunRsaSign does, that is
	Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1.10	RSASSA-PSS
	Alg.Alias.Signature.OID.1.2.840.113549.1.1.10	RSASSA-PSS
	KeyFactory.RSASSA-PSS	sun.security.rsa.RSAKeyFactory$PSS
	Signature.RSASSA-PSS SupportedKeyClasses	java.security.interfaces.RSAPublicKey|java.security.interfaces.RSAPrivateKey
	Alg.Alias.AlgorithmParameters.1.2.840.113549.1.1.10	RSASSA-PSS
	Alg.Alias.KeyFactory.OID.1.2.840.113549.1.1.10	RSASSA-PSS
	Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.10	RSASSA-PSS
	KeyPairGenerator.RSASSA-PSS	sun.security.rsa.RSAKeyPairGenerator$PSS
	Signature.RSASSA-PSS	sun.security.rsa.RSAPSSSignature
	AlgorithmParameters.RSASSA-PSS	sun.security.rsa.PSSParameters
	Alg.Alias.AlgorithmParameters.OID.1.2.840.113549.1.1.10	RSASSA-PSS
	Alg.Alias.Signature.1.2.840.113549.1.1.10	RSASSA-PSS
	Alg.Alias.KeyFactory.1.2.840.113549.1.1.10	RSASSA-PSS
is missing from all SunPKCS11 providers

REGRESSION : Last worked in version 8u192

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
To reproduce, I used a modified version of the HTTPSServer from
https://www.pixelstech.net/article/1445603357-A-HTTPS-client-and-HTTPS-server-demo-in-Java, to use PKCS11 instead of JKS as key store.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Successfully established client session.
ACTUAL -
When a TLSv1.3 client tries to connect, the following stack trace is thrown server side:

javax.net.ssl.SSLHandshakeException: Cannot produce CertificateVerify signature
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:321)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
	at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:905)
	at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.onProduceCertificateVerify(CertificateVerify.java:1077)
	at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyProducer.produce(CertificateVerify.java:1070)
	at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
	at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1224)
	at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1160)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:849)
	at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:444)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
	at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:178)
	at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
	at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1152)
	at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1063)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
	at TLSServer$ServerThread.run(TLSServer.java:92)
Caused by: java.security.InvalidKeyException: No installed provider supports this key: sun.security.pkcs11.P11Key$P11PrivateKey
	at java.base/java.security.Signature$Delegate.chooseProvider(Signature.java:1163)
	at java.base/java.security.Signature$Delegate.engineInitSign(Signature.java:1204)
	at java.base/java.security.Signature.initSign(Signature.java:546)
	at java.base/sun.security.ssl.SignatureScheme.getSignature(SignatureScheme.java:473)
	at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:895)
	... 16 more


---------- BEGIN SOURCE ----------
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

class TLSServer {
    private int port = 8080;
    private boolean isServerDone = false;

    public static void main(String[] args){
        TLSServer server = new TLSServer();
        server.run();
    }

    TLSServer(){
    }

    // Create the and initialize the SSLContext
    private SSLContext createSSLContext(){
        try{
            KeyStore keyStore = KeyStore.getInstance("PKCS11");
            keyStore.load(null,"password".toCharArray());
            System.out.println("Keystore provider : " + keyStore.getProvider());
            // Create key manager
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, "password".toCharArray());
            KeyManager[] km = keyManagerFactory.getKeyManagers();

            // Create trust manager
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] tm = trustManagerFactory.getTrustManagers();

            // Initialize SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(km,  tm, null);

            return sslContext;
        } catch (Exception ex){
            ex.printStackTrace();
        }

        return null;
    }

    // Start to run the server
    public void run(){
        SSLContext sslContext = this.createSSLContext();

        try{
            // Create server socket factory
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();

            // Create server socket
            SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(this.port);

            System.out.println("SSL server started");
            while(!isServerDone){
                SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();

                // Start the server thread
                new ServerThread(sslSocket).start();
            }
        } catch (Exception ex){
            ex.printStackTrace();
        }
    }

    // Thread handling the socket from client
    static class ServerThread extends Thread {
        private SSLSocket sslSocket = null;

        ServerThread(SSLSocket sslSocket){
            this.sslSocket = sslSocket;
        }

        public void run(){
            sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());

            try{
                // Start handshake
                sslSocket.startHandshake();

                // Get session after the connection is established
                SSLSession sslSession = sslSocket.getSession();

                System.out.println("SSLSession :");
                System.out.println("\tProtocol : "+sslSession.getProtocol());
                System.out.println("\tCipher suite : "+sslSession.getCipherSuite());

                // Start handling application content
                InputStream inputStream = sslSocket.getInputStream();

                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

                String line = null;
                while((line = bufferedReader.readLine()) != null){
                    System.out.println("Input : "+line);

                    if(line.trim().isEmpty()){
                        break;
                    }
                }

                sslSocket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

run with java -D -Djava.security.properties=/path/to/java-security-nss.conf,
which contains 
security.provider.14=SunPKCS11 /tmp/nss.conf

/tmp/nss.conf :
name = NSScrypto
nssLibraryDirectory = /tmp/nss-3.41/dist/Darwin15.6.0_cc_64_OPT.OBJ/lib
nssSecmodDirectory = sql:/tmp/nss-3.41/dist/Darwin15.6.0_cc_64_OPT.OBJ
---------- END SOURCE ----------

FREQUENCY : always



Comments
JDK-8080462
12-06-2019

Closing this as duplicate of JDK-8080462 which adds the support for RSASSA-PSS signature.
12-06-2019

SunPKCS11 provider currently does not support RSASSA-PSS yet. It should be included as part of JDK-8080462 which is targeted to JDK 13.
23-01-2019