diff --git a/cli/args_cli.js b/cli/args_cli.js index bcd26a5..da4523d 100644 --- a/cli/args_cli.js +++ b/cli/args_cli.js @@ -343,6 +343,14 @@ importKeyParser.add_argument("-k", "--key-no", { required: true }); +let getDataStructParser = subparsers.add_parser("get_data_struct", {help: "Get certain data from the tag."}); +getDataStructParser.add_argument("-s", "--spec", { + dest: 'spec', + type: 'str', + help: "Data specification.", + required: true +}); + subparsers.add_parser("pcsc_detect", {help: "Detect PC/SC readers and HaLo tags (for debugging)."}); function parseArgs() { diff --git a/docs/firmware-versions.md b/docs/firmware-versions.md index 9680cc7..6b9a84e 100644 --- a/docs/firmware-versions.md +++ b/docs/firmware-versions.md @@ -74,6 +74,7 @@ Addons ver. - first HaLo Addons version to support the indicated driver. | `set_password` | 01.C7 | | | `replace_password` | 01.C7 | | | `unset_password` | 01.C7 | | +| `get_data_struct` | 01.C8 | | | `pcsc_detect` | 01.C1 | Only with CLI tool. | Core ver. - first HaLo Core version to officially support the indicated command. diff --git a/drivers/common.js b/drivers/common.js index 0008900..27e862c 100644 --- a/drivers/common.js +++ b/drivers/common.js @@ -11,7 +11,7 @@ const { const { cmdGetPkeys, cmdSign, cmdCfgNDEF, cmdWriteLatch, cmdSignRandom, cmdGenKey, cmdGenKeyConfirm, cmdGenKeyFinalize, cmdSignChallenge, cmdSetURLSubdomain, cmdSetPassword, cmdUnsetPassword, cmdReplacePassword, cmdGetKeyInfo, - cmdGetTransportPK, cmdLoadTransportPK, cmdExportKey, cmdImportKey, cmdImportKeyInit + cmdGetTransportPK, cmdLoadTransportPK, cmdExportKey, cmdImportKey, cmdImportKeyInit, cmdGetDataStruct } = require("../halo/commands"); const {ERROR_CODES} = require("../halo/errors"); @@ -60,6 +60,8 @@ async function execHaloCmd(command, options) { return await cmdImportKeyInit(options, command); case 'import_key': return await cmdImportKey(options, command); + case 'get_data_struct': + return await cmdGetDataStruct(options, command); default: throw new HaloLogicError("Unsupported command.name parameter specified."); } diff --git a/halo/cmdcodes.js b/halo/cmdcodes.js index 13251fe..586161a 100644 --- a/halo/cmdcodes.js +++ b/halo/cmdcodes.js @@ -21,6 +21,7 @@ const CMD_CODES = { "SHARED_CMD_GET_ADDON_FW_VERSION": 0x09, "SHARED_CMD_SIGN_CHALLENGE": 0x11, "SHARED_CMD_GET_KEY_INFO": 0x13, + "SHARED_CMD_GET_DATA_STRUCT": 0x14, "SHARED_CMD_SIGN_PWD": 0xA1, "SHARED_CMD_FETCH_SIGN_PWD": 0xA2, diff --git a/halo/commands.js b/halo/commands.js index 681ea71..c1704ee 100644 --- a/halo/commands.js +++ b/halo/commands.js @@ -667,6 +667,71 @@ async function cmdImportKey(options, args) { } } +async function cmdGetDataStruct(options, args) { + let specItems = args.spec.split(','); + specItems = specItems.map((item) => item.split(':', 2)); + + const TYPES = { + "publicKey": 0x01, + "publicKeyAttest": 0x02, + "keySlotFlags": 0x03, + "keySlotFailedAuthCtr": 0x04, + "latchValue": 0x20, + "latchAttest": 0x21, + "firmwareVersion": 0xF0 + }; + + let data = Buffer.alloc(0); + + for (let item of specItems) { + if (!TYPES[item[0]]) { + throw new HaloLogicError("Unsupported object type: " + item[0]); + } + + let val = parseInt(item[1]); + + if (val < 0 || val > 255) { + throw new HaloLogicError("Too high index value at: " + item[0] + ":" + item[1]); + } + + data = Buffer.concat([ + data, + Buffer.from([TYPES[item[0]], val]) + ]); + } + + let payload = Buffer.concat([ + Buffer.from([CMD.SHARED_CMD_GET_DATA_STRUCT]), + data + ]); + + let resp = await options.exec(payload); + let res = Buffer.from(resp.result, "hex"); + + specItems = specItems.reverse(); + let out = {}; + + while (res.length > 0) { + let item = specItems.pop(); + + let len = res[0]; + let data = res.slice(1, len + 1); + let value = data.toString('hex'); + + if (!data.length) { + value = null; + } + + out[item[0] + ':' + item[1]] = value; + res = res.slice(len + 1); + } + + return { + isPartial: specItems.length !== 0, + data: out + }; +} + module.exports = { cmdSign, cmdSignRandom, @@ -687,4 +752,5 @@ module.exports = { cmdExportKey, cmdImportKeyInit, cmdImportKey, + cmdGetDataStruct, };