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

PKCS11: Invalid SecretKey key size in SecretKey.toString() implementation

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.8.0_65"
      Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Linux secomo 2.6.32-573.7.1.el6.x86_64 #1 SMP Tue Sep 22 22:00:00 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
      CentOS release 6.7 (Final)

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      For the test case, I used an Utimaco CryptoServer HSM. However, any PKCS11 provider can be used to execute the test case.

      A DESCRIPTION OF THE PROBLEM :
       Executing SecretKey.toString() for an instance that represents an HMAC-SHA256 with a length of 32 bytes returns the following output:

        SunPKCS11-CryptoServer Generic Secret secret key, 32 bits (id 3, token object, sensitive, unextractable)

      The output indicates a length of 32 bits. However, the key has a length of 256 bits. The PKCS11 attributes are as follows:

      CKA_CLASS: CKO_SECRET_KEY
      CKA_LABEL: test
      CKA_ID: test
      CKA_TOKEN: CK_TRUE
      CKA_PRIVATE: CK_TRUE
      CKA_MODIFIABLE: CK_TRUE
      CKA_KEY_TYPE: CKK_GENERIC_SECRET
      CKA_DERIVE: CK_FALSE
      CKA_LOCAL: CK_TRUE
      CKA_ENCRYPT: CK_FALSE
      CKA_VERIFY: CK_TRUE
      CKA_VERIFY_RECOVER: CK_FALSE
      CKA_WRAP: CK_TRUE
      CKA_TRUSTED: CK_FALSE
      CKA_DECRYPT: CK_FALSE
      CKA_SIGN: CK_TRUE
      CKA_WRAP_WITH_TRUSTED: CK_FALSE
      CKA_UNWRAP: CK_TRUE
      CKA_SENSITIVE: CK_FALSE
      CKA_ALWAYS_SENSITIVE: CK_FALSE
      CKA_EXTRACTABLE: CK_TRUE
      CKA_NEVER_EXTRACTABLE: CK_FALSE
      CKA_CHECK_VALUE: 3 bytes (24 bits)
       14 e0 db
      CKA_VALUE: 32 bytes (256 bits)
       85 c0 9d 06 f3 bb 49 19 2b 44 3a 9e 33 e9 fd 86
       70 d4 db 4d 51 02 28 6e 7e ec dc f5 56 31 bc 79

      The return value should indicate the correct length of 32 bits.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      SunPKCS11 provider = new SunPKCS11(/* config */);
      TestCallbackHandler handler = new TestCallbackHandler(pin);
      provider.login(null, /* callback handler */);
      KeyStore keystore = KeyStore.Builder.newInstance("PKCS11", provider, new KeyStore.CallbackHandlerProtection(handler)).getKeyStore();

      Key key = keystore.getKey(/* key label */, null);
      System.out.println(key);

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      SunPKCS11-CryptoServer Generic Secret secret key, 256 bits (id 3, token object, sensitive, unextractable)
      ACTUAL -
      SunPKCS11-CryptoServer Generic Secret secret key, 32 bits (id 3, token object, sensitive, unextractable)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      The following test case assumes an Utimaco CryptoServer HSM. However, the provider initialization can be changed to work with any PKCS11 implementation.

      java Test <pkcs11-pin> <pkcs11-key-label>

      import java.io.*;
      import java.security.*;
      import java.util.*;
      import javax.security.auth.callback.*;
      import javax.crypto.*;
      import sun.security.pkcs11.*;

      public class Test
      {
        public static void main(String[] args) throws Exception
        {
          String pin = args[0];
          String label = args[1];
          Properties props = new Properties();
          props.put("PKCS11_NATIVE_MODULE", "/usr/lib64/libcs_pkcs11_R2.so");
          props.put("USE_UTF8_ENCODING", "true");
          props.put("CHECK_MECHANISM_SUPPORTED", "true");
          props.put("USER_PIN", pin);
          String config = "name = CryptoServer\n" +
                          "library = /usr/lib64/libcs_pkcs11_R2.so\n" +
                          "slotListIndex = 0\n";
          InputStream in = new ByteArrayInputStream(config.getBytes("UTF-8"));
          SunPKCS11 provider = new SunPKCS11(in);
          TestCallbackHandler handler = new TestCallbackHandler(pin);
          provider.login(null, handler);
          Security.addProvider(provider);
          KeyStore keystore = KeyStore.Builder.newInstance("PKCS11", provider, new KeyStore.CallbackHandlerProtection(handler)).getKeyStore();
          Key key = keystore.getKey(label, null);
          System.out.println(key);
        }
      }

      class TestCallbackHandler implements CallbackHandler
      {
        private String pin;

        public TestCallbackHandler(String pin)
        {
          this.pin = pin;
        }

        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
          for (int i = 0; i < callbacks.length; i++) {
            PasswordCallback pwcb = (PasswordCallback)callbacks[i];
            pwcb.setPassword(pin.toCharArray());
          }
        }
      }
      ---------- END SOURCE ----------

            coffeys Sean Coffey
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: