repair-prkd.js
Summary
Repair a missing PRKD section in a key backup
var File = require("scsh/file/File").File;
var SmartCardHSM = require("scsh/sc-hsm/SmartCardHSM").SmartCardHSM;
function dumpKeyBLOB(keyblob) {
var keytype = keyblob.byteAt(8);
print("Values from key blob:");
print("---------------------");
print("KCV : " + keyblob.bytes(0, 8).toString(HEX) + " [Must match the KCV of the DKEK for import]");
print("Key type : " + keytype + " [5=RSA, 6=RSA-CRT, 12=ECC, 15=AES]");
var ofs = 9;
var len = keyblob.bytes(ofs, 2).toUnsigned();
if ((keytype == 15) && (keyblob.byteAt(ofs + 2) != 0x60)) {
print("Default Algorithm ID : " + keyblob.bytes(ofs + 2, len).toString(HEX) + " (" + len + ") [Wrong encoding in V3.0 to V3.2]");
} else {
print("Default Algorithm ID : " + keyblob.bytes(ofs + 2, len).toString(OID) + " (" + len + ") [Default algorithm]");
}
ofs += len + 2;
var len = keyblob.bytes(ofs, 2).toUnsigned();
print("Allowed Algorithm IDs : " + keyblob.bytes(ofs + 2, len).toString(HEX) + " (" + len + ")");
ofs += len + 2;
var len = keyblob.bytes(ofs, 2).toUnsigned();
print("Access Conditions : " + keyblob.bytes(ofs + 2, len).toString(HEX) + " (" + len + ") [Not used]");
ofs += len + 2;
var len = keyblob.bytes(ofs, 2).toUnsigned();
print("Key OID : " + keyblob.bytes(ofs + 2, len).toString(HEX) + " (" + len + ") [Not used]");
}
var fn = Dialog.prompt("Select key backup", "", null, "*.wky");
print(fn);
var f = new File(fn);
var bin = f.readAllAsBinary();
f.close();
var outerseq = new ASN1(bin);
print("Dump of backup file");
print(outerseq);
var sections = outerseq.elements;
print("Key backup contains " + sections + " sections (Should be between 2 and 3)");
if ((sections < 1) || (outerseq.get(0).tag != ASN1.OCTET_STRING)) {
throw new Error("First section does not contain a vaild key blob. Can't repair");
}
var blob = outerseq.get(0).value;
if (blob.length < 16) {
throw new Error("Key blob too small. Can't repair");
}
dumpKeyBLOB(blob);
var i = 1;
var prkd = null;
if ((i < sections) && (outerseq.get(i).get(0).get(0).tag == ASN1.UTF8String)) {
prkd = outerseq.get(i);
i++;
}
var cert = null;
var label = "";
var keysize = 2048;
var id = "01";
if ((i < sections) && ((outerseq.get(i).tag == ASN1.SEQUENCE) || (outerseq.get(i).tag == 0x67))) {
var cert = outerseq.get(i);
if (cert.tag == ASN1.SEQUENCE) {
var x = new X509(cert.getBytes());
print(x);
} else {
var x = new CVC(cert.getBytes());
print(x);
}
}
if (prkd == null) {
print("Corrupted backup detected: Missing PRKD section");
var label = Dialog.prompt("Enter a label for the key", label );
if (label == null) {
throw new Error("User abort");
}
var keysize = Dialog.prompt("Enter key size in bits", "" + keysize );
if (keysize == null) {
throw new Error("User abort");
}
keysize = parseInt(keysize);
var id = Dialog.prompt("Enter key id as hex string", id );
if (id == null) {
throw new Error("User abort");
}
id = new ByteString(id, HEX);
var keytype = blob.byteAt(8);
switch(keytype) {
case 5:
case 6:
prkd = SmartCardHSM.buildPrkDforRSA(id, label, keysize);
break;
case 12:
prkd = SmartCardHSM.buildPrkDforECC(id, label, keysize);
break;
case 15:
prkd = SmartCardHSM.buildSKDforAES(id, label, keysize);
break;
default:
throw new Error("Unsupported key type");
}
var nseq = new ASN1(ASN1.SEQUENCE);
nseq.add(outerseq.get(0));
nseq.add(prkd);
if (cert != null) {
nseq.add(cert);
}
print(nseq);
var nfn = fn.substr(0, fn.lastIndexOf(".")) + "-fixed.wky";
var f = new File(nfn);
f.writeAll(nseq.getBytes());
f.close();
print("Fixed backup written to " + nfn);
} else {
print("No problem found");
}
Documentation generated by
JSDoc on Sat Feb 24 15:17:19 2024