Nitrokey HSM 2, encrypt with AES


I am trying to encrypt data with AES. I used Smart Card Shell 3 to generate the AES key. But now I don’t understand how to encrypt data.
I read the documentation :
I tried to use the function encrypt(), it’s working when I am generating a new AES key (as shown in the example) but I don’t understant how to use it with the AES key on the Nitrokey.

I also tried the sc-hsm-embedded library to encrypt data :

AES-KEY-GEN becomes available in the list of mechanisms after installing sc-hsm-embedded

But as there is no “encrypt” option with pkcs11-tool I don’t know how to use it neither.

If you have any clue on how to solve these isues, let me know.
Thanks you :slight_smile:


Just a formality: could you check you are using the latest OpenSC version?

I am using the opensc 0.20.0, which is the latest version I think. I used the windows installer (.msi) to install it.

You need to use the sc-hsm-pkcs11 module from the sc-hsm-embedded project. OpenSC does not yet include support for AES keys on a SmartCard-HSM.

See testAES for details on how AES keys can be used via the PKCS#11 interface.

If you download the starterkit, then you find in a workspace for the Smart Card Shell. The aes-performance.js and importAES.js scripts in examples/ show how AES operations can be performed.


Thanks for your help, but as I said before I already tried the example scripts. And when I am generating a new AES key it’s working but not when I am using a key from the smart card. I don’t know what I am missing… (see screenshot below)

Regarding sc-hsm-embedded, I might have an idea why it doesn’t work. I used the “.msi” windows installer and I think it installs the master branch and not the aes branch. So I installed the Windows Subsystem for Linux (WSL) and tried again with the aes branch this time. But it seems like WSL doesn’t not recognize USB devices…

I understood the AES support is in the master branch already (lately only tests are added), and included in the latest V2.11 release. @sc-hsm Could you confirm?

WSL1 might indeed not connect to the USB devices AFAIR. I believe the things were going to change with WSL2 - could you check what version did you use?

Edit: USB pass-through seems to still not be available after a brief search. There are reports of working this around with USB-IP and with a recompiled kernel.

1 Like

The aes branch is pretty old and has already been integrated in the master branch. You can use the .msi installer to install the latest 2.11 version.

When working with the SmartCard-HSM you need to obtain an instance of the Crypto class using

var card = new Card(_scsh3.reader);
var sc = new SmartCardHSM(card);
var crypto = sc.getCrypto();

however this currently only works for asymmetric key, but not for AES keys. For AES you need to use the APDU interface instead, like in

var enc = sc.card.sendApdu(0x80, 0x78, key.getId(), 0x10, plain, [0x9000]);

with 0x10 for encryption, 0x11 for decryption and 0x18 for CMAC.


Thank you for your replies. I will try again the aes branch on Windows !
I also tried the APDU interface but it still doesn’t work.

I don’t know which parameter is incorrect because I followed the starterkit…

This is a raw AES-CBC encryption operations, so the input block length must be a multiple of 16.

Oh yes of course ! Thank you. Just a last question, the initialisation vector used by default is 0000000000000000 ? Is there a way to specify the use of another initialisation vector in the APDU command ? Because I saw that the aes_crypt_cbc() function (link below) of the Nitrokey firmware requires an iv to be input.

In CBC mode the IV is xor’ed with the first input block. You can do that before you pass the input to the HSM. On the way back you need to xor the first plain block with the IV again.

The same when you chain multiple blocks, in which case the IV is the last block from the previous operation.

Thank you ! It works perfectly.