1 2 Previous Next 23 Replies Latest reply: Sep 13, 2011 5:01 PM by 888044 RSS

    Socket.startHandshake with PKCS11 token

    user10878887
      Hello
      I have 2 pkcs11 tokens(a Oberthur and a Gemalto).
      Oberthur works fine but Gemalto gives the following error
      javax.net.ssl.SSLException: Received fatal alert: illegal_parameter
      at the line "socket.startHandshake()".


      Both tokens are working fine - I can sign files from java using them .

      This is the code. I put a lot of debug information hoping I will find the cause. All println lines print the exact same thing for both tokens.

      keystorePkcs11 = KeyStore.getInstance("pkcs11");
      keystorePkcs11.load(null, PASSWORD_PKCS11);

      kKeyManagerFactory = KeyManagerFactory.getInstance("sunx509");
      kKeyManagerFactory.init(keystorePkcs11, PASSWORD_PKCS11);
      System.out.println("getAlgorithm>>>" + kKeyManagerFactory.getAlgorithm());
      System.out.println("get provider get info>>>" + kKeyManagerFactory.getProvider().getInfo());
      System.out.println("get provider get name>>>" + kKeyManagerFactory.getProvider().getName());

      SSLContext context = SSLContext.getInstance("TLS");
      context.init(kKeyManagerFactory.getKeyManagers(), null, null);

      factory = context.getSocketFactory();
      socket = (SSLSocket)factory.createSocket("www.siui.ro", 443);

      System.out.println("getCipherSuites>>>" + Arrays.toString(socket.getSSLParameters().getCipherSuites()));
      System.out.println("getNeedClientAuth>>>" + socket.getSSLParameters().getNeedClientAuth());
      System.out.println("getProtocols>>>" + Arrays.toString(socket.getSSLParameters().getProtocols()));
      System.out.println("getWantClientAuth>>>" + socket.getSSLParameters().getWantClientAuth());

      socket.startHandshake(); // here is the problem

      This is the output:
      getAlgorithm>>>sunx509

      get provider get info>>>Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)

      get provider get name>>>SunJSSE

      getCipherSuites>>>[SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]

      getNeedClientAuth>>>false

      getProtocols>>>[SSLv2Hello, SSLv3, TLSv1]

      getWantClientAuth>>>false

      javax.net.ssl.SSLException: Received fatal alert: illegal_parameter
           at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190)
           at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
           at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
           at client.Client.connect_tls(Client.java:119)
           at main_class.jButton1ActionPerformed(main_class.java:295)
           at main_class.access$500(main_class.java:26)
           at main_class$6.actionPerformed(main_class.java:152)
           at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
           at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
           at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
           at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
           at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
           at java.awt.Component.processMouseEvent(Component.java:6288)
           at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
           at java.awt.Component.processEvent(Component.java:6053)
           at java.awt.Container.processEvent(Container.java:2041)
           at java.awt.Component.dispatchEventImpl(Component.java:4651)
           at java.awt.Container.dispatchEventImpl(Container.java:2099)
           at java.awt.Component.dispatchEvent(Component.java:4481)
           at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4577)
           at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
           at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
           at java.awt.Container.dispatchEventImpl(Container.java:2085)
           at java.awt.Window.dispatchEventImpl(Window.java:2478)
           at java.awt.Component.dispatchEvent(Component.java:4481)
           at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:643)
           at java.awt.EventQueue.access$000(EventQueue.java:84)
           at java.awt.EventQueue$1.run(EventQueue.java:602)
           at java.awt.EventQueue$1.run(EventQueue.java:600)
           at java.security.AccessController.doPrivileged(Native Method)
           at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
           at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
           at java.awt.EventQueue$2.run(EventQueue.java:616)
           at java.awt.EventQueue$2.run(EventQueue.java:614)
           at java.security.AccessController.doPrivileged(Native Method)
           at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
           at java.awt.EventQueue.dispatchEvent(EventQueue.java:613)
           at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
           at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
           at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
           at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
           at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
           at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)


      Thank you.
        • 1. Re: Socket.startHandshake with PKCS11 token
          830591
          Would you please enable the JSSE debug log (JVM option "-Djavax.net.debug=all"), and past the debug log? It seems that Gemalto run into cryptographic operation issues. What are the mechanisms (AES, RSA, RC4?) that the tokens support?
          • 2. Re: Socket.startHandshake with PKCS11 token
            user10878887
            The debug is too big to fit on this forum but I posted it here
            http://www.casnt.ro/out.gemalto

            I started testing with java wrapper for Microsoft CAPI but I didn't fix it yet.
            I still hope there is a simple solution to this.

            This are the cipher suites that the token Gemalto knows. They are identical with Oberthur.

            getCipherSuites>>>[SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
            • 3. Re: Socket.startHandshake with PKCS11 token
              user10878887
              After testing with java wrapper for Microsoft CAPI I get the exact same result (Oberthur works and Gemalto gives "illegal parameter").
              The problem is that I don't know what illegal parameter means and how can I fix it.
              Seems like a generic error.
              • 4. Re: Socket.startHandshake with PKCS11 token
                user10878887
                I foud the error "illegal parameter" listed as a bug here
                http://bugs.sun.com/view_bug.do?bug_id=6998053

                Is it possible this is a java bug?
                • 5. Re: Socket.startHandshake with PKCS11 token
                  EJP
                  That bug concerns SSLv2Hello, OpenSSL in a very old version, and probably Apache server.

                  It is possible that this is a different bug, but I note that your client sent an empty certificate chain in response to the CertificateRequest. If the server is configured with needClientAuth=true, that will cause the handshake to fail anyway.
                  • 6. Re: Socket.startHandshake with PKCS11 token
                    830591
                    It's not a bug of Java. I don't think it is a bug of the smart card according to the log.

                    ---------------
                    Cert Types: RSA
                    Cert Authorities:
                    <CN=MSANATATII CA, O=Ministerul SANATATII, L=Bucuresti, ST=Romania, C=RO>
                    <CN=certSIGN Qualified CA Class 3, OU=certSIGN Qualified CA Class 3, O=certSIGN, C=RO>
                    <CN=DIGISIGN PUBLIC, OU=Digisign Public CA, O=Digisign S.A., C=RO>
                    <CN=TC TrustCenter Class 3 CA II, OU=TC TrustCenter Class 3 CA, O=TC TrustCenter GmbH, C=DE>
                    *** ServerHelloDone
                    *** Certificate chain
                    ***
                    *** ClientKeyExchange, RSA PreMasterSecret, TLSv1
                    ----------------

                    The server request a client certificate, however, the client send a empty certificate chain. I think you may want to check the certificate in the token to make sure:
                    1. there is personal certification stored in the token.
                    2. the certificate is of type RSA
                    3. the certificate is issue by one of the above cert authorities.

                    BTW, please pay attention that the server may be under TLS renegotiation attack. Your client Java RE is safe. For more information please refer to http://www.oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html.

                    Good luck!
                    • 7. Re: Socket.startHandshake with PKCS11 token
                      user10878887
                      Than you both.
                      I understand what is the problem now but I still can't get it to work.

                      1. There is a certificate stored on the token. I can login on the token with COVE user tool and I can see the certificate and is valid until 2012.
                      2. The "*signature algorithm*" is sha1RSA.
                      3. I can see the certificate path from IE.
                      The certificate path is TC TrustCenter Class 3 CA II / Trans Sped Qualified CA II /Maricica Timaru

                      In the debug log I have "*TC TrustCenter Class 3 CA II*" as a trusted certificate authority, but I don't have "*Trans Sped Qualified CA II*" as a trusted authority.
                      Can this be a problem? I downloaded the certificate for "*Trans Sped Qualified CA II*" and I installed it on my system but the chain is still empty in my debug log.

                      I also checked the existence of a certificate like this:
                      keystorePkcs11 = KeyStore.getInstance("pkcs11");
                      keystorePkcs11.load(null, PASSWORD_PKCS11);
                      java.util.Enumeration en = keystorePkcs11.aliases() ;
                      while (en.hasMoreElements()) {
                      String aliasKey = (String)en.nextElement() ;
                      System.out.println("---> FOUND alias : " + aliasKey);
                      }
                      The result is "*---> FOUND alias : Maricica Timaru's Trans Sped SRL ID*"

                      I also add these lines to my code, but the problem is the same - empty certificate chain:
                      System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
                      System.setProperty("sun.security.ssl.allowLegacyHelloMessages", "true");

                      I'm probably missing something very simple but I have no ideea what it is.

                      Thank you.
                      • 8. Re: Socket.startHandshake with PKCS11 token
                        EJP
                        2. The "signature algorithm" is sha1RSA.
                        I'm not sure that matches what the server has specified.
                        The certificate path is TC TrustCenter Class 3 CA II / Trans Sped Qualified CA II /Maricica Timaru

                        In the debug log I have "*TC TrustCenter Class 3 CA II*" as a trusted certificate authority, but I don't have "*Trans Sped Qualified CA II*" as a trusted authority.
                        No. As long as you have either of them it is OK.
                        • 9. Re: Socket.startHandshake with PKCS11 token
                          user10878887
                          I foud a great documentation about debugging SSL here [http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/ReadDebug.html] and I applied it to my debug log.

                          This is the client hello from the debug:

                          *** ClientHello, TLSv1
                          Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
                          Compression Methods: { 0 }

                          And this is the server hello where the server selects chiper suite "*SSL_RSA_WITH_3DES_EDE_CBC_SHA*" from the client available chipers.
                          *** ServerHello, TLSv1
                          Cipher Suite: SSL_RSA_WITH_3DES_EDE_CBC_SHA
                          Compression Method: 0

                          Next I should find in the debug log a line like this: "*matching alias: <my name>*". But this line is missing.
                          No alias is found or no alias is matching. I guess no alias is matching because there is a alias on the token.
                          But why?
                          I think is somethig wrong with the certificate chain but I don't know how to fix it.

                          This is the code:

                          keystorePkcs11 = KeyStore.getInstance("pkcs11");
                          keystorePkcs11.load(null, PASSWORD_PKCS11);
                          kKeyManagerFactory = KeyManagerFactory.getInstance("sunx509");
                          kKeyManagerFactory.init(keystorePkcs11, PASSWORD_PKCS11);
                          SSLContext context = SSLContext.getInstance("TLS");
                          context.init(kKeyManagerFactory.getKeyManagers(), null, null);
                          factory = context.getSocketFactory();
                          socket = (SSLSocket)factory.createSocket("www.siui.ro", 443);
                          socket.startHandshake();


                          Thank you.
                          • 10. Re: Socket.startHandshake with PKCS11 token
                            user10878887
                            I guess I should use TrustManagerFactory class and pass an extra argument to init procedure from SSLContext.
                            Like this: context.init(kKeyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
                            But how do I add to the TrustManagerFactory the missing chain?

                            I tryed this:
                            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
                            tmf.init(keystorePkcs11);

                            But now I can't check the server certificate and the exception is
                            "javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found"
                            • 11. Re: Socket.startHandshake with PKCS11 token
                              user10878887
                              I tryed something else and I got a new error(I think this may be the source of the problem):
                              "Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID".
                              But I found almost nothing about this error searching on the net.

                              This is the code:
                              keystorePkcs11 = KeyStore.getInstance("pkcs11");
                              keystorePkcs11.load(null, PASSWORD_PKCS11);
                              String aliasKey = (String)keystorePkcs11.aliases().nextElement(); //there is only one alias on the token
                              Certificate c = keystorePkcs11.getCertificate(aliasKey);
                              c.verify(c.getPublicKey(), keystorePkcs11.getProvider().getName()); // here I get the new exception

                              java.security.ProviderException: Initialization failed
                                   at sun.security.pkcs11.P11Signature.initialize(P11Signature.java:294)
                                   at sun.security.pkcs11.P11Signature.engineInitVerify(P11Signature.java:353)
                                   at java.security.Signature$Delegate.engineInitVerify(Signature.java:1086)
                              .............
                              Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_MECHANISM_INVALID
                                   at sun.security.pkcs11.wrapper.PKCS11.C_VerifyInit(Native Method)
                                   at sun.security.pkcs11.P11Signature.initialize(P11Signature.java:289)
                              • 12. Re: Socket.startHandshake with PKCS11 token
                                user10878887
                                I checked all the cipher suites supported by the client - they are listed at the end of my post and I tryed to create the socket with only one chiper activated like this:

                                String[] ssuites = new String[1];
                                ssuites[0]="SSL_RSA_WITH_RC4_128_MD5"; // I changed the chipper with this variable
                                socket.setEnabledCipherSuites(ssuites);
                                socket.startHandshake();

                                All attempts to create the socket ended with error, most of the errors are "*handshake failure*".
                                There were 2 errors "*illegal parameter*" when I set the chiper to "*SSL_RSA_WITH_3DES_EDE_CBC_SHA*" and "*TLS_RSA_WITH_AES_128_CBC_SHA*".
                                This probably means that the server only knows these 2 chiper suites from the presented list.
                                So my problem remains how to fix "*illegal parameter*" caused by the empty certificate chain send by the client in response to the CertificateRequest.
                                However I can't see why the client doesn't send the certificate chain since everything seems to be alright.

                                Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
                                • 13. Re: Socket.startHandshake with PKCS11 token
                                  830591
                                  1. There is a certificate stored on the token.
                                  It's fine.
                                  2. The "signature algorithm" is sha1RSA.
                                  We normally need the public key algorithm here, rather than the signature algorithm in the cert.

                                  From the log, http://www.casnt.ro/out.gemalto, I can see the key algorithm is "RSA". So, it's fine again.
                                  3. I can see the certificate path from IE.
                                  It does not make sense. You use the smart card token as the key store. IE has no connect with the smart card.

                                  Again, from the log, I can only find one cert:
                                  Subject: CN=Maricica Timaru, SURNAME=Timaru, GIVENNAME=Maricica, OU=Functia: Administrator, O=Farmacia Mara S.R.L., C=RO
                                  Issuer: CN=Trans Sped Qualified CA II, OU=Individual Subscriber CA, O=Trans Sped SRL, C=RO

                                  The issuer of the certificate is not trusted by the server, i.e., it is not in the list of server required Cert Authorities.

                                  If you believe that the certificate can be chained to <CN=TC TrustCenter Class 3 CA II, OU=TC TrustCenter Class 3 CA, O=TC TrustCenter GmbH, C=DE>. It's clear that the smart card certificate cannot be act as a complete certification path, it cannot be chained to <CN=TC TrustCenter Class 3 CA II, OU=TC TrustCenter Class 3 CA, O=TC TrustCenter GmbH, C=DE>, the trusted cert.

                                  I think if you check the other workable smart card, you should be able to find a complete certification path to a trusted anchor.

                                  To solve the issue, you may need to import the intermediate certificates between the smart card cert (CN=Maricica Timaru ...) and the trusted cert (CN=TC TrustCenter ...) into the smart card. Or contact your smart card provider. Otherwise, there is no way to find the complete certification path to the server trusted issuers.

                                  Other tries you made do not make sense to solve the issue, some of them even are not reasonable.

                                  Good luck!
                                  • 14. Re: Socket.startHandshake with PKCS11 token
                                    user10878887
                                    827588 wrote:

                                    To solve the issue, you may need to import the intermediate certificates between the smart card cert (CN=Maricica Timaru ...) and the trusted cert (CN=TC TrustCenter ...) into the smart card. Or contact your smart card provider. Otherwise, there is no way to find the complete certification path to the server trusted issuers.
                                    It must be another solution. I write this because I made a test with another application made in visual basic that creates the socket successfully.
                                    It it strange that the "Issuer name" from the token it is not found in the certification path from IE. I will contact the provider for this issue.

                                    It must be possible to add the missing chain at run time. But how? Is this correct?
                                    3. I can see the certificate path from IE.
                                    It does not make sense. You use the smart card token as the key store. IE has no connect with the smart card.
                                    All my certificates from the tokens are installed in IE and I can find them there.
                                    You are right, I shouldn't look in IE while I use "*KeyStore.getInstance("pkcs11")*".
                                    Maybe when I use "*KeyStore.getInstance("Windows-MY")*" this would have meaning.

                                    >
                                    Again, from the log, I can only find one cert:
                                    Subject: CN=Maricica Timaru, SURNAME=Timaru, GIVENNAME=Maricica, OU=Functia: Administrator, O=Farmacia Mara S.R.L., C=RO
                                    Issuer: CN=Trans Sped Qualified CA II, OU=Individual Subscriber CA, O=Trans Sped SRL, C=RO

                                    The issuer of the certificate is not trusted by the server, i.e., it is not in the list of server required Cert Authorities.

                                    If you believe that the certificate can be chained to <CN=TC TrustCenter Class 3 CA II, OU=TC TrustCenter Class 3 CA, O=TC TrustCenter GmbH, C=DE>. It's clear that the smart card certificate cannot be act as a complete certification path, it cannot be chained to <CN=TC TrustCenter Class 3 CA II, OU=TC TrustCenter Class 3 CA, O=TC TrustCenter GmbH, C=DE>, the trusted cert.

                                    I think if you check the other workable smart card, you should be able to find a complete certification path to a trusted anchor.
                                    Yes, I can find a complete certification path with my working token - Oberthur.
                                    1 2 Previous Next