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

KeyStore.load() throws an IOException with a wrong cause in case of wrong password

    Details

      Backports

        Description

        According to [1], KeyStore.load(InputStream, char[]) method should throw an IOException, and the cause of the IOException should be an UnrecoverableKeyException:

        ...
        Throws:
        IOException - if there is an I/O or format problem with the keystore data, if a password is required but not given, or if the given password was incorrect. If the error is due to a wrong password, the cause of the IOException should be an UnrecoverableKeyException
        ...

        But in case of PKCS11 keystore it throws an IOException, and the cause is javax.security.auth.login.FailedLoginException:

        java.io.IOException: load failed
        at sun.security.pkcs11.P11KeyStore.engineLoad(P11KeyStore.java:761)
        at java.security.KeyStore.load(KeyStore.java:1459)
        at LoadKeystore.main(LoadKeystore.java:73)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:504)
        at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:92)
        at java.lang.Thread.run(Thread.java:746)
        Caused by: javax.security.auth.login.FailedLoginException
        at sun.security.pkcs11.SunPKCS11.login(SunPKCS11.java:1253)
        at sun.security.pkcs11.P11KeyStore.login(P11KeyStore.java:847)
        at sun.security.pkcs11.P11KeyStore.engineLoad(P11KeyStore.java:751)
        ... 8 more
        Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_PIN_INCORRECT
        at sun.security.pkcs11.wrapper.PKCS11.C_Login(Native Method)
        at sun.security.pkcs11.SunPKCS11.login(SunPKCS11.java:1241)
        ... 10 more

        Please use attached LoadKeystore.java test to reproduce the problem.

        The implementation should follow the spec in all cases. Need to check other keystore types listed in [2].

        [1] http://docs.oracle.com/javase/8/docs/api/java/security/KeyStore.html#load-java.io.InputStream-char:A-
        [2] http://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore

          Issue Links

            Activity

            Hide
            asmotrak Artem Smotrakov added a comment -
            sun.security.pkcs11.P11KeyStore uses JAAS framework for authentication. P11KeyStore.engineLoad() method wraps a LoginException into an IOException:

            http://hg.openjdk.java.net/jdk9/dev/jdk/file/d99c2ffdd0f1/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java#l730

            ...
                public synchronized void engineLoad(InputStream stream, char[] password)
                    throws IOException, NoSuchAlgorithmException, CertificateException {

                    ...

                    try {
                        if (password == null) {
                            login(null);
                        } else {
                            login(new PasswordCallbackHandler(password));
                        }
                       
                        ...

                    } catch (LoginException | KeyStoreException | PKCS11Exception e) {
                        throw new IOException("load failed", e);
                    }
                }
            ...

            To make it follow the spec, it can be fixed with the following patch:

            diff -r d99c2ffdd0f1 src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java
            --- a/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java Thu Aug 20 12:29:24 2015 -0700
            +++ b/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java Fri Aug 21 09:38:00 2015 -0700
            @@ -1,5 +1,5 @@
             /*
            - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
            + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
              * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
              *
              * This code is free software; you can redistribute it and/or modify it
            @@ -62,6 +62,7 @@
             import javax.security.auth.callback.PasswordCallback;
             import javax.security.auth.callback.CallbackHandler;
             import javax.security.auth.callback.UnsupportedCallbackException;
            +import javax.security.auth.login.FailedLoginException;
             
             import sun.security.util.Debug;
             import sun.security.util.DerValue;
            @@ -750,6 +751,21 @@
                         } else {
                             login(new PasswordCallbackHandler(password));
                         }
            + } catch(LoginException e) {
            + Throwable cause = e.getCause();
            + if (cause instanceof PKCS11Exception) {
            + PKCS11Exception pe = (PKCS11Exception) cause;
            + if (pe.getErrorCode() == CKR_PIN_INCORRECT) {
            + // if password is wrong, the cause of the IOException
            + // should be an UnrecoverableKeyException
            + throw new IOException("load failed",
            + new UnrecoverableKeyException().initCause(e));
            + }
            + }
            + throw new IOException("load failed", e);
            + }
            +
            + try {
                         if (mapLabels() == true) {
                             // CKA_LABELs are shared by multiple certs
                             writeDisabled = true;
            @@ -757,7 +773,7 @@
                         if (debug != null) {
                             dumpTokenMap();
                         }
            - } catch (LoginException | KeyStoreException | PKCS11Exception e) {
            + } catch (KeyStoreException | PKCS11Exception e) {
                         throw new IOException("load failed", e);
                     }
                 }
            Show
            asmotrak Artem Smotrakov added a comment - sun.security.pkcs11.P11KeyStore uses JAAS framework for authentication. P11KeyStore.engineLoad() method wraps a LoginException into an IOException: http://hg.openjdk.java.net/jdk9/dev/jdk/file/d99c2ffdd0f1/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java#l730 ...     public synchronized void engineLoad(InputStream stream, char[] password)         throws IOException, NoSuchAlgorithmException, CertificateException {         ...         try {             if (password == null) {                 login(null);             } else {                 login(new PasswordCallbackHandler(password));             }                         ...         } catch (LoginException | KeyStoreException | PKCS11Exception e) {             throw new IOException("load failed", e);         }     } ... To make it follow the spec, it can be fixed with the following patch: diff -r d99c2ffdd0f1 src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java --- a/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java Thu Aug 20 12:29:24 2015 -0700 +++ b/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyStore.java Fri Aug 21 09:38:00 2015 -0700 @@ -1,5 +1,5 @@  /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.   *   * This code is free software; you can redistribute it and/or modify it @@ -62,6 +62,7 @@  import javax.security.auth.callback.PasswordCallback;  import javax.security.auth.callback.CallbackHandler;  import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.FailedLoginException;    import sun.security.util.Debug;  import sun.security.util.DerValue; @@ -750,6 +751,21 @@              } else {                  login(new PasswordCallbackHandler(password));              } + } catch(LoginException e) { + Throwable cause = e.getCause(); + if (cause instanceof PKCS11Exception) { + PKCS11Exception pe = (PKCS11Exception) cause; + if (pe.getErrorCode() == CKR_PIN_INCORRECT) { + // if password is wrong, the cause of the IOException + // should be an UnrecoverableKeyException + throw new IOException("load failed", + new UnrecoverableKeyException().initCause(e)); + } + } + throw new IOException("load failed", e); + } + + try {              if (mapLabels() == true) {                  // CKA_LABELs are shared by multiple certs                  writeDisabled = true; @@ -757,7 +773,7 @@              if (debug != null) {                  dumpTokenMap();              } - } catch (LoginException | KeyStoreException | PKCS11Exception e) { + } catch (KeyStoreException | PKCS11Exception e) {              throw new IOException("load failed", e);          }      }
            Hide
            asmotrak Artem Smotrakov added a comment -
            The patch above sets an UnrecoverableKeyException as a cause of IOException only if an error code is CKR_PIN_INCORRECT. I am not sure, but maybe some other error codes should be checked here, see PKCS11Constants.java:

            http://hg.openjdk.java.net/jdk9/dev/jdk/file/d99c2ffdd0f1/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java

            ...
                public static final long CKR_PIN_INCORRECT = 0x000000A0L;
                public static final long CKR_PIN_INVALID = 0x000000A1L;
                public static final long CKR_PIN_LEN_RANGE = 0x000000A2L;

                /* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
                public static final long CKR_PIN_EXPIRED = 0x000000A3L;
                public static final long CKR_PIN_LOCKED = 0x000000A4L;
            ...
            Show
            asmotrak Artem Smotrakov added a comment - The patch above sets an UnrecoverableKeyException as a cause of IOException only if an error code is CKR_PIN_INCORRECT. I am not sure, but maybe some other error codes should be checked here, see PKCS11Constants.java: http://hg.openjdk.java.net/jdk9/dev/jdk/file/d99c2ffdd0f1/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/wrapper/PKCS11Constants.java ...     public static final long CKR_PIN_INCORRECT = 0x000000A0L;     public static final long CKR_PIN_INVALID = 0x000000A1L;     public static final long CKR_PIN_LEN_RANGE = 0x000000A2L;     /* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */     public static final long CKR_PIN_EXPIRED = 0x000000A3L;     public static final long CKR_PIN_LOCKED = 0x000000A4L; ...
            Hide
            asmotrak Artem Smotrakov added a comment -
            JCEKS keystore doesn't use UnrecoverableKeyException as well:

            java.io.IOException: Keystore was tampered with, or password was incorrect
            at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:865)
            at java.security.KeyStore.load(KeyStore.java:1459)
            at LoadKeystore.runTest(LoadKeystore.java:58)
            at LoadKeystore.main(LoadKeystore.java:43)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:504)
            at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:92)
            at java.lang.Thread.run(Thread.java:746)
            Show
            asmotrak Artem Smotrakov added a comment - JCEKS keystore doesn't use UnrecoverableKeyException as well: java.io.IOException: Keystore was tampered with, or password was incorrect at com.sun.crypto.provider.JceKeyStore.engineLoad(JceKeyStore.java:865) at java.security.KeyStore.load(KeyStore.java:1459) at LoadKeystore.runTest(LoadKeystore.java:58) at LoadKeystore.main(LoadKeystore.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:504) at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:92) at java.lang.Thread.run(Thread.java:746)
            Hide
            asmotrak Artem Smotrakov added a comment -
            DKS keystore throws an IOException, and there is an UnrecoverableKeyException in stack trace:

            java.io.IOException: java.security.KeyStoreException: KeyStore instantiation failed
            at sun.security.provider.DomainKeyStore.engineLoad(DomainKeyStore.java:747)
            at sun.security.provider.DomainKeyStore$DKS.engineLoad(DomainKeyStore.java:68)
            at java.security.KeyStore.load(KeyStore.java:1493)
            at DKSTest.main(DKSTest.java:83)
            Caused by: java.security.KeyStoreException: KeyStore instantiation failed
            at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:2109)
            at sun.security.provider.DomainKeyStore.engineLoad(DomainKeyStore.java:739)
            ... 3 more
            Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
            at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780)
            at java.security.KeyStore.load(KeyStore.java:1459)
            at java.security.KeyStore$Builder$FileBuilder$1.run0(KeyStore.java:2098)
            at java.security.KeyStore$Builder$FileBuilder$1.run(KeyStore.java:2042)
            at java.security.KeyStore$Builder$FileBuilder$1.run(KeyStore.java:2039)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:2105)
            ... 4 more
            Caused by: java.security.UnrecoverableKeyException: Password verification failed
            at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:778)
            ... 10 more
            Show
            asmotrak Artem Smotrakov added a comment - DKS keystore throws an IOException, and there is an UnrecoverableKeyException in stack trace: java.io.IOException: java.security.KeyStoreException: KeyStore instantiation failed at sun.security.provider.DomainKeyStore.engineLoad(DomainKeyStore.java:747) at sun.security.provider.DomainKeyStore$DKS.engineLoad(DomainKeyStore.java:68) at java.security.KeyStore.load(KeyStore.java:1493) at DKSTest.main(DKSTest.java:83) Caused by: java.security.KeyStoreException: KeyStore instantiation failed at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:2109) at sun.security.provider.DomainKeyStore.engineLoad(DomainKeyStore.java:739) ... 3 more Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780) at java.security.KeyStore.load(KeyStore.java:1459) at java.security.KeyStore$Builder$FileBuilder$1.run0(KeyStore.java:2098) at java.security.KeyStore$Builder$FileBuilder$1.run(KeyStore.java:2042) at java.security.KeyStore$Builder$FileBuilder$1.run(KeyStore.java:2039) at java.security.AccessController.doPrivileged(Native Method) at java.security.KeyStore$Builder$FileBuilder.getKeyStore(KeyStore.java:2105) ... 4 more Caused by: java.security.UnrecoverableKeyException: Password verification failed at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:778) ... 10 more
            Show
            asmotrak Artem Smotrakov added a comment - Code review: http://mail.openjdk.java.net/pipermail/security-dev/2015-September/012789.html
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/13a89c1302be
            User: asmotrak
            Date: 2015-09-14 16:49:48 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/13a89c1302be User: asmotrak Date: 2015-09-14 16:49:48 +0000
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/13a89c1302be
            User: lana
            Date: 2015-09-23 23:04:33 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/13a89c1302be User: lana Date: 2015-09-23 23:04:33 +0000

              People

              • Assignee:
                asmotrak Artem Smotrakov
                Reporter:
                asmotrak Artem Smotrakov
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: