Halo: Allow to provide raw password digest instead of password for signing, fix bug in RN driver (#467)

This commit is contained in:
Michał Leszczyński
2025-07-11 16:52:29 +02:00
committed by GitHub
parent 8b5fbe7861
commit 25a3bec272
5 changed files with 28 additions and 19 deletions

View File

@@ -41,6 +41,7 @@ import {
HaloResponseObject
} from "../types.js";
import {Buffer} from 'buffer/index.js';
import {arr2hex, isWebDebugEnabled} from "../halo/util.js";
async function execHaloCmd(command: HaloCommandObject, options: ExecHaloCmdOptions): Promise<HaloResponseObject> {
command = Object.assign({}, command);
@@ -103,12 +104,19 @@ async function execHaloCmd(command: HaloCommandObject, options: ExecHaloCmdOptio
}
function checkErrors(res: Buffer) {
const webDebug = isWebDebugEnabled();
if (res.length === 2 && res[0] === 0xE1) {
if (webDebug) {
console.log('[libhalo] execCredential() command fail:', arr2hex(res));
}
if (Object.prototype.hasOwnProperty.call(ERROR_CODES, res[1])) {
const err = ERROR_CODES[res[1]];
throw new HaloTagError(err[0], "Tag responded with error: [" + err[0] + "] " + err[1]);
throw new HaloTagError(err[0], err[1]);
} else {
throw new HaloLogicError("Tag responded with unknown error: " + res.toString('hex'));
const errCode = arr2hex([res[1]]);
throw new HaloTagError("ERROR_CODE_" + errCode, "Command returned an unknown error: " + arr2hex(res));
}
}
}

View File

@@ -4,11 +4,11 @@
* License: MIT
*/
import {HaloTagError, NFCOperationError, NFCMethodNotSupported} from "../halo/exceptions.js";
import {ERROR_CODES} from "../halo/errors.js";
import {NFCOperationError, NFCMethodNotSupported} from "../halo/exceptions.js";
import {arr2hex, isWebDebugEnabled} from "../halo/util.js";
import {ExecOptions, ExecReturnStruct} from "../types.js";
import {Buffer} from 'buffer/index.js';
import {checkErrors} from "./common.js";
async function execCredential(request: Buffer, options: ExecOptions): Promise<ExecReturnStruct> {
const webDebug = isWebDebugEnabled();
@@ -87,19 +87,7 @@ async function execCredential(request: Buffer, options: ExecOptions): Promise<Ex
const res = (u2fRes.response as AuthenticatorAssertionResponse).signature;
const resBuf = new Uint8Array(res);
if (resBuf.length === 2 && resBuf[0] === 0xE1) {
if (webDebug) {
console.log('[libhalo] execCredential() command fail:', arr2hex(resBuf));
}
if (Object.prototype.hasOwnProperty.call(ERROR_CODES, resBuf[1])) {
const err = ERROR_CODES[resBuf[1]];
throw new HaloTagError(err[0], err[1]);
} else {
const errCode = arr2hex([resBuf[1]]);
throw new HaloTagError("ERROR_CODE_" + errCode, "Command returned an unknown error: " + arr2hex(resBuf));
}
}
checkErrors(Buffer.from(resBuf));
if (webDebug) {
console.log('[libhalo] execCredential() command result:', arr2hex(resBuf));

View File

@@ -26,7 +26,7 @@ async function execCoreCommandRN(nfcManager: RNNFCManager, command: Buffer) {
]);
const res = Buffer.from(await nfcManager.isoDepHandler.transceive([...cmdBuf]));
checkErrors(res);
checkErrors(res.slice(0, -2));
return {
result: res.slice(0, -2).toString('hex'),

View File

@@ -14,6 +14,7 @@ export interface BaseHaloCmdSign {
keyNo: KeySlotNo
format?: "text" | "hex"
password?: ASCIIString
rawPwdDigest?: ASCIIString
legacySignCommand?: boolean
}

View File

@@ -194,7 +194,19 @@ async function cmdSign(options: ExecHaloCmdOptions, args: HaloCmdSign): Promise<
let payload;
let pwdHash = null;
if (args.password) {
if (args.rawPwdDigest && args.password) {
throw new HaloLogicError("Arguments authDigest and password are mutually exclusive.")
}
if (args.rawPwdDigest) {
pwdHash = Buffer.from(sha256(Buffer.concat([
Buffer.from([0x19]),
Buffer.from("Password authentication:\n"),
Buffer.from([args.keyNo]),
digestBuf,
Buffer.from(args.rawPwdDigest, "hex")
])), "hex");
} else if (args.password) {
const derivedKey = pbkdf2.pbkdf2Sync(args.password, 'HaLoChipSalt', 5000, 16, 'sha512');
pwdHash = Buffer.from(sha256(Buffer.concat([