Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8217610

TLSv1.3 fail with ClassException when EC keys are stored in PKCS11

XMLWordPrintable

    • b16
    • x86
    • os_x

        ADDITIONAL SYSTEM INFORMATION :
        Mac OS 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 NSS or SoftHSM as PKCS11 module containing an EC server key, client cannot connect with any protocol.



        REGRESSION : Last worked in version 8u192

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

        run the server with
        java -Djava.security.properties=file:////tmp/java-nss.security -Djava.security.debug=sunpkcs11 -cp . TLSServer

        contents of java-nss.security:
        security.provider.14=SunPKCS11 /Users/fabiop/src/tmp/nss.conf

        contents of 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


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Connection is established successfully
        ACTUAL -
        Server throws:

        java.lang.ClassCastException: class sun.security.pkcs11.P11Key$P11PrivateKey cannot be cast to class java.security.interfaces.ECPrivateKey (sun.security.pkcs11.P11Key$P11PrivateKey is in module jdk.crypto.cryptoki of loader 'platform'; java.security.interfaces.ECPrivateKey is in module java.base of loader 'bootstrap')
        at java.base/sun.security.ssl.SignatureScheme.getPreferableAlgorithm(SignatureScheme.java:436)
        at java.base/sun.security.ssl.CertificateVerify$T13CertificateVerifyMessage.<init>(CertificateVerify.java:867)
        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)

        ---------- 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();
                    }
                }
            }
        }
        ---------- END SOURCE ----------

        FREQUENCY : always


              xuelei Xuelei Fan
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: