Problem importing AES 128 key

I try to import a 16bytes AES key:

openssl rand -out aes_key.bin 16
pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -l --pin xxxxx --write-object aes_key.bin --type secrkey --key-type AES:16 --id 11 --label “MyAESKey”
Using slot 0 with a present token (0x0)
error: PKCS11 function C_CreateObject failed: rv = CKR_GENERAL_ERROR (0x5)
Aborting.

Looks like what I want to do is basic, I don’t know what I’m missing, do you need full logs?

Thanks

The HSM does not allow import of sensitive key material in plain for security reasons. Sensitive key material would traverse several layers in the application and operating system with the risk of unwanted disclosure.

You will need to use a Key Encryption Key for import. The easiest way is to use the importAES.js script from the SmartCard-HSM Workspace. It is contained in the SmartCard-HSM Starterkit:

var aes = new Key();
aes.setComponent(Key.AES, new ByteString("00112233445566778899AABBCCDDEEFF", HEX));

// Use default crypto provider
var crypto = new Crypto();

// Create card access object
var card = new Card(_scsh3.reader);

card.reset(Card.RESET_COLD);

// Create SmartCard-HSM card service
var sc = new SmartCardHSM(card);

// Attach key store
var ks = new HSMKeyStore(sc);

// Initialize with key domain
var sci = new SmartCardHSMInitializer(card);
sci.setKeyDomains(1);
sci.initialize();

// Create DKEK domain with 00.00 DKEK
sc.createDKEKKeyDomain(0, 1);
var share = new ByteString("0000000000000000000000000000000000000000000000000000000000000000", HEX);
sc.importKeyShare(0, share);

// Create DKEK encoder and import share
var dkek = new DKEK(crypto);
dkek.importDKEKShare(share);

// Encode AES key into blob
var blob = dkek.encodeAESKey(aes);
dkek.dumpKeyBLOB(blob);

var key = ks.importAESKey("ImportedAESKey", blob, 128);

What the script does is to create a DKEK key domain on the HSM with a known key share of all ‘00’. It then encrypts the plain key value into a suitable key blob which is then imported.

Of course you should either choose a secret DKEK share or clear the DKEK share in the HSM to prevent later export under the known DKEK.

Thanks, is there a way to do it with PKCS11 API and sc-hsm-tool ?

You could do the import with sc-hsm-tool, but for encrypting the key blob you will need to use the Smart Card Shell.

Another question: Why do you want to generate the AES key outside the HSM ?

That defeats the purpose of using a Hardware Security Module, as you never know how many copies of the key exist.

You typically use a HSM, because you want to control the full key life-cycle, from creation to deletion. Of course you want a secure backup and key migration, that is what key domains are for.

I usually compare cryptographic keys to radioactive material. You never want to touch that by hand, which is why you handle radioactive material in a hot-cell. A HSM is for keys, what a hot-cell is for radioactive material, a safe containment.

I tried the scsh way and it works! Thanks

On why I don’t generate the key in the HSM, it’s a long story.
I use AES-ECB to generate a unique password based on some device serial number.
One copy of the key should be in factory (abroad, third party)
One copy of the key should be in a cloud provider (AWS/Azure/…)
But in the past, I used Luna Safenet HSM for this and could not have the right level of interoperability between the vendors (AWS cloud HSM, Azure HSM, Safenet).
Basically, you generate the key in your SafeNet HSM and are stuck with it; you can’t back it up and install it in another vendor or a cloud provider’s HSM you can only use Safenet HSM.

So what I’m experimenting with Nitrokey is to generate the key outside of the HSM and use the HSM to distribute the key to my factory, so it’s safe here. And if I need to change of HSM vendors (like pushing the key to AWS cloud HSM, I can do it).

1 Like

I get the key generated:
image

but if I try to list it using pkcs11-tool I can’t see it (my goal is to use it from a tool I’m writting and using pkcs11 to connect to the key)

pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -l --pin 648219 --list-objects
Using slot 0 with a present token (0x0)
Profile object 3694819104
  profile_id:          CKP_PUBLIC_CERTIFICATES_TOKEN (4)

You need to use the native SmartCard-HSM PKCS#11 module. OpenSC does not have support for AES keys on the SmartCard-HSM yet.

Both modules are compatible, so you can mix their use.

1 Like

Thanks, with this module I can see it:

❯ pkcs11-tool --module /usr/local/lib/libsc-hsm-pkcs11.so -l --pin 648219 --list-objects                                                                                    
Using slot 0 with a present token (0x1)
Secret Key Object; AES length 16
  label:      MyAESKey
  ID:         01
  Usage:      encrypt, decrypt
  Access:     sensitive, always sensitive, never extractable, local

I managed to encrypt using the key from Go code using PKCS11. My only issue is that AES ECB is not supported, but I can use AES-CBC with a fixed IV. Thanks for the help!

Hi, I have a very similar issue to you, I would love to either generate a key outside the HSM and import it in, or the other way round, so that I can use it both from a cloud provider or the hardware token. would you sum up what you ended up doing?
Thank you!

Hello there,
The script fails after the following step:

>sci.setKeyDomains(1);
>sci.initialize();
GPError: Card (CARD_INVALID_SW/25549) - "Unexpected SW1/SW2=63CD (Warning processing: Counter at 13) received" in /home/wola/cloud_secrets/scsh-3.18.39/scsh/sc-hsm/SmartCardHSM.js#2873
    at /home/wola/cloud_secrets/scsh-3.18.39/scsh/sc-hsm/SmartCardHSM.js#2873

Which script ?

The error indicates a wrong initialization code (aka SO-PIN).

I blindly used the script provided in the 2nd message of the thread to test a key import: Problem importing AES 128 key - #2 by sc-hsm

Do I have to provide the SO-PIN at some point?

After running the full script from the provided Starterkit, it fails with the same issue.

apparently scsh SmartCardHSM::SmartCardHSMInitializer() sets the default SO-PIN in initializationCode and then the call to initialize() failed, so I suppose this is the issue.

Is there a way to tell scsh to use my SO-PIN? the hardcoded value makes me think I’m not looking in the right place…

The example script uses the default test initialization code we recommend to use unless you are going productive.

You can set your own initialization code (SO-PIN) with

sci.setInitializationCode(new ByteString("57621880", ASCII));

and your own PIN with

sci.setUserPIN(new ByteString("648219", ASCII));

If you already have a fully initialized HSM and just want the import.

Another option is to use a script that attaches to the running key manager
and import the AES key into a sparse key domain.

You can access the running key manager with the km variable in the script environment.

if (typeof(km) == "undefined") {
	throw new Error("Key Manager must be running");
}

var aes = new Key();
aes.setComponent(Key.AES, new ByteString("00112233445566778899AABBCCDDEEFF", HEX));
aes.label = "ImportedAESKey";


// Locate an empty key domain
var kdid = -1;
do {
	kdid++;
	var kd = km.sc.queryKeyDomainStatus(kdid);
	if ((kd.sw == 0x6A86) || (kd.sw == 0x6D00)) {
		Dialog.prompt("No empty key domain found.");
		throw new Error("User abort");
	}
} while (kd.sw != 0x6A88);

// Create DKEK domain with random DKEK
km.sc.createDKEKKeyDomain(kdid, 1);
var share = km.crypto.generateRandom(32);
km.sc.importKeyShare(kdid, share);

// Create DKEK encoder and import share
var dkek = new DKEK(km.crypto);
dkek.importDKEKShare(share);

// Encode AES key into blob
var blob = dkek.encodeAESKey(aes);
dkek.dumpKeyBLOB(blob);

var key = km.ks.importAESKey(aes.label, blob, aes.getSize());

// Remove the Key Encryption Key
km.sc.deleteKEK(kdid);

// Force a refresh
km.setCard(km.sc.card);

@grk I’m in the process of writing a blog post with code samples, I’ll keep you posted

1 Like

@grk I resumed what I did here: Generating and distributing symmetrical IoT authentication keys | Julien Vermillard it’s mainly what you have in this thread plus a Go sample