Hello,
I know about the examples of Smart Card Shell to see how to import AES keys.
But these examples require a “dkekshare”, we would like to know how it’s possible to get the value when the key is initialised externally (with sc hsm tools).
When we create a DKEK Share using sc hsm tools we get a .pbe file with the double of required size. I think we can’t use the content of this file AS-IS as it is also supposed to be secured.
Also is it possible to import an AES key in a Nitrokey HSM 2 secured with DKEK Share n-of-m ?
If the only choice for us is to import key with Smart Card Shell AND create the DKEK share in Smart Card Shell in order to init the HSM and import key, then how do we create a backup of the HSM to another one ?
Here is how we can import AES and private keys (P12 files)
/**
* ---------
* |.##> <##.| SmartCard-HSM Support Scripts
* |# #|
* |# #| Copyright (c) 2011-2012 CardContact Software & System Consulting
* |'##> <##'| Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
* ---------
*
* Consult your license package for usage terms and conditions.
*
* @fileoverview Import RSA Key and certificate from PKCS#12 file into SmartCard-HSM
*/
SmartCardHSM = require("scsh/sc-hsm/SmartCardHSM").SmartCardHSM;
HSMKeyStore = require("scsh/sc-hsm/HSMKeyStore").HSMKeyStore;
DKEK = require("scsh/sc-hsm/DKEK").DKEK;
function readfile(filename)
{
var FileReader = java.io.FileReader;
var BufferedReader = java.io.BufferedReader;
var content = "";
var reader = new BufferedReader(new FileReader("/tmp/cmn_key_idx0.txt"));
var line;
while ((line = reader.readLine()) != null) {
content += line;
}
reader.close();
return content;
}
var crypto = new Crypto();
var dkekshare = crypto.generateRandom(32);
var doinit = true;
var page = "<html>" +
"<p>The DKEK is used to encrypt the private key for import into the SmartCard-HSM.</p>" +
"<p>If you already have initialized your SmartCard-HSM and know the DKEK from a previous key import,<br>" +
"then you can replace the random DKEK below with the known DKEK from the previous import</p>" +
"</html>";
var str = Dialog.prompt(page, dkekshare.toString(HEX));
if ((str != null) && (str.length > 0)) {
newdkekshare = new ByteString(str, HEX);
assert(newdkekshare.length == 32, "DKEK share must be 32 bytes long");
if (!newdkekshare.equals(dkekshare)) {
doinit = false;
dkekshare = newdkekshare;
}
}
var card = new Card(_scsh3.reader);
card.reset(Card.RESET_COLD);
var sc = new SmartCardHSM(card);
if (doinit) {
if (sc.queryUserPINStatus() == 0x6984) {
assert(Dialog.prompt("WARNING: If you continue, then your SmartCard-HSM will be initialized to the initialization code selected in the next step"));
} else {
assert(Dialog.prompt("WARNING: If you continue, then your SmartCard-HSM will be initialized and all key contained will be lost"));
}
var initializationCode = Dialog.prompt("Enter initialization code for SmartCard-HSM", "0000000000000000");
assert(initializationCode != null);
initializationCode = new ByteString(initializationCode, HEX);
var pin = Dialog.prompt("Enter PIN for newly initialized SmartCard-HSM", "000000");
assert(pin != null);
pin = new ByteString(pin, ASCII);
sc.initDevice(new ByteString("0001", HEX), pin, initializationCode, 3, 1);
var status = sc.importKeyShare(dkekshare);
print("Device initialized:");
print("-------------------");
print("SW : " + status.sw.toString(HEX));
print("Shares : " + status.shares);
print("Outstanding : " + status.outstanding);
print("KVC : " + status.kcv.toString(HEX));
print("");
} else {
assert(sc.queryUserPINStatus() != 0x6984, "SmartCard-HSM is not initialized");
var pin = Dialog.prompt("Enter PIN for SmartCard-HSM", "648219");
assert(pin != null);
pin = new ByteString(pin, ASCII);
}
sc.verifyUserPIN(pin);
var file = "";
var pwd = "";
do {
// Prompt for PKCS#12 container and password, then select key to import
var file = Dialog.prompt("Select PKCS#12 container", file, null, "*.p12");
assert(file != null);
var pwd = Dialog.prompt("Enter PKCS#12 password", pwd);
assert(pwd != null);
var ks = new KeyStore("BC", "PKCS12", file, pwd);
var aliases = ks.getAliases();
var alias = Dialog.prompt("Select key", "", aliases);
assert(alias != null);
var key = new Key();
key.setType(Key.PRIVATE);
key.setID(alias);
ks.getKey(key);
var cert = ks.getCertificate(alias);
print(cert);
var alias = Dialog.prompt("Enter key name for import", alias);
assert(alias != null);
var ks = new HSMKeyStore(sc);
var dkek = new DKEK(crypto);
dkek.importDKEKShare(dkekshare);
var pubkey = cert.getPublicKey();
var blob = dkek.encodeKey(key, pubkey);
dkek.dumpKeyBLOB(blob);
if (pubkey.getComponent(Key.MODULUS)) {
hkey = ks.importRSAKey(alias, blob, cert.getPublicKey().getSize());
var signalgo = Crypto.RSA_PSS_SHA256;
} else {
hkey = ks.importECCKey(alias, blob, cert.getPublicKey().getSize());
var signalgo = Crypto.ECDSA_SHA256;
}
ks.storeEndEntityCertificate(alias, cert);
// Test import
var msg = new ByteString("Hello World", ASCII);
var signature = hkey.sign(signalgo, msg);
assert(crypto.verify(cert.getPublicKey(), signalgo, msg, signature));
} while (Dialog.prompt("Import more keys ?"));
while(Dialog.prompt("Any AES key to add ?"))
{
var file = Dialog.prompt("Select AES key file", file, null, "*.txt");
assert(file != null);
var aesdata = readfile(file);
print("AES DATA : " + aesdata);
var aes = new Key();
aes.setComponent(Key.AES, new ByteString(aesdata, HEX));
const keyname = file.split("/").pop(); // "cmn_key_idx0.txt"
const keyname2 = keyname.split(".").shift(); // "cmn_key_idx0"
var alias = Dialog.prompt("Enter key name for import", keyname2);
assert(alias != null);
var ks = new HSMKeyStore(sc);
var dkek = new DKEK(crypto);
dkek.importDKEKShare(dkekshare);
var blob = dkek.encodeAESKey(aes);
dkek.dumpKeyBLOB(blob);
ks.importAESKey(alias, blob, 128);
}
