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

SUN PKCS#11 force a user to login for any access even public access to the smartcard

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Future Project
    • Icon: P3 P3
    • None
    • 6u10
    • security-libs

      There are some issues concerning PKCS#11 support in various JDKs an especially in the most recent JDK 6 Update 10.

      The PKCS#11 standard generally distinguishes between public and user sessions.

      Public session provide access to public objects (e.g. certificates) without the user being logged into the smartcard in question.

      The SUN PKCS#11 support seems to contain a general design bug by forcing a user to login for any access to the smartcard. Such an approach results in various access policies and workflows of real life applications being violated when trying to use the Java KeyStore API for accessing smartcards.

      Example:

      For enumerating the aliases in a KeyStore, the following code snippet could be used:

      KeyStore ks = KeyStore.getInstance("PKCS11", PKCS11.getProvider(0)); ks.load(null, "myPIN".toCharArray()); List<String> aliases = Collections.list(ks.aliases()); for (String alias : aliases) {

         System.out.println(alias);

       }

      However, the above-cited code snippet does not work without any PIN being entered, i.e. without the user being logged in, even if the smartcard would allow such an enumeration during a public session (cf. the subsequent stacktrace when using ks.load(null, null)):

      Exception in thread "main" java.io.IOException: load failed

              at sun.security.pkcs11.P11KeyStore.engineLoad(P11KeyStore.java:754)

              at java.security.KeyStore.load(Unknown Source)

              at test.NoPin.main(NoPin.java:12) Caused by: javax.security.auth.login.LoginException: no password provided, and no callback handler available for retrieving password

              at sun.security.pkcs11.SunPKCS11.login(SunPKCS11.java:1087)

              at sun.security.pkcs11.P11KeyStore.login(P11KeyStore.java:854)

              at sun.security.pkcs11.P11KeyStore.engineLoad(P11KeyStore.java:742)

              ... 2 more

       

      Please eliminate the above-cited design bug in order to provide PKCS#11 KeyStore access using

      CallbackHandlerProtection, which queries the PIN lazily, i.e. when really required by the smartcard in contrast to an early PIN query. Hence, SUN PKCS#11 support would become compatible with standard PKCS#11 access policies.
      The sun.security.pkcs11.SunPCS11 class forces an early login, i.e.
      during Keystore.load(), depending on the PKCS#11 token info flag
      CKF_LOGIN_REQUIRED being set.


      However, the PKCS#11 spec says that this flag means that SOME (but not
      necessarily all) functions require the user to be logged in. We think
      that a misinterpretation of this flag causes the reported bug.


      As a consequence, some scenarios, e.g. enlisting certificates stored on
      a smartcard, do not work without the user being logged in. This is a
      showstopper for various PKI-enabled real life applications.
      All critical functions like C_SignInit or C_DigestInit have a special return code called "CKR_USER_NOT_LOGGED_IN" which is returned by the PKCS#11 implementstion if the login on the card would have been required for the execution of the function. Such a return should be treated in a similar way that the CKR_DEVICE_REMOVED.

      Functions looking for objects like for example C_FindObjectsInit, don't have such a return code. However, the PKCS#11 specification define that if no login has occurred, the function shall only return public objects. This is indeed what LuxTrust needs.

      It's not evident to include such a public session management into the JCE/JCA given the diversity of possible tokens and vendors. We thus think that the application developer should have the possibility to define if a login on the card is required or not.

      KeyStore ks = KeyStore.getInstance("PKCS11", PKCS11.getProvider(0)); ks.load(null, null); // no login on token necessary
      List<String> aliases = Collections.list(ks.aliases()); // only alias of public objects are returned if no login as occurred
      for (String alias : aliases)
      {
      ....
      }

            valeriep Valerie Peng
            tyao Ting-Yun Ingrid Yao (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: