# NitrokeyHSM and Java Sun PKCS#11

**URL:** https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812
**Category:** Nitrokeys
**Created:** [December 19, 2017, 5:07pm UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812 "2017-12-19T17:07:32Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![nmadden](https://support.nitrokey.com/letter_avatar_proxy/v4/letter/n/d07c76/32.png) [@nmadden](https://support.nitrokey.com/u/nmadden)
#### Post date: [December 19, 2017, 5:07pm UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812/1 "2017-12-19T17:07:32Z")

</div>

Hi,

I am trying to test the NitrokeyHSM with our Java application to ensure compatibility. I am using the OpenSC 0.17.0 PKCS#11 driver with the Java Sun PKCS#11 interface ([JDK 8 PKCS#11 Reference Guide](https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html)). I have not performed any custom configuration of either - just setup the PKCS#11 configuration pointing at the opensc-pkcs11.so and using slot 0.

I am running into difficulties performing anything other than basic RSA decryption or RSA/ECDSA signing using the card in this setup. For example, ECDH key agreement always fails with CKR\_KEY\_TYPE\_INCONSISTENT. Also, attempting to use RSA for key wrapping/unwrapping (for hybrid encryption using AES) also fails during the unwrap step. Can somebody let me know if I am doing something wrong or if these functions are just not supported using the PKCS#11 driver?

If I use the custom JCE provider from Smart Card Shell then ECDH key agreement works as expected using exactly the same code. However, RSA unwrap always fails with both providers.

Here is the output using the Sun PKCS#11 provider (source code follows):  
Loading keystore  
Loading static ECDH keys  
Static Private: SunPKCS11-NitrokeyHSM EC private key, 256 bits (id 140678806112736, token object, sensitive, unextractable)  
Static Public : Sun EC public key, 256 bits  
public x coord: 23919995184559860976253713360680914112848079777551416149635514637024520745309  
public y coord: 17120898397917041930631477206293964934850084751907000036557497273114856567487  
parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)  
Generating ephemeral ECDH keys  
Ephemeral Priv: SunPKCS11-NitrokeyHSM EC private key, 256 bits (id 140678806192720, token object, not sensitive, unextractable)  
Ephemeral Pub : SunPKCS11-NitrokeyHSM EC public key, 256 bits (id 140678806226736, session object)  
public x coord: 97449259143949072573844538684056027183607805363410967416942108362277540249769  
public y coord: 115640378721741984368022032270838032861978611587357263759325321358099294564788  
parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)  
Performing ECDH key agreement  
java.security.ProviderException: Could not derive key  
at sun.security.pkcs11.P11ECDHKeyAgreement.engineGenerateSecret(P11ECDHKeyAgreement.java:144)  
at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:586)  
at hsm.main(hsm.java:52)  
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR\_KEY\_TYPE\_INCONSISTENT  
at sun.security.pkcs11.wrapper.PKCS11.C\_DeriveKey(Native Method)  
at sun.security.pkcs11.P11ECDHKeyAgreement.engineGenerateSecret(P11ECDHKeyAgreement.java:133)  
… 2 more  
Loading RSA keys  
Wrapping AES key  
Unwrapping AES key  
Exception in thread “main” java.security.InvalidKeyException: unwrap() failed  
at sun.security.pkcs11.P11RSACipher.engineUnwrap(P11RSACipher.java:536)  
at javax.crypto.Cipher.unwrap(Cipher.java:2550)  
at hsm.main(hsm.java:73)  
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR\_FUNCTION\_NOT\_SUPPORTED  
at sun.security.pkcs11.wrapper.PKCS11.C\_UnwrapKey(Native Method)  
at sun.security.pkcs11.P11RSACipher.engineUnwrap(P11RSACipher.java:527)  
… 2 more

With the Smart Card Shell JCE provider then ECDH succeeds and RSA unwrap fails with the following error:

```
Exception in thread "main" java.lang.UnsupportedOperationException
at de.cardcontact.smartcardhsmprovider.SmartCardHSMCipher.engineSetMode(SmartCardHSMCipher.java:183)
at javax.crypto.Cipher$Transform.setModePadding(Cipher.java:374)
at javax.crypto.Cipher.chooseProvider(Cipher.java:862)
at javax.crypto.Cipher.init(Cipher.java:1249)
at javax.crypto.Cipher.init(Cipher.java:1186)
at hsm.main(hsm.java:72)

```

The source code I am using (with Java 1.8):

```
import java.security.*;
import java.security.interfaces.*;
import javax.crypto.*;
import javax.crypto.spec.*;

import java.util.*;
import javax.xml.bind.DatatypeConverter;

public class hsm {

    public static void main(String...args) throws Exception {
        if (args.length != 1) {
            System.err.println("Usage: java hsm <pin>");
            System.exit(1);
        }
        char[] pin = args[0].toCharArray();

        Security.addProvider(new de.cardcontact.smartcardhsmprovider.SmartCardHSMProvider());
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        
        // Load the HSM as a PKCS#11 keystore
        System.out.println("Loading keystore");
        KeyStore hsm = KeyStore.getInstance("SmartCardHSMKeyStore");
        //KeyStore hsm = KeyStore.getInstance("PKCS11");
        hsm.load(null, pin);
        Arrays.fill(pin, ' ');

        // Load an EC P-256 private key from the keystore
        System.out.println("Loading static ECDH keys");
        Key staticPrivateKey = hsm.getKey("p256", new char[0]); // No password
        Key staticPublicKey = hsm.getCertificate("p256").getPublicKey();

        System.out.println("Static Private: " + staticPrivateKey);
        System.out.println("Static Public : " + staticPublicKey);

        // Generate an ephemeral key-pair on the device
        System.out.println("Generating ephemeral ECDH keys");
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", hsm.getProvider());
        kpg.initialize(((ECPublicKey) staticPublicKey).getParams()); // Will default to P-256 curve
        KeyPair ephemeralKeys = kpg.generateKeyPair();

        System.out.println("Ephemeral Priv: " + ephemeralKeys.getPrivate());
        System.out.println("Ephemeral Pub : " + ephemeralKeys.getPublic());

        // Now perform ECDH key agreement between static private and ephemeral public keys
        System.out.println("Performing ECDH key agreement");
        KeyAgreement ecdh = KeyAgreement.getInstance("ECDH", hsm.getProvider());
        ecdh.init(staticPrivateKey);
        ecdh.doPhase(ephemeralKeys.getPublic(), true);

        try {
            byte[] sharedSecret = ecdh.generateSecret();
            System.out.println("Derived shared secret: " + DatatypeConverter.printHexBinary(sharedSecret));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Try wrapping/unwrapping
        System.out.println("Loading RSA keys");
        Key rsaPrivateKey = hsm.getKey("jwtEncRsa", new char[0]);
        Key rsaPublicKey = hsm.getCertificate("jwtEncRsa").getPublicKey();

        Key aesKey = new SecretKeySpec(new byte[16], "AES");

        System.out.println("Wrapping AES key");
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.WRAP_MODE, rsaPublicKey);
        byte[] wrapped = cipher.wrap(aesKey);

        System.out.println("Unwrapping AES key");
        cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.UNWRAP_MODE, rsaPrivateKey);
        Key unwrappedKey = cipher.unwrap(wrapped, "AES", Cipher.SECRET_KEY);

        System.out.println("Unwrapped key: " + unwrappedKey);
    }
}
```

---

<div class="post-metadata">

### Author: ![nmadden](https://support.nitrokey.com/letter_avatar_proxy/v4/letter/n/d07c76/32.png) [@nmadden](https://support.nitrokey.com/u/nmadden)
#### Post date: [December 19, 2017, 5:16pm UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812/2 "2017-12-19T17:16:14Z")

</div>

Another issue I have when using the Sun PKCS#11 provider is that the code to generate the ephemeral key pair (KeyPairGenerator) creates the keys permanently on the device, even though I did not save them to the KeyStore (and they are not visible through the KeyStore). This causes the device to eventually run out of memory. There seems to be no way to cleanup these ephemeral keys in Java and I have to resort to manually deleting them using pkcs11-tool. The Smart Card Shell provider does not leave such keys behind, so seems much better in that regard. There is no reason for these ephemeral keys to exist on the device, so I will just create the ephemeral keys in-memory instead (I can just drop the second argument to the KeyPairGenerator.getInstance() call), but I thought it was worth mentioning.

---

<div class="post-metadata">

### Author: ![jan](https://support.nitrokey.com/letter_avatar_proxy/v4/letter/j/ce7236/32.png) [@jan](https://support.nitrokey.com/u/jan)
#### Post date: [December 19, 2017, 7:20pm UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812/3 "2017-12-19T19:20:23Z")

</div>

> [@nmadden](#):
>
> I am using the OpenSC 0.17.0 PKCS#11 driver with the Java Sun PKCS#11 interface ([JDK 8 PKCS#11 Reference Guide](https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html)). I have not performed any custom configuration of either - just setup the PKCS#11 configuration pointing at the opensc-pkcs11.so and using slot 0.
> 
> I am running into difficulties performing anything other than basic RSA decryption or RSA/ECDSA signing using the card in this setup. For example, ECDH key agreement always fails with CKR\_KEY\_TYPE\_INCONSISTENT. Also, attempting to use RSA for key wrapping/unwrapping (for hybrid encryption using AES) also fails during the unwrap step.

This issue is rooted to OpenSC. Please collect a debug trace from OpenSC (Linux: start with  
OPENSC\_DEBUG=9 in front; Windows: Activate logging in opensc.conf) and submit it with a new [issue ticket](https://github.com/OpenSC/OpenSC/issues).

Regarding JCE, we will come back to you.

---

<div class="post-metadata">

### Author: ![nmadden](https://support.nitrokey.com/letter_avatar_proxy/v4/letter/n/d07c76/32.png) [@nmadden](https://support.nitrokey.com/u/nmadden)
#### Post date: [December 20, 2017, 10:56am UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812/4 "2017-12-20T10:56:57Z")

</div>

Thanks, I will raise a ticket with OpenSC

---

<div class="post-metadata">

### Author: ![nmadden](https://support.nitrokey.com/letter_avatar_proxy/v4/letter/n/d07c76/32.png) [@nmadden](https://support.nitrokey.com/u/nmadden)
#### Post date: [December 20, 2017, 1:59pm UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812/5 "2017-12-20T13:59:03Z")

</div>

I have raised [an issue for the ECDH problem with OpenSC](https://github.com/OpenSC/OpenSC/issues/1227). I found in the source code that the C\_WrapKey and C\_UnwrapKey functions are [completely not supported in OpenSC PKCS#11 driver](https://github.com/OpenSC/OpenSC/blob/master/src/pkcs11/pkcs11-object.c#L1032), so that is why the RSA unwrap does not work.

---

<div class="post-metadata">

### Author: ![nmadden](https://support.nitrokey.com/letter_avatar_proxy/v4/letter/n/d07c76/32.png) [@nmadden](https://support.nitrokey.com/u/nmadden)
#### Post date: [January 26, 2018, 11:41am UTC](https://support.nitrokey.com/t/nitrokeyhsm-and-java-sun-pkcs-11/812/6 "2018-01-26T11:41:09Z")

</div>

The OpenSC ticket is now closed. In case anyone else runs into this, it was my error - the key I was using did not have the derive flag set (only sign) so was quite reasonably being rejected by the driver as not suitable for ECDH.
