@ledgerhq/revault-sdk 0.28.6 → 0.28.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/engine.cjs +23 -59
- package/lib/engine.cjs.map +1 -1
- package/lib/engine.js +23 -59
- package/lib/engine.js.map +1 -1
- package/package.json +2 -2
package/lib/engine.cjs
CHANGED
|
@@ -4,7 +4,6 @@ const require_device = require("./device-CTYTWL2K.cjs");
|
|
|
4
4
|
const require_utils = require("./utils-qv4hwX4J.cjs");
|
|
5
5
|
let invariant = require("invariant");
|
|
6
6
|
invariant = require_rolldown_runtime.__toESM(invariant, 1);
|
|
7
|
-
let ts_pattern = require("ts-pattern");
|
|
8
7
|
let rxjs = require("rxjs");
|
|
9
8
|
let _trpc_client = require("@trpc/client");
|
|
10
9
|
let superjson = require("superjson");
|
|
@@ -672,55 +671,40 @@ function createEngine(options, logger) {
|
|
|
672
671
|
});
|
|
673
672
|
if (engine.device && engine.__onboardingId) decorate((engine) => {
|
|
674
673
|
const { device, client, __onboardingId } = engine;
|
|
675
|
-
const isPskEnabled = async () => {
|
|
676
|
-
try {
|
|
677
|
-
return await client.onboarding.getPskFeatureFlag.query({ onboardingId: __onboardingId }) === true;
|
|
678
|
-
} catch {
|
|
679
|
-
return false;
|
|
680
|
-
}
|
|
681
|
-
};
|
|
682
674
|
async function enforcePairing() {
|
|
683
675
|
const status = await device.hasPairing();
|
|
684
676
|
if (status === "OK") return;
|
|
685
|
-
const pskEnabled = await isPskEnabled();
|
|
686
677
|
let pubKeyPromise;
|
|
687
678
|
const getPubKey = async () => {
|
|
688
679
|
pubKeyPromise ??= device.getU2FPubKey().then(({ pubKey }) => pubKey);
|
|
689
680
|
return pubKeyPromise;
|
|
690
681
|
};
|
|
691
|
-
const
|
|
682
|
+
const refreshCurrentPsk = async () => {
|
|
692
683
|
const pubKey = await getPubKey();
|
|
693
|
-
await
|
|
684
|
+
await refreshPsk({
|
|
694
685
|
device,
|
|
695
|
-
|
|
686
|
+
getRefreshPskData: (data) => client.onboarding.refreshPsk.mutate({
|
|
696
687
|
pubKey,
|
|
697
688
|
onboardingId: __onboardingId,
|
|
698
|
-
data
|
|
699
|
-
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
700
|
-
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
701
|
-
}
|
|
689
|
+
data
|
|
702
690
|
})
|
|
703
691
|
});
|
|
704
692
|
};
|
|
705
|
-
|
|
693
|
+
if (status === "NO_PAIRING") {
|
|
706
694
|
const pubKey = await getPubKey();
|
|
707
|
-
await
|
|
695
|
+
await pairDevice({
|
|
708
696
|
device,
|
|
709
|
-
|
|
697
|
+
getPairing: (confidentialityKey) => client.onboarding.pairDevicePartition.mutate({
|
|
710
698
|
pubKey,
|
|
711
699
|
onboardingId: __onboardingId,
|
|
712
|
-
data
|
|
700
|
+
data: {
|
|
701
|
+
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
702
|
+
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
703
|
+
}
|
|
713
704
|
})
|
|
714
705
|
});
|
|
715
|
-
}
|
|
716
|
-
await (
|
|
717
|
-
await pairCurrentDevice();
|
|
718
|
-
}).with(["NO_PAIRING", true], async () => {
|
|
719
|
-
await pairCurrentDevice();
|
|
720
|
-
await refreshCurrentPsk();
|
|
721
|
-
}).with(["PSK_MISSING", false], async () => {}).with(["PSK_MISSING", true], async () => {
|
|
722
|
-
await refreshCurrentPsk();
|
|
723
|
-
}).exhaustive();
|
|
706
|
+
}
|
|
707
|
+
await refreshCurrentPsk();
|
|
724
708
|
}
|
|
725
709
|
return {
|
|
726
710
|
claimDevice: async (params) => {
|
|
@@ -903,40 +887,23 @@ function createEngine(options, logger) {
|
|
|
903
887
|
});
|
|
904
888
|
if (engine.device && engine.__workspaceName && engine.__psdToken) decorate((engine) => {
|
|
905
889
|
const { client, device } = engine;
|
|
906
|
-
const isPskEnabled = async () => {
|
|
907
|
-
try {
|
|
908
|
-
return await client.debug.getPskFeatureFlag.query() === true;
|
|
909
|
-
} catch {
|
|
910
|
-
return false;
|
|
911
|
-
}
|
|
912
|
-
};
|
|
913
890
|
async function enforcePairing() {
|
|
914
891
|
const status = await device.hasPairing();
|
|
915
892
|
if (status === "OK") return;
|
|
916
|
-
const pskEnabled = await isPskEnabled();
|
|
917
|
-
const pairCurrentDevice = async () => {
|
|
918
|
-
await pairDevice({
|
|
919
|
-
device,
|
|
920
|
-
getPairing: (confidentialityKey) => client.debug.pairDevicePartition.mutate({
|
|
921
|
-
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
922
|
-
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
923
|
-
})
|
|
924
|
-
});
|
|
925
|
-
};
|
|
926
893
|
const refreshCurrentPsk = async () => {
|
|
927
894
|
await refreshPsk({
|
|
928
895
|
device,
|
|
929
896
|
getRefreshPskData: (data) => client.debug.refreshPsk.mutate(data)
|
|
930
897
|
});
|
|
931
898
|
};
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
899
|
+
if (status === "NO_PAIRING") await pairDevice({
|
|
900
|
+
device,
|
|
901
|
+
getPairing: (confidentialityKey) => client.debug.pairDevicePartition.mutate({
|
|
902
|
+
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
903
|
+
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
904
|
+
})
|
|
905
|
+
});
|
|
906
|
+
await refreshCurrentPsk();
|
|
940
907
|
}
|
|
941
908
|
const approveChallenge = async (challenge, params) => {
|
|
942
909
|
await enforcePairing();
|
|
@@ -944,11 +911,8 @@ function createEngine(options, logger) {
|
|
|
944
911
|
await openSecureChannel(device, challenge);
|
|
945
912
|
} catch (err) {
|
|
946
913
|
if (!require_device.isPskMissingError(err)) throw err;
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
await enforcePairing();
|
|
950
|
-
await openSecureChannel(device, challenge);
|
|
951
|
-
}
|
|
914
|
+
await enforcePairing();
|
|
915
|
+
await openSecureChannel(device, challenge);
|
|
952
916
|
}
|
|
953
917
|
await params?.onScreenDisplayed?.();
|
|
954
918
|
return await device.validateVaultOperation({ actions: challenge.wActions });
|
package/lib/engine.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.cjs","names":["PAGINATED_STATUS","LockedDeviceError","isTransportStatusError","DisconnectedDevice","lastValueFrom","withDevicePolling","from","PATHS","APPID_VAULT_ADMINISTRATOR","STR_ROLES","SCRIPT_IDS","createTRPCClient","httpLink","createApiDevice","match","buildTrpcContext","isPskMissingError"],"sources":["../src/device/real-device.ts","../src/trpc.ts","../src/engine/index.ts"],"sourcesContent":["import { DisconnectedDevice, LockedDeviceError } from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport type { HsmCertificate, PubKey, RefreshPskData } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { from, lastValueFrom } from \"rxjs\";\n\nimport type { Logger } from \"@/logger\";\n\nimport {\n APPID_VAULT_ADMINISTRATOR,\n PAGINATED_STATUS,\n PATHS,\n SCRIPT_IDS,\n STATUS_LENGTH,\n STR_ROLES,\n STREAMING_NEXT_ACTION,\n STREAMING_RESPONSE,\n} from \"./constants\";\nimport { withDevicePolling } from \"./device-access\";\nimport type { Device, PairingStatus } from \"./types\";\nimport { isTransportStatusError } from \"./utils\";\n\nconst MAX_CHUNK_LENGTH = 250;\n\ntype Options = {\n transportId: string;\n};\n\nconst getPathFromPathString = (pathString: string): number[] => {\n const parts = pathString.split(\"'/\").map((part) => Number.parseInt(part, 10));\n return parts.map((part) => (part | 0x80000000) >>> 0);\n};\n\nconst splitChunks = (chunk: number, buffer: Buffer): Buffer[] => {\n const chunks = [];\n for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {\n chunks.push(buffer.slice(i, i + size));\n }\n return chunks;\n};\n\nconst removeStatus = (result: Buffer): Buffer => result.slice(0, result.length - STATUS_LENGTH);\n\nconst sendByChunk = async (\n transport: Transport,\n command: number[], // eg [0xe0, 0x45, 0x00, 0x00]\n data: Buffer,\n chunkSize: number = MAX_CHUNK_LENGTH,\n): Promise<Buffer> => {\n const chunks = splitChunks(chunkSize, data);\n let response = Buffer.from([]);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const apdu = [...command];\n // command is 0xe0,0x45,0x00,0x00 for first chunk, then it's 0xe0,0x45,0x80,0x00\n /* v8 ignore next -- @preserve */\n apdu[2] = i && 0x80;\n response = (await transport.send(apdu[0]!, apdu[1]!, apdu[2], apdu[3]!, chunk, [\n 0x9000,\n ...PAGINATED_STATUS,\n ])) as Buffer<ArrayBuffer>;\n }\n return response;\n};\n\nconst buildAttestation = (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n}): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const cliMsgBuffer = Buffer.from(params.handshake, \"hex\");\n const cliMsgLengthBuffer = Buffer.alloc(1);\n cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);\n\n const pidBuffer = Buffer.from(params.partitionId, \"hex\");\n const pidLengthBuffer = Buffer.alloc(1);\n pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n cliMsgLengthBuffer,\n cliMsgBuffer,\n certChainDataLengthBuff,\n certChainData,\n pidLengthBuffer,\n pidBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n const toSend = Buffer.concat([totalLengthBuffer, data]);\n\n return toSend;\n};\n\n// Wire-format builder for FINALIZE_PSK_REFRESH (`0xE0 0x53`). Same layout as `buildAttestation`\n// (consumed by the device's `parse_nn_handshake_payload`), but the trailing TLV carries the\n// encrypted PairingPayload from `RefreshPsk` instead of a partition ID.\n//\n// Layout after the leading 2-byte total length:\n// [1] handshake length (the NN responder handshake, written from its actual decoded length)\n// [N] handshake bytes\n// [2] cert-chain-data length (BE)\n// [1] handshake-cert (DER signature) length\n// [N] handshake-cert bytes\n// [65] vault attestation pubkey (raw 0x04|x|y, no length prefix)\n// [1] att-cert length\n// [M] att-cert bytes\n// [1] ciphered-payload length\n// [K] encrypted PairingPayload bytes\nconst buildPskRefreshPayload = (params: RefreshPskData): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const handshakeBuffer = Buffer.from(params.handshake, \"base64\");\n invariant(\n handshakeBuffer.length <= 255,\n `PSK refresh handshake too long: ${handshakeBuffer.length} bytes (max 255)`,\n );\n const handshakeLengthBuffer = Buffer.alloc(1);\n handshakeLengthBuffer.writeUInt8(handshakeBuffer.length, 0);\n\n const encryptedPayloadBuffer = Buffer.from(params.encryptedPairingPayload, \"base64\");\n invariant(\n encryptedPayloadBuffer.length <= 255,\n `PSK encrypted payload too long: ${encryptedPayloadBuffer.length} bytes (max 255)`,\n );\n const encryptedPayloadLengthBuffer = Buffer.alloc(1);\n encryptedPayloadLengthBuffer.writeUInt8(encryptedPayloadBuffer.length, 0);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n handshakeLengthBuffer,\n handshakeBuffer,\n certChainDataLengthBuff,\n certChainData,\n encryptedPayloadLengthBuffer,\n encryptedPayloadBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n return Buffer.concat([totalLengthBuffer, data]);\n};\n\ntype RetryOnError = (err: Error) => boolean;\n/* v8 ignore next -- @preserve */\nconst genericRetryOnError: RetryOnError = (err) => {\n // device is locked\n if (err instanceof LockedDeviceError) return true;\n // user is on dashboard when receiving a Vault app apdu\n if (isTransportStatusError(err) && err.statusCode === 0x6d09) return true;\n // VG-24797 error that can happen in BLE in some situations (still unclear)\n if (err instanceof DisconnectedDevice) return true;\n\n // for everything else, we don't want to retry\n return false;\n};\n\nexport function createRealDevice(options: Options, logger: Logger): Device {\n const { transportId } = options;\n\n async function run<T>(\n job: (transport: Transport) => Promise<T>,\n retryOnError: RetryOnError = genericRetryOnError,\n ): Promise<T> {\n return lastValueFrom(\n withDevicePolling(transportId)<T>((transport) => from(job(transport)), retryOnError),\n );\n }\n\n /* v8 ignore next -- @preserve */\n const noRetry = (): boolean => false;\n /* v8 ignore next -- @preserve */\n const alwaysRetry = (): boolean => true;\n const poll = async (\n opts: { retryOnError?: RetryOnError } = {},\n ): Promise<{ isAppOpened: boolean }> => {\n // waiting for device to be turned on\n await run(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n async (_transport) => {},\n opts.retryOnError ?? alwaysRetry,\n );\n // checking if app is opened: should return directly on getPubKey\n try {\n await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });\n return { isAppOpened: true };\n } catch (err) {\n if (isTransportStatusError(err) && genericRetryOnError(err)) {\n return { isAppOpened: false };\n }\n throw err;\n }\n };\n\n const pollApp = async (appName: string): Promise<string> => {\n const res = await run((transport) =>\n transport.send(0xe0, 0xd8, 0x00, 0x00, Buffer.from(appName, \"utf8\")),\n );\n // little delay to give time to the app to be fully opened\n await new Promise((r) => setTimeout(r, 1e3));\n return res.toString(\"hex\");\n };\n\n const getPublicKey = async (\n pathString: string,\n { secp256k1, retryOnError }: { secp256k1: boolean; retryOnError?: RetryOnError },\n ): Promise<{ pubKey: string; signature: string }> => {\n logger.info(`[device] getPublicKey (${pathString})`);\n const path = getPathFromPathString(pathString);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const curve = secp256k1 ? 0x01 : 0x02;\n const response = await run(\n (transport) => transport.send(0xe0, 0x40, curve, 0x00, data),\n retryOnError ?? genericRetryOnError,\n );\n const pubKeyLength = response.readInt8(0);\n const pubKey = response\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = response\n .slice(pubKeyLength + 1, response.length - STATUS_LENGTH)\n .toString(\"base64\");\n return { pubKey, signature };\n };\n\n const device: Device = {\n authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {\n logger.info(`[device] Authenticate`);\n invariant(role !== \"READ_ONLY_API_KEY\", \"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n const nameBuffer = Buffer.from(name);\n const workspaceBuffer = Buffer.from(workspaceName);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([nameBuffer.length]),\n nameBuffer,\n Buffer.from([workspaceBuffer.length]),\n workspaceBuffer,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([\n Buffer.from(challenge, \"base64\"),\n applicationBuffer,\n Buffer.from([keyHandle.length]),\n Buffer.from(keyHandle, \"hex\"),\n keyHandleDataLength,\n keyHandleData,\n ]);\n\n const authentication = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x02, 0x00, 0x00], data),\n );\n\n return removeStatus(authentication).toString(\"hex\");\n },\n\n finalizePairingHandshake: async (params: {\n handshake: string;\n partitionId: string;\n handshakeAttestation: HsmCertificate;\n }): Promise<string> => {\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x47, 0x00, 0x02], buildAttestation(params)),\n );\n return removeStatus(bufWithStatus).toString(\"hex\");\n },\n\n generateSeedFragment: async (): Promise<string> => {\n logger.info(`[device] generateSeedFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x00, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n generateWrappingKeyFragment: async (): Promise<string> => {\n logger.info(`[device] generateWrappingKeyFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x01, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n getAttestation: async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x41, 0x00, 0x00));\n const buffer = removeStatus(bufWithStatus);\n const certLen = buffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: buffer.slice(0, 32).toString(\"base64\"),\n attestationPub: buffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer,\n };\n },\n getConfidentialityKey: async () => {\n logger.info(`[device] getConfidentialityKey`);\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x4d, 0x00, 0x00));\n const buf = removeStatus(bufWithStatus);\n const keyLength = buf[0]!;\n const key = buf.slice(1, 1 + keyLength);\n const sig = buf.slice(1 + keyLength + 1);\n return {\n confidentialityKeyCurve25519: key.toString(\"hex\"),\n confidentialityKeySignature: sig.toString(\"hex\"),\n };\n },\n getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),\n getDeviceUserId: async (): Promise<string> => {\n logger.info(`[device] getDeviceUserId`);\n const response = await run((transport) => transport.send(0xe0, 0x52, 0x00, 0x00));\n return removeStatus(response).toString(\"hex\").toUpperCase();\n },\n getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),\n getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),\n hasPairing: async (): Promise<PairingStatus> => {\n logger.info(`[device] hasPairing`);\n const apdu = [0xe0, 0x51, 0x00, 0x00, 0xb5];\n const res = await run((transport) => transport.exchange(Buffer.from(apdu)));\n\n // GET_PARTITION_IDS returns the partition list followed by a 2-byte SW. Inspect only\n // the trailing SW; the device may return data alongside non-`9000` SWs (notably 0x6065\n // — see below).\n const swHex = res.subarray(res.length - 2).toString(\"hex\");\n\n // 6f45 => no partition ID on the device (SW_NO_PARTITION_ID).\n // 6a87 => TEMPORARY hack: some firmware revs don't implement the APDU and return\n // \"incorrect length\"; treat as no pairing so revault drives the full pair-from-\n // scratch flow.\n if (swHex === \"6f45\" || swHex === \"6a87\") return \"NO_PAIRING\";\n\n // 6065 => SW_PSK_MISSING: a valid pairing record exists but its PSK field is the all-\n // zero sentinel. Skip the full pairing chain and run the refresh sub-chain.\n if (swHex === \"6065\") return \"PSK_MISSING\";\n\n // Anything else (typically 9000) => fully provisioned pairing with PSK.\n return \"OK\";\n },\n\n initPairingHandshake: async (): Promise<{ pubKey: string; signature: string }> => {\n const res = await run((transport) => transport.send(0xe0, 0x46, 0x00, 0x00));\n const pubKeyLength = res.readInt8(0);\n const pubKey = res\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString(\"base64\");\n return { pubKey, signature };\n },\n\n openSession: async (params: {\n secureChannel: { pubKey: PubKey; certificate: HsmCertificate };\n }): Promise<void> => {\n logger.info(`[device] openSession`);\n const { secureChannel } = params;\n\n const path = getPathFromPathString(PATHS.CONFIDENTIALITY);\n const dataDerivation = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n const pubKey = Buffer.from(secureChannel.pubKey, \"hex\");\n\n const sigBuffer = Buffer.from(secureChannel.certificate.signature, \"base64\");\n const attestationPubBuffer = Buffer.from(secureChannel.certificate.attestationPub, \"base64\");\n const certBuffer = Buffer.from(secureChannel.certificate.certificate, \"base64\");\n const attestation = Buffer.concat([\n Buffer.from([sigBuffer.length]),\n sigBuffer,\n attestationPubBuffer,\n Buffer.from([certBuffer.length]),\n certBuffer,\n ]);\n\n const lengthAttestation = Buffer.alloc(2);\n lengthAttestation.writeUInt16BE(attestation.length, 0);\n\n const data = Buffer.concat([dataDerivation, pubKey, lengthAttestation, attestation]);\n\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x42, 0x00, SCRIPT_IDS.INIT_SESSION], data),\n );\n },\n\n register: async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n invariant(applicationBuf.length === 32, \"application hex is expected to have 32 bytes\");\n\n const userNameBuff = Buffer.from(name);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([userNameBuff.length]),\n userNameBuff,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);\n\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x01, 0x00, 0x00], data),\n );\n\n let i = 0;\n const rfu = response.slice(i, i + 1)[0]!;\n i += 1;\n const pubKey = response.slice(i, i + 65).toString(\"hex\");\n i += 65;\n const keyHandleLength = response.slice(i, i + 1)[0]!;\n i++;\n const keyHandle = response.slice(i, i + keyHandleLength);\n i += keyHandleLength;\n return {\n u2fRegister: removeStatus(response),\n keyHandle,\n rfu,\n pubKey,\n };\n },\n registerData: async (params: { challenge: string }): Promise<string> => {\n const { challenge: strChallenge } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const response = await run((transport) => transport.send(0xe0, 0x03, 0x00, 0x00, challenge));\n return removeStatus(response).toString(\"hex\");\n },\n\n setPairing: async ({ pairing }) => {\n logger.info(`[device] setPairing`);\n const psdPayload = Buffer.from(pairing.blob, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(psdPayload.length, 0);\n const final = Buffer.concat([length, psdPayload]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x4e, 0x00, 0x00], final));\n },\n\n // `ephemeralKey` is unused here: the firmware signs over the ephemeral it captured in its own\n // `G_nn_initiator_eph_pubkey` global at INITIALIZE_NN_HANDSHAKE, and INS 0x55 rejects any\n // payload. The arg only exists for the stateless device-api (see api-device.ts).\n signRefreshPskAuth: async (): Promise<string> => {\n logger.info(`[device] signRefreshPskAuth`);\n const res = await run((transport) => transport.send(0xe0, 0x55, 0x00, 0x00));\n return res.slice(0, res.length - STATUS_LENGTH).toString(\"base64\");\n },\n\n finalizePskRefresh: async (params: RefreshPskData): Promise<void> => {\n logger.info(`[device] finalizePskRefresh`);\n const payload = buildPskRefreshPayload(params);\n await run((transport) => sendByChunk(transport, [0xe0, 0x53, 0x00, 0x00], payload));\n },\n startKKPatternAsResponder: async (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n }): Promise<{ handshake: string; signature: string }> => {\n logger.info(`[device] startKKPatternAsResponder`);\n const data = buildAttestation(params);\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x4c, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n const buffer = removeStatus(bufWithStatus);\n const dataLength = buffer.readInt8(0);\n return {\n handshake: buffer.slice(1, dataLength + 1).toString(\"base64\"),\n signature: buffer.slice(dataLength + 1).toString(\"base64\"),\n };\n },\n startKPatternAsResponder: async (params) => {\n logger.info(`[device] startKPatternAsResponder`);\n const data = buildAttestation(params);\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x49, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n },\n startPskSession: async (params) => {\n logger.info(`[device] startPskSession`);\n // START_PSK_SESSION (0xe0 0x50): the device reads a raw `nonce(32) || partitionId(16)`\n // payload straight from cmd->data (lc must be exactly 48) — no length prefixes and no\n // attestation. The dispatcher also rejects any non-zero P1/P2 with SW_WRONG_P1P2, so\n // both stay 0 (unlike the K handshake, which ignores P2 = ACCOUNT_MANAGER_SESSION).\n invariant(\n params.nonce.length === 64,\n `PSK nonce must be 32 bytes (64 hex chars), got ${params.nonce.length} chars`,\n );\n invariant(\n params.partitionId.length === 32,\n `partitionId must be 16 bytes (32 hex chars), got ${params.partitionId.length} chars`,\n );\n const data = Buffer.concat([\n Buffer.from(params.nonce, \"hex\"),\n Buffer.from(params.partitionId, \"hex\"),\n ]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x50, 0x00, 0x00], data));\n },\n validateVaultOperation: async (params) => {\n logger.info(`[device] validateVaultOperation`);\n const path = getPathFromPathString(PATHS.VALIDATION);\n const paths = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n let nextActionId = 1;\n let finalResponse: Buffer | null = null;\n\n while (!finalResponse) {\n const screen = Buffer.from(params.actions[nextActionId - 1]!, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(screen.length, 0);\n const data = Buffer.concat([paths, length, screen]);\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x45, 0x00, 0x00], data),\n );\n const responseType = response.readInt8(0);\n let responseStatus = response.readUInt16BE(response.length - 2);\n switch (responseType) {\n case STREAMING_NEXT_ACTION:\n nextActionId = response.readUIntBE(1, 2);\n break;\n case STREAMING_RESPONSE:\n finalResponse = response.slice(3, response.length - 2);\n while (responseStatus !== 0x9000) {\n /* v8 ignore next -- @preserve */ {\n const resp = await run((transport) => transport.send(0x00, 0xc0, 0x00, 0x00));\n responseStatus = resp.readUInt16BE(resp.length - 2);\n finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);\n }\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(`Invalid response type: ${responseType}`);\n }\n }\n return finalResponse.toString(\"base64\");\n },\n\n sendAPDU: async (apduCommand: string) => {\n const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, \"hex\")));\n return Buffer.from(res).toString(\"hex\");\n },\n getVersion: async () => {\n const res = await run((transport) => transport.send(0xb0, 0x01, 0x00, 0x00));\n const appNameLen = res.readInt8(1);\n const appVersionLen = res.readInt8(2 + appNameLen);\n const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);\n\n const appVersion = Buffer.from(appVersionHex).toString();\n\n return appVersion;\n },\n poll,\n pollApp,\n };\n return device;\n}\n","import type { AppRouter } from \"@ledgerhq/revault-api\";\nimport { createTRPCClient, httpLink, type TRPCClient } from \"@trpc/client\";\nimport type { inferRouterInputs, inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nexport type TRPCClientOptions = {\n baseUrl: string;\n debugAuthToken?: string;\n rootAuthToken?: string;\n apiAccessToken?: string;\n psdAuth?: string;\n};\n\nexport type RevaultApiTRPCClient = TRPCClient<AppRouter>;\n\nexport type RouterInputs = inferRouterInputs<AppRouter>;\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n\nexport type TRPCContext = { context: Record<string, unknown> } | undefined;\n\nexport const createClient = (options: TRPCClientOptions): RevaultApiTRPCClient => {\n const trpc = createTRPCClient<AppRouter>({\n links: [\n httpLink({\n url: `${options.baseUrl}/trpc`,\n transformer: superjson,\n headers(opts) {\n // Extract headers from the operation context\n const contextHeaders = (opts.op.context?.headers as Record<string, string>) || {};\n\n return {\n ...(options.debugAuthToken\n ? { \"x-revault-debug-auth-token\": options.debugAuthToken }\n : {}),\n ...(options.rootAuthToken\n ? { \"x-revault-root-auth-token\": options.rootAuthToken }\n : {}),\n ...(options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}),\n ...(options.apiAccessToken\n ? { Authorization: `Bearer ${options.apiAccessToken}` }\n : {}),\n // Merge in any headers passed via context\n ...contextHeaders,\n };\n },\n }),\n ],\n });\n return trpc;\n};\n","import type {\n ApiChallenge,\n ClaimedRole,\n OnboardingSeedChallenge,\n PsdChallenge,\n UserRegistrationChallenge,\n UserRegistrationChallengeResponse,\n UserRegistrationDeviceData,\n UserRegistrationResponse,\n VaultRequestResponse,\n WrappingKeyResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { createApiDevice, type Device, isPskMissingError } from \"@/device\";\nimport { createRealDevice } from \"@/device/real-device\";\nimport type { Logger } from \"@/logger\";\nimport { createClient, type RouterOutputs, type TRPCClientOptions } from \"@/trpc\";\n\nimport { buildTrpcContext } from \"../utils\";\nimport type {\n ApproveRequestParams,\n CorrelationIdOpts,\n DecorateWithApiUserAndWorkspaceUnauthenticated,\n DecorateWithDevice,\n DecorateWithDeviceAndOnboarding,\n DecorateWithDeviceAndWorkspaceUnauthenticated,\n DecorateWithWorkspaceApiAuthenticated,\n DecorateWithWorkspacePsdAuthenticated,\n DecorateWithWorkspaceUnauthenticated,\n Engine,\n EngineBase,\n EngineOptions,\n OnboardingOperationParams,\n RegisterOnboardingDeviceParams,\n WithApiAuth,\n WithApiUser,\n WithDevice,\n WithOnboarding,\n WithPsdAuth,\n WithWorkspace,\n} from \"./types\";\n\nexport { fetchAll, fetchAllCursor } from \"../utils\";\nexport type * from \"./types\";\n\nconst PSK_NONCE_BYTE_LEN = 32;\n\n// Open the per-operation secure channel matching the crypto the HSM used at Prepare, branching\n// on the challenge — never on `enable_psk_secure_channel`, even when it's on. A 32-byte `handshake`\n// (hex, 64 chars) is the PSK HKDF nonce; longer is legacy Noise-K.\nconst openSecureChannel = (\n device: Device,\n challenge: Pick<PsdChallenge, \"handshake\" | \"handshakeAttestation\" | \"partitionId\">,\n): Promise<void> => {\n if (challenge.handshake.length === PSK_NONCE_BYTE_LEN * 2) {\n return device.startPskSession({\n nonce: challenge.handshake,\n partitionId: challenge.partitionId,\n });\n }\n return device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n};\n\ntype DeviceConfidentialityKey = Awaited<ReturnType<Device[\"getConfidentialityKey\"]>>;\ntype DevicePairing = Parameters<Device[\"setPairing\"]>[0][\"pairing\"];\ntype DeviceRefreshPskData = Parameters<Device[\"finalizePskRefresh\"]>[0];\n\ntype RefreshPskInput = {\n psdEphemeralKey: string;\n psdEphemeralKeyAttestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n signature: string;\n };\n validationKeySignature: string;\n};\n\nconst pairDevice = async ({\n device,\n getPairing,\n}: {\n device: Pick<Device, \"getConfidentialityKey\" | \"setPairing\">;\n getPairing: (confidentialityKey: DeviceConfidentialityKey) => Promise<DevicePairing>;\n}): Promise<void> => {\n const confidentialityKey = await device.getConfidentialityKey();\n const pairing = await getPairing(confidentialityKey);\n await device.setPairing({ pairing });\n};\n\nconst refreshPsk = async ({\n device,\n getRefreshPskData,\n}: {\n device: Pick<\n Device,\n \"finalizePskRefresh\" | \"getAttestation\" | \"initPairingHandshake\" | \"signRefreshPskAuth\"\n >;\n getRefreshPskData: (input: RefreshPskInput) => Promise<DeviceRefreshPskData>;\n}): Promise<void> => {\n // Shared refresh sub-chain: 0x46 (device NN init) + 0x55 (validation-key auth signature)\n // → HSM refresh-psk (single read-only re-delivery) → 0x53 (finalize). The HSM verifies\n // the device-attested ephemeral key and the validation-key signature, so we stitch the\n // per-ephemeral signature from INITIALIZE_NN_HANDSHAKE onto the device's static attestation\n // chain (INS_GET_ATTESTATION_CERTIFICATE) and pass the SIGN_REFRESH_PSK_AUTH signature\n // alongside. initPairingHandshake (0x46) must resolve first: the soft-device\n // signRefreshPskAuth needs the ephemeral it returns, and the firmware FSM requires 0x46\n // before 0x55.\n const eph = await device.initPairingHandshake();\n const [deviceAttestation, validationKeySignature] = await Promise.all([\n device.getAttestation(),\n device.signRefreshPskAuth({ ephemeralKey: eph.pubKey }),\n ]);\n const refresh = await getRefreshPskData({\n psdEphemeralKey: Buffer.from(eph.pubKey, \"hex\").toString(\"base64\"),\n psdEphemeralKeyAttestation: {\n codeHash: deviceAttestation.attestation.codeHash,\n attestationPub: deviceAttestation.attestation.attestationPub,\n certificate: deviceAttestation.attestation.certificate,\n signature: eph.signature,\n },\n validationKeySignature,\n });\n await device.finalizePskRefresh(refresh);\n};\n\nasync function genericRegister<T>({\n device,\n name,\n role,\n getChallenge,\n submitChallenge,\n onScreenDisplayed,\n}: {\n device: Device;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n getChallenge: (p: {\n pubKey: string;\n deviceData: UserRegistrationDeviceData;\n }) => Promise<UserRegistrationChallenge>;\n submitChallenge: (p: {\n pubKey: string;\n challengeResponse: UserRegistrationChallengeResponse;\n }) => Promise<T>;\n onScreenDisplayed?: () => void | Promise<void>;\n}): Promise<T> {\n const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([\n device.getAttestation(),\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n const ephemeralPubKey = await device.initPairingHandshake();\n const deviceData: UserRegistrationDeviceData = {\n name,\n pubKey: u2fPubKey.pubKey,\n psdModel: \"STAX\",\n confidentialityKey: confidentialityKey.pubKey,\n psdEphemeralKey: ephemeralPubKey.pubKey,\n psdEphemeralKeyAttestation: {\n ...attestation.attestation,\n signature: ephemeralPubKey.signature,\n },\n };\n const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });\n const pairingPayload = await device.finalizePairingHandshake({\n handshake: challenge.handshake,\n partitionId: challenge.ciphertext,\n handshakeAttestation: challenge.handshakeAttestation,\n });\n await onScreenDisplayed?.();\n const register = await device.register({\n challenge: challenge.challenge,\n u2fRegisterData: challenge.u2fRegisterData,\n name,\n role,\n });\n const validationPubKey = await device.getValidationPubKey();\n const registerData = await device.registerData({ challenge: challenge.challenge });\n const attestationOffset = 67 + register.u2fRegister.readInt8(66);\n const u2fRegister = Buffer.concat([\n register.u2fRegister.slice(0, attestationOffset),\n Buffer.from([attestation.buffer.length]),\n attestation.buffer,\n register.u2fRegister.slice(attestationOffset),\n ]).toString(\"hex\");\n const challengeResponse: UserRegistrationChallengeResponse = {\n registerData,\n certificate: {\n ...attestation.attestation,\n signature: validationPubKey.signature,\n },\n u2fRegister,\n u2fKeyHandle: register.keyHandle.toString(\"hex\"),\n validationKey: validationPubKey.pubKey,\n pairingPayload,\n };\n return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });\n}\n\nexport function createEngine(options: EngineOptions, logger: Logger): Engine {\n const clientOptions: TRPCClientOptions = {\n baseUrl: options.baseUrl,\n };\n const client = createClient(clientOptions);\n const apiDevice = createApiDevice(options, logger);\n\n const base: EngineBase = {\n client,\n createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),\n __options: options,\n };\n\n const withDeviceIndex: Engine[\"withDeviceIndex\"] = function <T>(\n this: Engine<T>,\n deviceIndex: number,\n ) {\n const device = apiDevice.with(deviceIndex);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withTransportId: Engine[\"withTransportId\"] = function <T>(\n this: Engine<T>,\n transportId: string,\n ) {\n const device = createRealDevice({ transportId }, logger);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withApiUser: Engine[\"withApiUser\"] = function <T>(this: Engine<T>) {\n const withApiUser: WithApiUser = { __isApiUser: true };\n return decorateEngine({ ...this, ...withApiUser } as Engine<T & WithApiUser>);\n };\n\n const withWorkspace: Engine[\"withWorkspace\"] = function <T>(\n this: Engine<T>,\n workspaceName: string,\n ) {\n const withWorkspace: WithWorkspace = { __workspaceName: workspaceName };\n return decorateEngine({ ...this, ...withWorkspace } as Engine<T & WithWorkspace>);\n };\n\n const withOnboarding: Engine[\"withOnboarding\"] = function <T>(\n this: Engine<T>,\n onboardingId: string,\n ) {\n const withOnboarding: WithOnboarding = { __onboardingId: onboardingId };\n return decorateEngine({ ...this, ...withOnboarding } as Engine<T & WithOnboarding>);\n };\n\n function decorateEngine<T>(\n engine: Engine<\n T &\n Partial<\n WithDevice & WithOnboarding & WithWorkspace & WithPsdAuth & WithApiUser & WithApiAuth\n >\n >,\n ): Engine<T> {\n function decorate<TEnhanced, TDecoration>(\n decorator: (engine: EngineBase & TEnhanced) => TDecoration,\n ): void {\n Object.assign(engine, decorator(engine as EngineBase & TEnhanced));\n }\n\n // DecorateWithDevice\n // -------------------------------------------------------------------------\n if (engine.device) {\n decorate<WithDevice, DecorateWithDevice<T>>(\n (engine) =>\n ({\n getWorkspaces: async (): Promise<string[]> => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });\n return workspaceNames;\n },\n\n getWorkspacesForSso: async (): Promise<\n RouterOutputs[\"auth\"][\"sso\"][\"findWorkspaces\"][\"workspaces\"]\n > => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaces } = await client.auth.sso.findWorkspaces.query({ pubKey });\n return workspaces;\n },\n }) satisfies DecorateWithDevice<T>,\n );\n }\n\n // DecorateWithWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {\n decorate<WithWorkspace, DecorateWithWorkspaceUnauthenticated<T>>((engine) => {\n const { __workspaceName } = engine;\n return {\n withPsdToken: function <T>(this: Engine<T>, token: string): Engine<T & WithPsdAuth> {\n const withPsdAuth: WithPsdAuth = { __psdToken: token };\n const psdAuth = `${__workspaceName}:${token}`;\n const client = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client, ...withPsdAuth } as Engine<T & WithPsdAuth>);\n },\n } satisfies DecorateWithWorkspaceUnauthenticated<T>;\n });\n }\n\n // DecorateWithDeviceAndOnboarding\n // -------------------------------------------------------------------------\n if (engine.device && engine.__onboardingId) {\n decorate<WithDevice & WithOnboarding, DecorateWithDeviceAndOnboarding>((engine) => {\n const { device, client, __onboardingId } = engine;\n\n // Whether PSK secure-channel provisioning is enabled for this onboarding's workspace.\n // On any failure default to false (legacy Noise-K) so a flag-read hiccup can't break\n // onboarding by forcing the PSK path.\n const isPskEnabled = async (): Promise<boolean> => {\n try {\n const enabled = await client.onboarding.getPskFeatureFlag.query({\n onboardingId: __onboardingId,\n });\n return enabled === true;\n } catch {\n return false;\n }\n };\n\n // Drive the device's pairing record + PSK to a fully-provisioned state.\n // Three-way switch on hasPairing() (when PSK is enabled):\n // - \"OK\" → nothing to do.\n // - \"NO_PAIRING\" → run the full pairing chain, then deliver a PSK via refresh.\n // - \"PSK_MISSING\" → pairing already exists; only run the PSK refresh sub-chain.\n // When PSK is disabled we reproduce the pre-PSK flow: pair only on NO_PAIRING, never run\n // the refresh sub-chain, and treat PSK_MISSING as a no-op (the missing-PSK is discarded).\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n const pskEnabled = await isPskEnabled();\n let pubKeyPromise: Promise<string> | undefined;\n const getPubKey = async (): Promise<string> => {\n pubKeyPromise ??= device.getU2FPubKey().then(({ pubKey }) => pubKey);\n return pubKeyPromise;\n };\n const pairCurrentDevice = async (): Promise<void> => {\n const pubKey = await getPubKey();\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.onboarding.pairDevicePartition.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data: {\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n },\n }),\n });\n };\n const refreshCurrentPsk = async (): Promise<void> => {\n const pubKey = await getPubKey();\n await refreshPsk({\n device,\n getRefreshPskData: (data) =>\n client.onboarding.refreshPsk.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data,\n }),\n });\n };\n\n await match([status, pskEnabled] as const)\n .with([\"NO_PAIRING\", false], async () => {\n await pairCurrentDevice();\n })\n .with([\"NO_PAIRING\", true], async () => {\n await pairCurrentDevice();\n await refreshCurrentPsk();\n })\n .with([\"PSK_MISSING\", false], async () => {\n // PSK FF is disabled and the vault-app returns PSK_MISSING => we can discard it\n return;\n })\n .with([\"PSK_MISSING\", true], async () => {\n await refreshCurrentPsk();\n })\n .exhaustive();\n }\n\n return {\n claimDevice: async (params: { role: ClaimedRole; deviceName: string }): Promise<void> => {\n const { role, deviceName } = params;\n const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await client.onboarding.claimDevice.mutate({\n onboardingId: __onboardingId,\n claim: { role, pubKey, deviceName, confidentialityKey },\n });\n },\n\n collectWrappingKeyFragment: async (\n wrappingKey: WrappingKeyResponse,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await device.openSession({\n secureChannel: {\n pubKey: wrappingKey.ephemeralPubKey,\n certificate: wrappingKey.ephemeralCertificate,\n },\n });\n const { attestation } = await device.getAttestation();\n await params?.onScreenDisplayed?.();\n const blob = await device.generateWrappingKeyFragment();\n await client.onboarding.submitWrappingKeyFragment.mutate({\n pubKey,\n onboardingId: __onboardingId,\n fragment: {\n blob,\n ephemeralPubKey: confidentialityKey.pubKey,\n ephemeralCertificate: {\n ...attestation,\n signature: confidentialityKey.signature,\n },\n },\n });\n },\n\n registerDevice: async (\n registerParams: RegisterOnboardingDeviceParams,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const { role, name } = registerParams;\n const getChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.generateMasterAdminRegistrationChallenge\n : client.onboarding.generateSharedOwnerRegistrationChallenge;\n const submitChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.submitMasterAdminRegistration\n : client.onboarding.submitSharedOwnerRegistration;\n await genericRegister({\n device: device,\n name,\n role,\n getChallenge: ({ pubKey, deviceData }) =>\n getChallengeMutation.mutate({\n onboardingId: __onboardingId,\n pubKey,\n deviceData,\n }),\n submitChallenge: ({ pubKey, challengeResponse }) =>\n submitChallengeMutation.mutate({\n onboardingId: engine.__onboardingId,\n pubKey,\n // FIXME this should be renamed to `challengeResponse` on backend side\n response: challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n\n reviewSharedOwner: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitReviewByMasterAdminSignature.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n reviewExternalSigners: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitExternalSignersRegistration.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n collectSeedFragment: async (\n challenge: OnboardingSeedChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const [{ pubKey }, { attestation }] = await Promise.all([\n device.getU2FPubKey(),\n device.getAttestation(),\n ]);\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const challengeResponse = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n const kkPattern = await device.startKKPatternAsResponder({\n partitionId: challenge.partitionId,\n handshake: challenge.kkHandshake,\n handshakeAttestation: challenge.kkHandshakeAttestation,\n });\n const approverBlob = await device.generateSeedFragment();\n await client.onboarding.submitSeedFragment.mutate({\n onboardingId: __onboardingId,\n pubKey,\n seedFragment: {\n challengeResponse,\n approverBlob,\n handshake: kkPattern.handshake,\n handshakeAttestation: {\n ...attestation,\n signature: kkPattern.signature,\n },\n },\n });\n },\n } satisfies DecorateWithDeviceAndOnboarding;\n });\n }\n\n // DecorateWithDeviceAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && !engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithDeviceAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { device, client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n opts?: {\n validityDurationSecs?: number;\n onScreenDisplayed?: () => void | Promise<void>;\n correlationId?: string;\n },\n ): Promise<Engine<T & WithPsdAuth>> {\n const { pubKey } = await device.getU2FPubKey();\n const challenge = await client.auth.psd.generateChallenge.mutate(\n {\n pubKey,\n workspaceName: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n await opts?.onScreenDisplayed?.();\n const authentication = await device.authenticate({\n challenge,\n workspaceName: __workspaceName,\n });\n const authPayload = {\n workspaceName: __workspaceName,\n pubKey,\n authentication,\n challengeId: challenge.challengeId,\n validityDurationSecs: opts?.validityDurationSecs,\n };\n const { token } = await client.auth.psd.authenticate.mutate(\n { ...authPayload },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withPsdAuth: WithPsdAuth = {\n __psdToken: token,\n };\n const psdAuth = `${engine.__workspaceName}:${token}`;\n const __authClient = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client: __authClient, ...withPsdAuth } as Engine<\n T & WithPsdAuth\n >);\n },\n\n register: (\n registration: UserRegistrationResponse,\n params?: OnboardingOperationParams,\n ): Promise<UserRegistrationResponse> => {\n return genericRegister({\n device,\n name: registration.name,\n role: registration.role,\n getChallenge: async ({ deviceData }) => {\n const challenge = await client.userRegistrations.generateChallenge.mutate({\n id: registration.id,\n workspaceName: __workspaceName,\n deviceData,\n });\n return challenge;\n },\n submitChallenge: ({ challengeResponse }) =>\n client.userRegistrations.submitChallenge.mutate({\n workspaceName: __workspaceName,\n id: registration.id,\n challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n } satisfies DecorateWithDeviceAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithApiUserAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {\n decorate<WithWorkspace & WithApiUser, DecorateWithApiUserAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n credentials: {\n apiKeyId: string;\n apiKeySecret: string;\n },\n opts?: { correlationId?: string },\n ): Promise<Engine<T & WithApiAuth>> {\n const res = await client.auth.authenticate.mutate(\n {\n apiKeyId: credentials.apiKeyId,\n apiKeySecret: credentials.apiKeySecret,\n workspace: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withApiAuth: WithApiAuth = {\n __apiAuth: res,\n };\n const __authClient = engine.createClient({ apiAccessToken: res.accessToken });\n return decorateEngine({ ...this, client: __authClient, ...withApiAuth } as Engine<\n T & WithApiAuth\n >);\n },\n } satisfies DecorateWithApiUserAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithWorkspacePsdAuthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithWorkspacePsdAuthenticated>((engine) => {\n const { client, device } = engine;\n\n // Whether PSK secure-channel provisioning is enabled for this workspace. On any failure\n // default to false (legacy Noise-K) so a flag-read hiccup can't force the PSK path.\n const isPskEnabled = async (): Promise<boolean> => {\n try {\n return (await client.debug.getPskFeatureFlag.query()) === true;\n } catch {\n return false;\n }\n };\n\n // Drive the device's pairing record + PSK to a fully-provisioned state. Same tri-state\n // switch as the onboarding decorator; routes through `client.debug.*` instead of\n // `client.onboarding.*` and pulls workspace context implicitly from `__psdToken`.\n // When PSK is disabled we reproduce the pre-PSK flow: pair only on NO_PAIRING, never run\n // the refresh sub-chain, and treat PSK_MISSING as a no-op (the missing-PSK is discarded).\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n const pskEnabled = await isPskEnabled();\n const pairCurrentDevice = async (): Promise<void> => {\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.debug.pairDevicePartition.mutate({\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n }),\n });\n };\n const refreshCurrentPsk = async (): Promise<void> => {\n await refreshPsk({\n device,\n getRefreshPskData: (data) => client.debug.refreshPsk.mutate(data),\n });\n };\n\n await match([status, pskEnabled] as const)\n .with([\"NO_PAIRING\", false], async () => {\n await pairCurrentDevice();\n })\n .with([\"NO_PAIRING\", true], async () => {\n await pairCurrentDevice();\n await refreshCurrentPsk();\n })\n .with([\"PSK_MISSING\", false], async () => {\n // PSK FF is disabled and the vault-app returns PSK_MISSING => we can discard it\n return;\n })\n .with([\"PSK_MISSING\", true], async () => {\n await refreshCurrentPsk();\n })\n .exhaustive();\n }\n\n const approveChallenge = async (\n challenge: PsdChallenge,\n params?: ApproveRequestParams,\n ): Promise<string> => {\n await enforcePairing();\n try {\n await openSecureChannel(device, challenge);\n } catch (err) {\n if (!isPskMissingError(err)) throw err;\n // PSK disabled = SElf not yet migrated. The HSM sends a Noise-K challenge; a\n // migrated device may emit SW_PSK_MISSING alongside a still-valid K-pattern session.\n // Discard and proceed — the channel is open.\n if (!(await isPskEnabled())) {\n logger.warning(\"Discarding SW_PSK_MISSING: PSK secure channel is disabled\");\n } else {\n // Defense-in-depth: a session opened before the PSK was wiped still hits\n // SW_PSK_MISSING here. Re-run enforcePairing() — it now sees PSK_MISSING and drives\n // the refresh sub-chain — then retry the secure-channel APDU once.\n await enforcePairing();\n await openSecureChannel(device, challenge);\n }\n }\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n return signature;\n };\n\n return {\n approve: async (\n request: VaultRequestResponse,\n params?: ApproveRequestParams,\n ): Promise<VaultRequestResponse> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n if (challenge.challengeType === \"PSD\") {\n const signature = await approveChallenge(challenge, params);\n await params?.onPsdChallengeSigned?.();\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"PSD\", signature },\n },\n buildTrpcContext(params),\n );\n }\n if (challenge.challengeType === \"SOFT\") {\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"SOFT\" },\n },\n buildTrpcContext(params),\n );\n }\n throw new Error(\"Challenge type must be either PSD or SOFT\");\n },\n\n approveChallenge,\n\n reject: (\n request: VaultRequestResponse,\n opts?: CorrelationIdOpts,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate(\n { id: request.id, data: null },\n buildTrpcContext(opts),\n );\n },\n } satisfies DecorateWithWorkspacePsdAuthenticated;\n });\n }\n\n // DecorateWithWorkspaceApiAuthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__apiAuth) {\n decorate<WithWorkspace & WithApiAuth, DecorateWithWorkspaceApiAuthenticated>((engine) => {\n const { client } = engine;\n return {\n getChallenge: async (request: VaultRequestResponse): Promise<ApiChallenge[\"payload\"]> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"API\", \"Challenge type must be API\");\n return challenge.payload;\n },\n\n approve: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n\n reject: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n } satisfies DecorateWithWorkspaceApiAuthenticated;\n });\n }\n\n return engine;\n }\n\n return {\n ...base,\n withDeviceIndex,\n withTransportId,\n withApiUser,\n withWorkspace,\n withOnboarding,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"engine.cjs","names":["PAGINATED_STATUS","LockedDeviceError","isTransportStatusError","DisconnectedDevice","lastValueFrom","withDevicePolling","from","PATHS","APPID_VAULT_ADMINISTRATOR","STR_ROLES","SCRIPT_IDS","createTRPCClient","httpLink","createApiDevice","buildTrpcContext","isPskMissingError"],"sources":["../src/device/real-device.ts","../src/trpc.ts","../src/engine/index.ts"],"sourcesContent":["import { DisconnectedDevice, LockedDeviceError } from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport type { HsmCertificate, PubKey, RefreshPskData } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { from, lastValueFrom } from \"rxjs\";\n\nimport type { Logger } from \"@/logger\";\n\nimport {\n APPID_VAULT_ADMINISTRATOR,\n PAGINATED_STATUS,\n PATHS,\n SCRIPT_IDS,\n STATUS_LENGTH,\n STR_ROLES,\n STREAMING_NEXT_ACTION,\n STREAMING_RESPONSE,\n} from \"./constants\";\nimport { withDevicePolling } from \"./device-access\";\nimport type { Device, PairingStatus } from \"./types\";\nimport { isTransportStatusError } from \"./utils\";\n\nconst MAX_CHUNK_LENGTH = 250;\n\ntype Options = {\n transportId: string;\n};\n\nconst getPathFromPathString = (pathString: string): number[] => {\n const parts = pathString.split(\"'/\").map((part) => Number.parseInt(part, 10));\n return parts.map((part) => (part | 0x80000000) >>> 0);\n};\n\nconst splitChunks = (chunk: number, buffer: Buffer): Buffer[] => {\n const chunks = [];\n for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {\n chunks.push(buffer.slice(i, i + size));\n }\n return chunks;\n};\n\nconst removeStatus = (result: Buffer): Buffer => result.slice(0, result.length - STATUS_LENGTH);\n\nconst sendByChunk = async (\n transport: Transport,\n command: number[], // eg [0xe0, 0x45, 0x00, 0x00]\n data: Buffer,\n chunkSize: number = MAX_CHUNK_LENGTH,\n): Promise<Buffer> => {\n const chunks = splitChunks(chunkSize, data);\n let response = Buffer.from([]);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const apdu = [...command];\n // command is 0xe0,0x45,0x00,0x00 for first chunk, then it's 0xe0,0x45,0x80,0x00\n /* v8 ignore next -- @preserve */\n apdu[2] = i && 0x80;\n response = (await transport.send(apdu[0]!, apdu[1]!, apdu[2], apdu[3]!, chunk, [\n 0x9000,\n ...PAGINATED_STATUS,\n ])) as Buffer<ArrayBuffer>;\n }\n return response;\n};\n\nconst buildAttestation = (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n}): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const cliMsgBuffer = Buffer.from(params.handshake, \"hex\");\n const cliMsgLengthBuffer = Buffer.alloc(1);\n cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);\n\n const pidBuffer = Buffer.from(params.partitionId, \"hex\");\n const pidLengthBuffer = Buffer.alloc(1);\n pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n cliMsgLengthBuffer,\n cliMsgBuffer,\n certChainDataLengthBuff,\n certChainData,\n pidLengthBuffer,\n pidBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n const toSend = Buffer.concat([totalLengthBuffer, data]);\n\n return toSend;\n};\n\n// Wire-format builder for FINALIZE_PSK_REFRESH (`0xE0 0x53`). Same layout as `buildAttestation`\n// (consumed by the device's `parse_nn_handshake_payload`), but the trailing TLV carries the\n// encrypted PairingPayload from `RefreshPsk` instead of a partition ID.\n//\n// Layout after the leading 2-byte total length:\n// [1] handshake length (the NN responder handshake, written from its actual decoded length)\n// [N] handshake bytes\n// [2] cert-chain-data length (BE)\n// [1] handshake-cert (DER signature) length\n// [N] handshake-cert bytes\n// [65] vault attestation pubkey (raw 0x04|x|y, no length prefix)\n// [1] att-cert length\n// [M] att-cert bytes\n// [1] ciphered-payload length\n// [K] encrypted PairingPayload bytes\nconst buildPskRefreshPayload = (params: RefreshPskData): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const handshakeBuffer = Buffer.from(params.handshake, \"base64\");\n invariant(\n handshakeBuffer.length <= 255,\n `PSK refresh handshake too long: ${handshakeBuffer.length} bytes (max 255)`,\n );\n const handshakeLengthBuffer = Buffer.alloc(1);\n handshakeLengthBuffer.writeUInt8(handshakeBuffer.length, 0);\n\n const encryptedPayloadBuffer = Buffer.from(params.encryptedPairingPayload, \"base64\");\n invariant(\n encryptedPayloadBuffer.length <= 255,\n `PSK encrypted payload too long: ${encryptedPayloadBuffer.length} bytes (max 255)`,\n );\n const encryptedPayloadLengthBuffer = Buffer.alloc(1);\n encryptedPayloadLengthBuffer.writeUInt8(encryptedPayloadBuffer.length, 0);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n handshakeLengthBuffer,\n handshakeBuffer,\n certChainDataLengthBuff,\n certChainData,\n encryptedPayloadLengthBuffer,\n encryptedPayloadBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n return Buffer.concat([totalLengthBuffer, data]);\n};\n\ntype RetryOnError = (err: Error) => boolean;\n/* v8 ignore next -- @preserve */\nconst genericRetryOnError: RetryOnError = (err) => {\n // device is locked\n if (err instanceof LockedDeviceError) return true;\n // user is on dashboard when receiving a Vault app apdu\n if (isTransportStatusError(err) && err.statusCode === 0x6d09) return true;\n // VG-24797 error that can happen in BLE in some situations (still unclear)\n if (err instanceof DisconnectedDevice) return true;\n\n // for everything else, we don't want to retry\n return false;\n};\n\nexport function createRealDevice(options: Options, logger: Logger): Device {\n const { transportId } = options;\n\n async function run<T>(\n job: (transport: Transport) => Promise<T>,\n retryOnError: RetryOnError = genericRetryOnError,\n ): Promise<T> {\n return lastValueFrom(\n withDevicePolling(transportId)<T>((transport) => from(job(transport)), retryOnError),\n );\n }\n\n /* v8 ignore next -- @preserve */\n const noRetry = (): boolean => false;\n /* v8 ignore next -- @preserve */\n const alwaysRetry = (): boolean => true;\n const poll = async (\n opts: { retryOnError?: RetryOnError } = {},\n ): Promise<{ isAppOpened: boolean }> => {\n // waiting for device to be turned on\n await run(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n async (_transport) => {},\n opts.retryOnError ?? alwaysRetry,\n );\n // checking if app is opened: should return directly on getPubKey\n try {\n await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });\n return { isAppOpened: true };\n } catch (err) {\n if (isTransportStatusError(err) && genericRetryOnError(err)) {\n return { isAppOpened: false };\n }\n throw err;\n }\n };\n\n const pollApp = async (appName: string): Promise<string> => {\n const res = await run((transport) =>\n transport.send(0xe0, 0xd8, 0x00, 0x00, Buffer.from(appName, \"utf8\")),\n );\n // little delay to give time to the app to be fully opened\n await new Promise((r) => setTimeout(r, 1e3));\n return res.toString(\"hex\");\n };\n\n const getPublicKey = async (\n pathString: string,\n { secp256k1, retryOnError }: { secp256k1: boolean; retryOnError?: RetryOnError },\n ): Promise<{ pubKey: string; signature: string }> => {\n logger.info(`[device] getPublicKey (${pathString})`);\n const path = getPathFromPathString(pathString);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const curve = secp256k1 ? 0x01 : 0x02;\n const response = await run(\n (transport) => transport.send(0xe0, 0x40, curve, 0x00, data),\n retryOnError ?? genericRetryOnError,\n );\n const pubKeyLength = response.readInt8(0);\n const pubKey = response\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = response\n .slice(pubKeyLength + 1, response.length - STATUS_LENGTH)\n .toString(\"base64\");\n return { pubKey, signature };\n };\n\n const device: Device = {\n authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {\n logger.info(`[device] Authenticate`);\n invariant(role !== \"READ_ONLY_API_KEY\", \"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n const nameBuffer = Buffer.from(name);\n const workspaceBuffer = Buffer.from(workspaceName);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([nameBuffer.length]),\n nameBuffer,\n Buffer.from([workspaceBuffer.length]),\n workspaceBuffer,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([\n Buffer.from(challenge, \"base64\"),\n applicationBuffer,\n Buffer.from([keyHandle.length]),\n Buffer.from(keyHandle, \"hex\"),\n keyHandleDataLength,\n keyHandleData,\n ]);\n\n const authentication = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x02, 0x00, 0x00], data),\n );\n\n return removeStatus(authentication).toString(\"hex\");\n },\n\n finalizePairingHandshake: async (params: {\n handshake: string;\n partitionId: string;\n handshakeAttestation: HsmCertificate;\n }): Promise<string> => {\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x47, 0x00, 0x02], buildAttestation(params)),\n );\n return removeStatus(bufWithStatus).toString(\"hex\");\n },\n\n generateSeedFragment: async (): Promise<string> => {\n logger.info(`[device] generateSeedFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x00, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n generateWrappingKeyFragment: async (): Promise<string> => {\n logger.info(`[device] generateWrappingKeyFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x01, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n getAttestation: async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x41, 0x00, 0x00));\n const buffer = removeStatus(bufWithStatus);\n const certLen = buffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: buffer.slice(0, 32).toString(\"base64\"),\n attestationPub: buffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer,\n };\n },\n getConfidentialityKey: async () => {\n logger.info(`[device] getConfidentialityKey`);\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x4d, 0x00, 0x00));\n const buf = removeStatus(bufWithStatus);\n const keyLength = buf[0]!;\n const key = buf.slice(1, 1 + keyLength);\n const sig = buf.slice(1 + keyLength + 1);\n return {\n confidentialityKeyCurve25519: key.toString(\"hex\"),\n confidentialityKeySignature: sig.toString(\"hex\"),\n };\n },\n getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),\n getDeviceUserId: async (): Promise<string> => {\n logger.info(`[device] getDeviceUserId`);\n const response = await run((transport) => transport.send(0xe0, 0x52, 0x00, 0x00));\n return removeStatus(response).toString(\"hex\").toUpperCase();\n },\n getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),\n getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),\n hasPairing: async (): Promise<PairingStatus> => {\n logger.info(`[device] hasPairing`);\n const apdu = [0xe0, 0x51, 0x00, 0x00, 0xb5];\n const res = await run((transport) => transport.exchange(Buffer.from(apdu)));\n\n // GET_PARTITION_IDS returns the partition list followed by a 2-byte SW. Inspect only\n // the trailing SW; the device may return data alongside non-`9000` SWs (notably 0x6065\n // — see below).\n const swHex = res.subarray(res.length - 2).toString(\"hex\");\n\n // 6f45 => no partition ID on the device (SW_NO_PARTITION_ID).\n // 6a87 => TEMPORARY hack: some firmware revs don't implement the APDU and return\n // \"incorrect length\"; treat as no pairing so revault drives the full pair-from-\n // scratch flow.\n if (swHex === \"6f45\" || swHex === \"6a87\") return \"NO_PAIRING\";\n\n // 6065 => SW_PSK_MISSING: a valid pairing record exists but its PSK field is the all-\n // zero sentinel. Skip the full pairing chain and run the refresh sub-chain.\n if (swHex === \"6065\") return \"PSK_MISSING\";\n\n // Anything else (typically 9000) => fully provisioned pairing with PSK.\n return \"OK\";\n },\n\n initPairingHandshake: async (): Promise<{ pubKey: string; signature: string }> => {\n const res = await run((transport) => transport.send(0xe0, 0x46, 0x00, 0x00));\n const pubKeyLength = res.readInt8(0);\n const pubKey = res\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString(\"base64\");\n return { pubKey, signature };\n },\n\n openSession: async (params: {\n secureChannel: { pubKey: PubKey; certificate: HsmCertificate };\n }): Promise<void> => {\n logger.info(`[device] openSession`);\n const { secureChannel } = params;\n\n const path = getPathFromPathString(PATHS.CONFIDENTIALITY);\n const dataDerivation = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n const pubKey = Buffer.from(secureChannel.pubKey, \"hex\");\n\n const sigBuffer = Buffer.from(secureChannel.certificate.signature, \"base64\");\n const attestationPubBuffer = Buffer.from(secureChannel.certificate.attestationPub, \"base64\");\n const certBuffer = Buffer.from(secureChannel.certificate.certificate, \"base64\");\n const attestation = Buffer.concat([\n Buffer.from([sigBuffer.length]),\n sigBuffer,\n attestationPubBuffer,\n Buffer.from([certBuffer.length]),\n certBuffer,\n ]);\n\n const lengthAttestation = Buffer.alloc(2);\n lengthAttestation.writeUInt16BE(attestation.length, 0);\n\n const data = Buffer.concat([dataDerivation, pubKey, lengthAttestation, attestation]);\n\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x42, 0x00, SCRIPT_IDS.INIT_SESSION], data),\n );\n },\n\n register: async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n invariant(applicationBuf.length === 32, \"application hex is expected to have 32 bytes\");\n\n const userNameBuff = Buffer.from(name);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([userNameBuff.length]),\n userNameBuff,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);\n\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x01, 0x00, 0x00], data),\n );\n\n let i = 0;\n const rfu = response.slice(i, i + 1)[0]!;\n i += 1;\n const pubKey = response.slice(i, i + 65).toString(\"hex\");\n i += 65;\n const keyHandleLength = response.slice(i, i + 1)[0]!;\n i++;\n const keyHandle = response.slice(i, i + keyHandleLength);\n i += keyHandleLength;\n return {\n u2fRegister: removeStatus(response),\n keyHandle,\n rfu,\n pubKey,\n };\n },\n registerData: async (params: { challenge: string }): Promise<string> => {\n const { challenge: strChallenge } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const response = await run((transport) => transport.send(0xe0, 0x03, 0x00, 0x00, challenge));\n return removeStatus(response).toString(\"hex\");\n },\n\n setPairing: async ({ pairing }) => {\n logger.info(`[device] setPairing`);\n const psdPayload = Buffer.from(pairing.blob, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(psdPayload.length, 0);\n const final = Buffer.concat([length, psdPayload]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x4e, 0x00, 0x00], final));\n },\n\n // `ephemeralKey` is unused here: the firmware signs over the ephemeral it captured in its own\n // `G_nn_initiator_eph_pubkey` global at INITIALIZE_NN_HANDSHAKE, and INS 0x55 rejects any\n // payload. The arg only exists for the stateless device-api (see api-device.ts).\n signRefreshPskAuth: async (): Promise<string> => {\n logger.info(`[device] signRefreshPskAuth`);\n const res = await run((transport) => transport.send(0xe0, 0x55, 0x00, 0x00));\n return res.slice(0, res.length - STATUS_LENGTH).toString(\"base64\");\n },\n\n finalizePskRefresh: async (params: RefreshPskData): Promise<void> => {\n logger.info(`[device] finalizePskRefresh`);\n const payload = buildPskRefreshPayload(params);\n await run((transport) => sendByChunk(transport, [0xe0, 0x53, 0x00, 0x00], payload));\n },\n startKKPatternAsResponder: async (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n }): Promise<{ handshake: string; signature: string }> => {\n logger.info(`[device] startKKPatternAsResponder`);\n const data = buildAttestation(params);\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x4c, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n const buffer = removeStatus(bufWithStatus);\n const dataLength = buffer.readInt8(0);\n return {\n handshake: buffer.slice(1, dataLength + 1).toString(\"base64\"),\n signature: buffer.slice(dataLength + 1).toString(\"base64\"),\n };\n },\n startKPatternAsResponder: async (params) => {\n logger.info(`[device] startKPatternAsResponder`);\n const data = buildAttestation(params);\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x49, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n },\n startPskSession: async (params) => {\n logger.info(`[device] startPskSession`);\n // START_PSK_SESSION (0xe0 0x50): the device reads a raw `nonce(32) || partitionId(16)`\n // payload straight from cmd->data (lc must be exactly 48) — no length prefixes and no\n // attestation. The dispatcher also rejects any non-zero P1/P2 with SW_WRONG_P1P2, so\n // both stay 0 (unlike the K handshake, which ignores P2 = ACCOUNT_MANAGER_SESSION).\n invariant(\n params.nonce.length === 64,\n `PSK nonce must be 32 bytes (64 hex chars), got ${params.nonce.length} chars`,\n );\n invariant(\n params.partitionId.length === 32,\n `partitionId must be 16 bytes (32 hex chars), got ${params.partitionId.length} chars`,\n );\n const data = Buffer.concat([\n Buffer.from(params.nonce, \"hex\"),\n Buffer.from(params.partitionId, \"hex\"),\n ]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x50, 0x00, 0x00], data));\n },\n validateVaultOperation: async (params) => {\n logger.info(`[device] validateVaultOperation`);\n const path = getPathFromPathString(PATHS.VALIDATION);\n const paths = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n let nextActionId = 1;\n let finalResponse: Buffer | null = null;\n\n while (!finalResponse) {\n const screen = Buffer.from(params.actions[nextActionId - 1]!, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(screen.length, 0);\n const data = Buffer.concat([paths, length, screen]);\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x45, 0x00, 0x00], data),\n );\n const responseType = response.readInt8(0);\n let responseStatus = response.readUInt16BE(response.length - 2);\n switch (responseType) {\n case STREAMING_NEXT_ACTION:\n nextActionId = response.readUIntBE(1, 2);\n break;\n case STREAMING_RESPONSE:\n finalResponse = response.slice(3, response.length - 2);\n while (responseStatus !== 0x9000) {\n /* v8 ignore next -- @preserve */ {\n const resp = await run((transport) => transport.send(0x00, 0xc0, 0x00, 0x00));\n responseStatus = resp.readUInt16BE(resp.length - 2);\n finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);\n }\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(`Invalid response type: ${responseType}`);\n }\n }\n return finalResponse.toString(\"base64\");\n },\n\n sendAPDU: async (apduCommand: string) => {\n const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, \"hex\")));\n return Buffer.from(res).toString(\"hex\");\n },\n getVersion: async () => {\n const res = await run((transport) => transport.send(0xb0, 0x01, 0x00, 0x00));\n const appNameLen = res.readInt8(1);\n const appVersionLen = res.readInt8(2 + appNameLen);\n const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);\n\n const appVersion = Buffer.from(appVersionHex).toString();\n\n return appVersion;\n },\n poll,\n pollApp,\n };\n return device;\n}\n","import type { AppRouter } from \"@ledgerhq/revault-api\";\nimport { createTRPCClient, httpLink, type TRPCClient } from \"@trpc/client\";\nimport type { inferRouterInputs, inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nexport type TRPCClientOptions = {\n baseUrl: string;\n debugAuthToken?: string;\n rootAuthToken?: string;\n apiAccessToken?: string;\n psdAuth?: string;\n};\n\nexport type RevaultApiTRPCClient = TRPCClient<AppRouter>;\n\nexport type RouterInputs = inferRouterInputs<AppRouter>;\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n\nexport type TRPCContext = { context: Record<string, unknown> } | undefined;\n\nexport const createClient = (options: TRPCClientOptions): RevaultApiTRPCClient => {\n const trpc = createTRPCClient<AppRouter>({\n links: [\n httpLink({\n url: `${options.baseUrl}/trpc`,\n transformer: superjson,\n headers(opts) {\n // Extract headers from the operation context\n const contextHeaders = (opts.op.context?.headers as Record<string, string>) || {};\n\n return {\n ...(options.debugAuthToken\n ? { \"x-revault-debug-auth-token\": options.debugAuthToken }\n : {}),\n ...(options.rootAuthToken\n ? { \"x-revault-root-auth-token\": options.rootAuthToken }\n : {}),\n ...(options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}),\n ...(options.apiAccessToken\n ? { Authorization: `Bearer ${options.apiAccessToken}` }\n : {}),\n // Merge in any headers passed via context\n ...contextHeaders,\n };\n },\n }),\n ],\n });\n return trpc;\n};\n","import type {\n ApiChallenge,\n ClaimedRole,\n OnboardingSeedChallenge,\n PsdChallenge,\n UserRegistrationChallenge,\n UserRegistrationChallengeResponse,\n UserRegistrationDeviceData,\n UserRegistrationResponse,\n VaultRequestResponse,\n WrappingKeyResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport { createApiDevice, type Device, isPskMissingError } from \"@/device\";\nimport { createRealDevice } from \"@/device/real-device\";\nimport type { Logger } from \"@/logger\";\nimport { createClient, type RouterOutputs, type TRPCClientOptions } from \"@/trpc\";\n\nimport { buildTrpcContext } from \"../utils\";\nimport type {\n ApproveRequestParams,\n CorrelationIdOpts,\n DecorateWithApiUserAndWorkspaceUnauthenticated,\n DecorateWithDevice,\n DecorateWithDeviceAndOnboarding,\n DecorateWithDeviceAndWorkspaceUnauthenticated,\n DecorateWithWorkspaceApiAuthenticated,\n DecorateWithWorkspacePsdAuthenticated,\n DecorateWithWorkspaceUnauthenticated,\n Engine,\n EngineBase,\n EngineOptions,\n OnboardingOperationParams,\n RegisterOnboardingDeviceParams,\n WithApiAuth,\n WithApiUser,\n WithDevice,\n WithOnboarding,\n WithPsdAuth,\n WithWorkspace,\n} from \"./types\";\n\nexport { fetchAll, fetchAllCursor } from \"../utils\";\nexport type * from \"./types\";\n\nconst PSK_NONCE_BYTE_LEN = 32;\n\n// Open the per-operation secure channel matching the crypto the HSM used at Prepare, branching\n// on the challenge shape. A 32-byte `handshake` (hex, 64 chars) is the PSK HKDF nonce;\n// longer is legacy Noise-K.\nconst openSecureChannel = (\n device: Device,\n challenge: Pick<PsdChallenge, \"handshake\" | \"handshakeAttestation\" | \"partitionId\">,\n): Promise<void> => {\n if (challenge.handshake.length === PSK_NONCE_BYTE_LEN * 2) {\n return device.startPskSession({\n nonce: challenge.handshake,\n partitionId: challenge.partitionId,\n });\n }\n return device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n};\n\ntype DeviceConfidentialityKey = Awaited<ReturnType<Device[\"getConfidentialityKey\"]>>;\ntype DevicePairing = Parameters<Device[\"setPairing\"]>[0][\"pairing\"];\ntype DeviceRefreshPskData = Parameters<Device[\"finalizePskRefresh\"]>[0];\n\ntype RefreshPskInput = {\n psdEphemeralKey: string;\n psdEphemeralKeyAttestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n signature: string;\n };\n validationKeySignature: string;\n};\n\nconst pairDevice = async ({\n device,\n getPairing,\n}: {\n device: Pick<Device, \"getConfidentialityKey\" | \"setPairing\">;\n getPairing: (confidentialityKey: DeviceConfidentialityKey) => Promise<DevicePairing>;\n}): Promise<void> => {\n const confidentialityKey = await device.getConfidentialityKey();\n const pairing = await getPairing(confidentialityKey);\n await device.setPairing({ pairing });\n};\n\nconst refreshPsk = async ({\n device,\n getRefreshPskData,\n}: {\n device: Pick<\n Device,\n \"finalizePskRefresh\" | \"getAttestation\" | \"initPairingHandshake\" | \"signRefreshPskAuth\"\n >;\n getRefreshPskData: (input: RefreshPskInput) => Promise<DeviceRefreshPskData>;\n}): Promise<void> => {\n // Shared refresh sub-chain: 0x46 (device NN init) + 0x55 (validation-key auth signature)\n // → HSM refresh-psk (single read-only re-delivery) → 0x53 (finalize). The HSM verifies\n // the device-attested ephemeral key and the validation-key signature, so we stitch the\n // per-ephemeral signature from INITIALIZE_NN_HANDSHAKE onto the device's static attestation\n // chain (INS_GET_ATTESTATION_CERTIFICATE) and pass the SIGN_REFRESH_PSK_AUTH signature\n // alongside. initPairingHandshake (0x46) must resolve first: the soft-device\n // signRefreshPskAuth needs the ephemeral it returns, and the firmware FSM requires 0x46\n // before 0x55.\n const eph = await device.initPairingHandshake();\n const [deviceAttestation, validationKeySignature] = await Promise.all([\n device.getAttestation(),\n device.signRefreshPskAuth({ ephemeralKey: eph.pubKey }),\n ]);\n const refresh = await getRefreshPskData({\n psdEphemeralKey: Buffer.from(eph.pubKey, \"hex\").toString(\"base64\"),\n psdEphemeralKeyAttestation: {\n codeHash: deviceAttestation.attestation.codeHash,\n attestationPub: deviceAttestation.attestation.attestationPub,\n certificate: deviceAttestation.attestation.certificate,\n signature: eph.signature,\n },\n validationKeySignature,\n });\n await device.finalizePskRefresh(refresh);\n};\n\nasync function genericRegister<T>({\n device,\n name,\n role,\n getChallenge,\n submitChallenge,\n onScreenDisplayed,\n}: {\n device: Device;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n getChallenge: (p: {\n pubKey: string;\n deviceData: UserRegistrationDeviceData;\n }) => Promise<UserRegistrationChallenge>;\n submitChallenge: (p: {\n pubKey: string;\n challengeResponse: UserRegistrationChallengeResponse;\n }) => Promise<T>;\n onScreenDisplayed?: () => void | Promise<void>;\n}): Promise<T> {\n const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([\n device.getAttestation(),\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n const ephemeralPubKey = await device.initPairingHandshake();\n const deviceData: UserRegistrationDeviceData = {\n name,\n pubKey: u2fPubKey.pubKey,\n psdModel: \"STAX\",\n confidentialityKey: confidentialityKey.pubKey,\n psdEphemeralKey: ephemeralPubKey.pubKey,\n psdEphemeralKeyAttestation: {\n ...attestation.attestation,\n signature: ephemeralPubKey.signature,\n },\n };\n const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });\n const pairingPayload = await device.finalizePairingHandshake({\n handshake: challenge.handshake,\n partitionId: challenge.ciphertext,\n handshakeAttestation: challenge.handshakeAttestation,\n });\n await onScreenDisplayed?.();\n const register = await device.register({\n challenge: challenge.challenge,\n u2fRegisterData: challenge.u2fRegisterData,\n name,\n role,\n });\n const validationPubKey = await device.getValidationPubKey();\n const registerData = await device.registerData({ challenge: challenge.challenge });\n const attestationOffset = 67 + register.u2fRegister.readInt8(66);\n const u2fRegister = Buffer.concat([\n register.u2fRegister.slice(0, attestationOffset),\n Buffer.from([attestation.buffer.length]),\n attestation.buffer,\n register.u2fRegister.slice(attestationOffset),\n ]).toString(\"hex\");\n const challengeResponse: UserRegistrationChallengeResponse = {\n registerData,\n certificate: {\n ...attestation.attestation,\n signature: validationPubKey.signature,\n },\n u2fRegister,\n u2fKeyHandle: register.keyHandle.toString(\"hex\"),\n validationKey: validationPubKey.pubKey,\n pairingPayload,\n };\n return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });\n}\n\nexport function createEngine(options: EngineOptions, logger: Logger): Engine {\n const clientOptions: TRPCClientOptions = {\n baseUrl: options.baseUrl,\n };\n const client = createClient(clientOptions);\n const apiDevice = createApiDevice(options, logger);\n\n const base: EngineBase = {\n client,\n createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),\n __options: options,\n };\n\n const withDeviceIndex: Engine[\"withDeviceIndex\"] = function <T>(\n this: Engine<T>,\n deviceIndex: number,\n ) {\n const device = apiDevice.with(deviceIndex);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withTransportId: Engine[\"withTransportId\"] = function <T>(\n this: Engine<T>,\n transportId: string,\n ) {\n const device = createRealDevice({ transportId }, logger);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withApiUser: Engine[\"withApiUser\"] = function <T>(this: Engine<T>) {\n const withApiUser: WithApiUser = { __isApiUser: true };\n return decorateEngine({ ...this, ...withApiUser } as Engine<T & WithApiUser>);\n };\n\n const withWorkspace: Engine[\"withWorkspace\"] = function <T>(\n this: Engine<T>,\n workspaceName: string,\n ) {\n const withWorkspace: WithWorkspace = { __workspaceName: workspaceName };\n return decorateEngine({ ...this, ...withWorkspace } as Engine<T & WithWorkspace>);\n };\n\n const withOnboarding: Engine[\"withOnboarding\"] = function <T>(\n this: Engine<T>,\n onboardingId: string,\n ) {\n const withOnboarding: WithOnboarding = { __onboardingId: onboardingId };\n return decorateEngine({ ...this, ...withOnboarding } as Engine<T & WithOnboarding>);\n };\n\n function decorateEngine<T>(\n engine: Engine<\n T &\n Partial<\n WithDevice & WithOnboarding & WithWorkspace & WithPsdAuth & WithApiUser & WithApiAuth\n >\n >,\n ): Engine<T> {\n function decorate<TEnhanced, TDecoration>(\n decorator: (engine: EngineBase & TEnhanced) => TDecoration,\n ): void {\n Object.assign(engine, decorator(engine as EngineBase & TEnhanced));\n }\n\n // DecorateWithDevice\n // -------------------------------------------------------------------------\n if (engine.device) {\n decorate<WithDevice, DecorateWithDevice<T>>(\n (engine) =>\n ({\n getWorkspaces: async (): Promise<string[]> => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });\n return workspaceNames;\n },\n\n getWorkspacesForSso: async (): Promise<\n RouterOutputs[\"auth\"][\"sso\"][\"findWorkspaces\"][\"workspaces\"]\n > => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaces } = await client.auth.sso.findWorkspaces.query({ pubKey });\n return workspaces;\n },\n }) satisfies DecorateWithDevice<T>,\n );\n }\n\n // DecorateWithWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {\n decorate<WithWorkspace, DecorateWithWorkspaceUnauthenticated<T>>((engine) => {\n const { __workspaceName } = engine;\n return {\n withPsdToken: function <T>(this: Engine<T>, token: string): Engine<T & WithPsdAuth> {\n const withPsdAuth: WithPsdAuth = { __psdToken: token };\n const psdAuth = `${__workspaceName}:${token}`;\n const client = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client, ...withPsdAuth } as Engine<T & WithPsdAuth>);\n },\n } satisfies DecorateWithWorkspaceUnauthenticated<T>;\n });\n }\n\n // DecorateWithDeviceAndOnboarding\n // -------------------------------------------------------------------------\n if (engine.device && engine.__onboardingId) {\n decorate<WithDevice & WithOnboarding, DecorateWithDeviceAndOnboarding>((engine) => {\n const { device, client, __onboardingId } = engine;\n\n // Drive the device's pairing record + PSK to a fully-provisioned state.\n // - \"OK\" → nothing to do.\n // - \"NO_PAIRING\" → run the full pairing chain, then deliver a PSK via refresh.\n // - \"PSK_MISSING\" → pairing already exists; only run the PSK refresh sub-chain.\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n let pubKeyPromise: Promise<string> | undefined;\n const getPubKey = async (): Promise<string> => {\n pubKeyPromise ??= device.getU2FPubKey().then(({ pubKey }) => pubKey);\n return pubKeyPromise;\n };\n const refreshCurrentPsk = async (): Promise<void> => {\n const pubKey = await getPubKey();\n await refreshPsk({\n device,\n getRefreshPskData: (data) =>\n client.onboarding.refreshPsk.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data,\n }),\n });\n };\n\n if (status === \"NO_PAIRING\") {\n const pubKey = await getPubKey();\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.onboarding.pairDevicePartition.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data: {\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n },\n }),\n });\n }\n\n await refreshCurrentPsk();\n }\n\n return {\n claimDevice: async (params: { role: ClaimedRole; deviceName: string }): Promise<void> => {\n const { role, deviceName } = params;\n const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await client.onboarding.claimDevice.mutate({\n onboardingId: __onboardingId,\n claim: { role, pubKey, deviceName, confidentialityKey },\n });\n },\n\n collectWrappingKeyFragment: async (\n wrappingKey: WrappingKeyResponse,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await device.openSession({\n secureChannel: {\n pubKey: wrappingKey.ephemeralPubKey,\n certificate: wrappingKey.ephemeralCertificate,\n },\n });\n const { attestation } = await device.getAttestation();\n await params?.onScreenDisplayed?.();\n const blob = await device.generateWrappingKeyFragment();\n await client.onboarding.submitWrappingKeyFragment.mutate({\n pubKey,\n onboardingId: __onboardingId,\n fragment: {\n blob,\n ephemeralPubKey: confidentialityKey.pubKey,\n ephemeralCertificate: {\n ...attestation,\n signature: confidentialityKey.signature,\n },\n },\n });\n },\n\n registerDevice: async (\n registerParams: RegisterOnboardingDeviceParams,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const { role, name } = registerParams;\n const getChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.generateMasterAdminRegistrationChallenge\n : client.onboarding.generateSharedOwnerRegistrationChallenge;\n const submitChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.submitMasterAdminRegistration\n : client.onboarding.submitSharedOwnerRegistration;\n await genericRegister({\n device: device,\n name,\n role,\n getChallenge: ({ pubKey, deviceData }) =>\n getChallengeMutation.mutate({\n onboardingId: __onboardingId,\n pubKey,\n deviceData,\n }),\n submitChallenge: ({ pubKey, challengeResponse }) =>\n submitChallengeMutation.mutate({\n onboardingId: engine.__onboardingId,\n pubKey,\n // FIXME this should be renamed to `challengeResponse` on backend side\n response: challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n\n reviewSharedOwner: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitReviewByMasterAdminSignature.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n reviewExternalSigners: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitExternalSignersRegistration.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n collectSeedFragment: async (\n challenge: OnboardingSeedChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const [{ pubKey }, { attestation }] = await Promise.all([\n device.getU2FPubKey(),\n device.getAttestation(),\n ]);\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const challengeResponse = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n const kkPattern = await device.startKKPatternAsResponder({\n partitionId: challenge.partitionId,\n handshake: challenge.kkHandshake,\n handshakeAttestation: challenge.kkHandshakeAttestation,\n });\n const approverBlob = await device.generateSeedFragment();\n await client.onboarding.submitSeedFragment.mutate({\n onboardingId: __onboardingId,\n pubKey,\n seedFragment: {\n challengeResponse,\n approverBlob,\n handshake: kkPattern.handshake,\n handshakeAttestation: {\n ...attestation,\n signature: kkPattern.signature,\n },\n },\n });\n },\n } satisfies DecorateWithDeviceAndOnboarding;\n });\n }\n\n // DecorateWithDeviceAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && !engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithDeviceAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { device, client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n opts?: {\n validityDurationSecs?: number;\n onScreenDisplayed?: () => void | Promise<void>;\n correlationId?: string;\n },\n ): Promise<Engine<T & WithPsdAuth>> {\n const { pubKey } = await device.getU2FPubKey();\n const challenge = await client.auth.psd.generateChallenge.mutate(\n {\n pubKey,\n workspaceName: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n await opts?.onScreenDisplayed?.();\n const authentication = await device.authenticate({\n challenge,\n workspaceName: __workspaceName,\n });\n const authPayload = {\n workspaceName: __workspaceName,\n pubKey,\n authentication,\n challengeId: challenge.challengeId,\n validityDurationSecs: opts?.validityDurationSecs,\n };\n const { token } = await client.auth.psd.authenticate.mutate(\n { ...authPayload },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withPsdAuth: WithPsdAuth = {\n __psdToken: token,\n };\n const psdAuth = `${engine.__workspaceName}:${token}`;\n const __authClient = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client: __authClient, ...withPsdAuth } as Engine<\n T & WithPsdAuth\n >);\n },\n\n register: (\n registration: UserRegistrationResponse,\n params?: OnboardingOperationParams,\n ): Promise<UserRegistrationResponse> => {\n return genericRegister({\n device,\n name: registration.name,\n role: registration.role,\n getChallenge: async ({ deviceData }) => {\n const challenge = await client.userRegistrations.generateChallenge.mutate({\n id: registration.id,\n workspaceName: __workspaceName,\n deviceData,\n });\n return challenge;\n },\n submitChallenge: ({ challengeResponse }) =>\n client.userRegistrations.submitChallenge.mutate({\n workspaceName: __workspaceName,\n id: registration.id,\n challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n } satisfies DecorateWithDeviceAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithApiUserAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {\n decorate<WithWorkspace & WithApiUser, DecorateWithApiUserAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n credentials: {\n apiKeyId: string;\n apiKeySecret: string;\n },\n opts?: { correlationId?: string },\n ): Promise<Engine<T & WithApiAuth>> {\n const res = await client.auth.authenticate.mutate(\n {\n apiKeyId: credentials.apiKeyId,\n apiKeySecret: credentials.apiKeySecret,\n workspace: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withApiAuth: WithApiAuth = {\n __apiAuth: res,\n };\n const __authClient = engine.createClient({ apiAccessToken: res.accessToken });\n return decorateEngine({ ...this, client: __authClient, ...withApiAuth } as Engine<\n T & WithApiAuth\n >);\n },\n } satisfies DecorateWithApiUserAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithWorkspacePsdAuthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithWorkspacePsdAuthenticated>((engine) => {\n const { client, device } = engine;\n\n // Drive the device's pairing record + PSK to a fully-provisioned state. Same tri-state\n // switch as the onboarding decorator; routes through `client.debug.*` instead of\n // `client.onboarding.*` and pulls workspace context implicitly from `__psdToken`.\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n const refreshCurrentPsk = async (): Promise<void> => {\n await refreshPsk({\n device,\n getRefreshPskData: (data) => client.debug.refreshPsk.mutate(data),\n });\n };\n\n if (status === \"NO_PAIRING\") {\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.debug.pairDevicePartition.mutate({\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n }),\n });\n }\n\n await refreshCurrentPsk();\n }\n\n const approveChallenge = async (\n challenge: PsdChallenge,\n params?: ApproveRequestParams,\n ): Promise<string> => {\n await enforcePairing();\n try {\n await openSecureChannel(device, challenge);\n } catch (err) {\n if (!isPskMissingError(err)) throw err;\n // Defense-in-depth: a session opened before the PSK was wiped still hits\n // SW_PSK_MISSING here. Re-run enforcePairing() — it now sees PSK_MISSING and drives\n // the refresh sub-chain — then retry the secure-channel APDU once.\n await enforcePairing();\n await openSecureChannel(device, challenge);\n }\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n return signature;\n };\n\n return {\n approve: async (\n request: VaultRequestResponse,\n params?: ApproveRequestParams,\n ): Promise<VaultRequestResponse> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n if (challenge.challengeType === \"PSD\") {\n const signature = await approveChallenge(challenge, params);\n await params?.onPsdChallengeSigned?.();\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"PSD\", signature },\n },\n buildTrpcContext(params),\n );\n }\n if (challenge.challengeType === \"SOFT\") {\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"SOFT\" },\n },\n buildTrpcContext(params),\n );\n }\n throw new Error(\"Challenge type must be either PSD or SOFT\");\n },\n\n approveChallenge,\n\n reject: (\n request: VaultRequestResponse,\n opts?: CorrelationIdOpts,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate(\n { id: request.id, data: null },\n buildTrpcContext(opts),\n );\n },\n } satisfies DecorateWithWorkspacePsdAuthenticated;\n });\n }\n\n // DecorateWithWorkspaceApiAuthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__apiAuth) {\n decorate<WithWorkspace & WithApiAuth, DecorateWithWorkspaceApiAuthenticated>((engine) => {\n const { client } = engine;\n return {\n getChallenge: async (request: VaultRequestResponse): Promise<ApiChallenge[\"payload\"]> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"API\", \"Challenge type must be API\");\n return challenge.payload;\n },\n\n approve: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n\n reject: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n } satisfies DecorateWithWorkspaceApiAuthenticated;\n });\n }\n\n return engine;\n }\n\n return {\n ...base,\n withDeviceIndex,\n withTransportId,\n withApiUser,\n withWorkspace,\n withOnboarding,\n };\n}\n"],"mappings":"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"}
|
package/lib/engine.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { c as LockedDeviceError, d as PAGINATED_STATUS, f as PATHS, i as isTransportStatusError, l as createApiDevice, m as STR_ROLES, o as withDevicePolling, p as SCRIPT_IDS, r as isPskMissingError, s as DisconnectedDevice, u as APPID_VAULT_ADMINISTRATOR } from "./device-WXLkORvV.js";
|
|
2
2
|
import { i as fetchAllCursor, r as fetchAll, t as buildTrpcContext } from "./utils-CW0gdJME.js";
|
|
3
3
|
import invariant from "invariant";
|
|
4
|
-
import { match } from "ts-pattern";
|
|
5
4
|
import { from, lastValueFrom } from "rxjs";
|
|
6
5
|
import { createTRPCClient, httpLink } from "@trpc/client";
|
|
7
6
|
import superjson from "superjson";
|
|
@@ -668,55 +667,40 @@ function createEngine(options, logger) {
|
|
|
668
667
|
});
|
|
669
668
|
if (engine.device && engine.__onboardingId) decorate((engine) => {
|
|
670
669
|
const { device, client, __onboardingId } = engine;
|
|
671
|
-
const isPskEnabled = async () => {
|
|
672
|
-
try {
|
|
673
|
-
return await client.onboarding.getPskFeatureFlag.query({ onboardingId: __onboardingId }) === true;
|
|
674
|
-
} catch {
|
|
675
|
-
return false;
|
|
676
|
-
}
|
|
677
|
-
};
|
|
678
670
|
async function enforcePairing() {
|
|
679
671
|
const status = await device.hasPairing();
|
|
680
672
|
if (status === "OK") return;
|
|
681
|
-
const pskEnabled = await isPskEnabled();
|
|
682
673
|
let pubKeyPromise;
|
|
683
674
|
const getPubKey = async () => {
|
|
684
675
|
pubKeyPromise ??= device.getU2FPubKey().then(({ pubKey }) => pubKey);
|
|
685
676
|
return pubKeyPromise;
|
|
686
677
|
};
|
|
687
|
-
const
|
|
678
|
+
const refreshCurrentPsk = async () => {
|
|
688
679
|
const pubKey = await getPubKey();
|
|
689
|
-
await
|
|
680
|
+
await refreshPsk({
|
|
690
681
|
device,
|
|
691
|
-
|
|
682
|
+
getRefreshPskData: (data) => client.onboarding.refreshPsk.mutate({
|
|
692
683
|
pubKey,
|
|
693
684
|
onboardingId: __onboardingId,
|
|
694
|
-
data
|
|
695
|
-
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
696
|
-
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
697
|
-
}
|
|
685
|
+
data
|
|
698
686
|
})
|
|
699
687
|
});
|
|
700
688
|
};
|
|
701
|
-
|
|
689
|
+
if (status === "NO_PAIRING") {
|
|
702
690
|
const pubKey = await getPubKey();
|
|
703
|
-
await
|
|
691
|
+
await pairDevice({
|
|
704
692
|
device,
|
|
705
|
-
|
|
693
|
+
getPairing: (confidentialityKey) => client.onboarding.pairDevicePartition.mutate({
|
|
706
694
|
pubKey,
|
|
707
695
|
onboardingId: __onboardingId,
|
|
708
|
-
data
|
|
696
|
+
data: {
|
|
697
|
+
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
698
|
+
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
699
|
+
}
|
|
709
700
|
})
|
|
710
701
|
});
|
|
711
|
-
}
|
|
712
|
-
await
|
|
713
|
-
await pairCurrentDevice();
|
|
714
|
-
}).with(["NO_PAIRING", true], async () => {
|
|
715
|
-
await pairCurrentDevice();
|
|
716
|
-
await refreshCurrentPsk();
|
|
717
|
-
}).with(["PSK_MISSING", false], async () => {}).with(["PSK_MISSING", true], async () => {
|
|
718
|
-
await refreshCurrentPsk();
|
|
719
|
-
}).exhaustive();
|
|
702
|
+
}
|
|
703
|
+
await refreshCurrentPsk();
|
|
720
704
|
}
|
|
721
705
|
return {
|
|
722
706
|
claimDevice: async (params) => {
|
|
@@ -899,40 +883,23 @@ function createEngine(options, logger) {
|
|
|
899
883
|
});
|
|
900
884
|
if (engine.device && engine.__workspaceName && engine.__psdToken) decorate((engine) => {
|
|
901
885
|
const { client, device } = engine;
|
|
902
|
-
const isPskEnabled = async () => {
|
|
903
|
-
try {
|
|
904
|
-
return await client.debug.getPskFeatureFlag.query() === true;
|
|
905
|
-
} catch {
|
|
906
|
-
return false;
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
886
|
async function enforcePairing() {
|
|
910
887
|
const status = await device.hasPairing();
|
|
911
888
|
if (status === "OK") return;
|
|
912
|
-
const pskEnabled = await isPskEnabled();
|
|
913
|
-
const pairCurrentDevice = async () => {
|
|
914
|
-
await pairDevice({
|
|
915
|
-
device,
|
|
916
|
-
getPairing: (confidentialityKey) => client.debug.pairDevicePartition.mutate({
|
|
917
|
-
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
918
|
-
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
919
|
-
})
|
|
920
|
-
});
|
|
921
|
-
};
|
|
922
889
|
const refreshCurrentPsk = async () => {
|
|
923
890
|
await refreshPsk({
|
|
924
891
|
device,
|
|
925
892
|
getRefreshPskData: (data) => client.debug.refreshPsk.mutate(data)
|
|
926
893
|
});
|
|
927
894
|
};
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
895
|
+
if (status === "NO_PAIRING") await pairDevice({
|
|
896
|
+
device,
|
|
897
|
+
getPairing: (confidentialityKey) => client.debug.pairDevicePartition.mutate({
|
|
898
|
+
confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
|
|
899
|
+
confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
|
|
900
|
+
})
|
|
901
|
+
});
|
|
902
|
+
await refreshCurrentPsk();
|
|
936
903
|
}
|
|
937
904
|
const approveChallenge = async (challenge, params) => {
|
|
938
905
|
await enforcePairing();
|
|
@@ -940,11 +907,8 @@ function createEngine(options, logger) {
|
|
|
940
907
|
await openSecureChannel(device, challenge);
|
|
941
908
|
} catch (err) {
|
|
942
909
|
if (!isPskMissingError(err)) throw err;
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
await enforcePairing();
|
|
946
|
-
await openSecureChannel(device, challenge);
|
|
947
|
-
}
|
|
910
|
+
await enforcePairing();
|
|
911
|
+
await openSecureChannel(device, challenge);
|
|
948
912
|
}
|
|
949
913
|
await params?.onScreenDisplayed?.();
|
|
950
914
|
return await device.validateVaultOperation({ actions: challenge.wActions });
|
package/lib/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","names":[],"sources":["../src/device/real-device.ts","../src/trpc.ts","../src/engine/index.ts"],"sourcesContent":["import { DisconnectedDevice, LockedDeviceError } from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport type { HsmCertificate, PubKey, RefreshPskData } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { from, lastValueFrom } from \"rxjs\";\n\nimport type { Logger } from \"@/logger\";\n\nimport {\n APPID_VAULT_ADMINISTRATOR,\n PAGINATED_STATUS,\n PATHS,\n SCRIPT_IDS,\n STATUS_LENGTH,\n STR_ROLES,\n STREAMING_NEXT_ACTION,\n STREAMING_RESPONSE,\n} from \"./constants\";\nimport { withDevicePolling } from \"./device-access\";\nimport type { Device, PairingStatus } from \"./types\";\nimport { isTransportStatusError } from \"./utils\";\n\nconst MAX_CHUNK_LENGTH = 250;\n\ntype Options = {\n transportId: string;\n};\n\nconst getPathFromPathString = (pathString: string): number[] => {\n const parts = pathString.split(\"'/\").map((part) => Number.parseInt(part, 10));\n return parts.map((part) => (part | 0x80000000) >>> 0);\n};\n\nconst splitChunks = (chunk: number, buffer: Buffer): Buffer[] => {\n const chunks = [];\n for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {\n chunks.push(buffer.slice(i, i + size));\n }\n return chunks;\n};\n\nconst removeStatus = (result: Buffer): Buffer => result.slice(0, result.length - STATUS_LENGTH);\n\nconst sendByChunk = async (\n transport: Transport,\n command: number[], // eg [0xe0, 0x45, 0x00, 0x00]\n data: Buffer,\n chunkSize: number = MAX_CHUNK_LENGTH,\n): Promise<Buffer> => {\n const chunks = splitChunks(chunkSize, data);\n let response = Buffer.from([]);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const apdu = [...command];\n // command is 0xe0,0x45,0x00,0x00 for first chunk, then it's 0xe0,0x45,0x80,0x00\n /* v8 ignore next -- @preserve */\n apdu[2] = i && 0x80;\n response = (await transport.send(apdu[0]!, apdu[1]!, apdu[2], apdu[3]!, chunk, [\n 0x9000,\n ...PAGINATED_STATUS,\n ])) as Buffer<ArrayBuffer>;\n }\n return response;\n};\n\nconst buildAttestation = (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n}): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const cliMsgBuffer = Buffer.from(params.handshake, \"hex\");\n const cliMsgLengthBuffer = Buffer.alloc(1);\n cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);\n\n const pidBuffer = Buffer.from(params.partitionId, \"hex\");\n const pidLengthBuffer = Buffer.alloc(1);\n pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n cliMsgLengthBuffer,\n cliMsgBuffer,\n certChainDataLengthBuff,\n certChainData,\n pidLengthBuffer,\n pidBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n const toSend = Buffer.concat([totalLengthBuffer, data]);\n\n return toSend;\n};\n\n// Wire-format builder for FINALIZE_PSK_REFRESH (`0xE0 0x53`). Same layout as `buildAttestation`\n// (consumed by the device's `parse_nn_handshake_payload`), but the trailing TLV carries the\n// encrypted PairingPayload from `RefreshPsk` instead of a partition ID.\n//\n// Layout after the leading 2-byte total length:\n// [1] handshake length (the NN responder handshake, written from its actual decoded length)\n// [N] handshake bytes\n// [2] cert-chain-data length (BE)\n// [1] handshake-cert (DER signature) length\n// [N] handshake-cert bytes\n// [65] vault attestation pubkey (raw 0x04|x|y, no length prefix)\n// [1] att-cert length\n// [M] att-cert bytes\n// [1] ciphered-payload length\n// [K] encrypted PairingPayload bytes\nconst buildPskRefreshPayload = (params: RefreshPskData): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const handshakeBuffer = Buffer.from(params.handshake, \"base64\");\n invariant(\n handshakeBuffer.length <= 255,\n `PSK refresh handshake too long: ${handshakeBuffer.length} bytes (max 255)`,\n );\n const handshakeLengthBuffer = Buffer.alloc(1);\n handshakeLengthBuffer.writeUInt8(handshakeBuffer.length, 0);\n\n const encryptedPayloadBuffer = Buffer.from(params.encryptedPairingPayload, \"base64\");\n invariant(\n encryptedPayloadBuffer.length <= 255,\n `PSK encrypted payload too long: ${encryptedPayloadBuffer.length} bytes (max 255)`,\n );\n const encryptedPayloadLengthBuffer = Buffer.alloc(1);\n encryptedPayloadLengthBuffer.writeUInt8(encryptedPayloadBuffer.length, 0);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n handshakeLengthBuffer,\n handshakeBuffer,\n certChainDataLengthBuff,\n certChainData,\n encryptedPayloadLengthBuffer,\n encryptedPayloadBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n return Buffer.concat([totalLengthBuffer, data]);\n};\n\ntype RetryOnError = (err: Error) => boolean;\n/* v8 ignore next -- @preserve */\nconst genericRetryOnError: RetryOnError = (err) => {\n // device is locked\n if (err instanceof LockedDeviceError) return true;\n // user is on dashboard when receiving a Vault app apdu\n if (isTransportStatusError(err) && err.statusCode === 0x6d09) return true;\n // VG-24797 error that can happen in BLE in some situations (still unclear)\n if (err instanceof DisconnectedDevice) return true;\n\n // for everything else, we don't want to retry\n return false;\n};\n\nexport function createRealDevice(options: Options, logger: Logger): Device {\n const { transportId } = options;\n\n async function run<T>(\n job: (transport: Transport) => Promise<T>,\n retryOnError: RetryOnError = genericRetryOnError,\n ): Promise<T> {\n return lastValueFrom(\n withDevicePolling(transportId)<T>((transport) => from(job(transport)), retryOnError),\n );\n }\n\n /* v8 ignore next -- @preserve */\n const noRetry = (): boolean => false;\n /* v8 ignore next -- @preserve */\n const alwaysRetry = (): boolean => true;\n const poll = async (\n opts: { retryOnError?: RetryOnError } = {},\n ): Promise<{ isAppOpened: boolean }> => {\n // waiting for device to be turned on\n await run(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n async (_transport) => {},\n opts.retryOnError ?? alwaysRetry,\n );\n // checking if app is opened: should return directly on getPubKey\n try {\n await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });\n return { isAppOpened: true };\n } catch (err) {\n if (isTransportStatusError(err) && genericRetryOnError(err)) {\n return { isAppOpened: false };\n }\n throw err;\n }\n };\n\n const pollApp = async (appName: string): Promise<string> => {\n const res = await run((transport) =>\n transport.send(0xe0, 0xd8, 0x00, 0x00, Buffer.from(appName, \"utf8\")),\n );\n // little delay to give time to the app to be fully opened\n await new Promise((r) => setTimeout(r, 1e3));\n return res.toString(\"hex\");\n };\n\n const getPublicKey = async (\n pathString: string,\n { secp256k1, retryOnError }: { secp256k1: boolean; retryOnError?: RetryOnError },\n ): Promise<{ pubKey: string; signature: string }> => {\n logger.info(`[device] getPublicKey (${pathString})`);\n const path = getPathFromPathString(pathString);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const curve = secp256k1 ? 0x01 : 0x02;\n const response = await run(\n (transport) => transport.send(0xe0, 0x40, curve, 0x00, data),\n retryOnError ?? genericRetryOnError,\n );\n const pubKeyLength = response.readInt8(0);\n const pubKey = response\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = response\n .slice(pubKeyLength + 1, response.length - STATUS_LENGTH)\n .toString(\"base64\");\n return { pubKey, signature };\n };\n\n const device: Device = {\n authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {\n logger.info(`[device] Authenticate`);\n invariant(role !== \"READ_ONLY_API_KEY\", \"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n const nameBuffer = Buffer.from(name);\n const workspaceBuffer = Buffer.from(workspaceName);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([nameBuffer.length]),\n nameBuffer,\n Buffer.from([workspaceBuffer.length]),\n workspaceBuffer,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([\n Buffer.from(challenge, \"base64\"),\n applicationBuffer,\n Buffer.from([keyHandle.length]),\n Buffer.from(keyHandle, \"hex\"),\n keyHandleDataLength,\n keyHandleData,\n ]);\n\n const authentication = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x02, 0x00, 0x00], data),\n );\n\n return removeStatus(authentication).toString(\"hex\");\n },\n\n finalizePairingHandshake: async (params: {\n handshake: string;\n partitionId: string;\n handshakeAttestation: HsmCertificate;\n }): Promise<string> => {\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x47, 0x00, 0x02], buildAttestation(params)),\n );\n return removeStatus(bufWithStatus).toString(\"hex\");\n },\n\n generateSeedFragment: async (): Promise<string> => {\n logger.info(`[device] generateSeedFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x00, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n generateWrappingKeyFragment: async (): Promise<string> => {\n logger.info(`[device] generateWrappingKeyFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x01, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n getAttestation: async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x41, 0x00, 0x00));\n const buffer = removeStatus(bufWithStatus);\n const certLen = buffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: buffer.slice(0, 32).toString(\"base64\"),\n attestationPub: buffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer,\n };\n },\n getConfidentialityKey: async () => {\n logger.info(`[device] getConfidentialityKey`);\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x4d, 0x00, 0x00));\n const buf = removeStatus(bufWithStatus);\n const keyLength = buf[0]!;\n const key = buf.slice(1, 1 + keyLength);\n const sig = buf.slice(1 + keyLength + 1);\n return {\n confidentialityKeyCurve25519: key.toString(\"hex\"),\n confidentialityKeySignature: sig.toString(\"hex\"),\n };\n },\n getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),\n getDeviceUserId: async (): Promise<string> => {\n logger.info(`[device] getDeviceUserId`);\n const response = await run((transport) => transport.send(0xe0, 0x52, 0x00, 0x00));\n return removeStatus(response).toString(\"hex\").toUpperCase();\n },\n getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),\n getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),\n hasPairing: async (): Promise<PairingStatus> => {\n logger.info(`[device] hasPairing`);\n const apdu = [0xe0, 0x51, 0x00, 0x00, 0xb5];\n const res = await run((transport) => transport.exchange(Buffer.from(apdu)));\n\n // GET_PARTITION_IDS returns the partition list followed by a 2-byte SW. Inspect only\n // the trailing SW; the device may return data alongside non-`9000` SWs (notably 0x6065\n // — see below).\n const swHex = res.subarray(res.length - 2).toString(\"hex\");\n\n // 6f45 => no partition ID on the device (SW_NO_PARTITION_ID).\n // 6a87 => TEMPORARY hack: some firmware revs don't implement the APDU and return\n // \"incorrect length\"; treat as no pairing so revault drives the full pair-from-\n // scratch flow.\n if (swHex === \"6f45\" || swHex === \"6a87\") return \"NO_PAIRING\";\n\n // 6065 => SW_PSK_MISSING: a valid pairing record exists but its PSK field is the all-\n // zero sentinel. Skip the full pairing chain and run the refresh sub-chain.\n if (swHex === \"6065\") return \"PSK_MISSING\";\n\n // Anything else (typically 9000) => fully provisioned pairing with PSK.\n return \"OK\";\n },\n\n initPairingHandshake: async (): Promise<{ pubKey: string; signature: string }> => {\n const res = await run((transport) => transport.send(0xe0, 0x46, 0x00, 0x00));\n const pubKeyLength = res.readInt8(0);\n const pubKey = res\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString(\"base64\");\n return { pubKey, signature };\n },\n\n openSession: async (params: {\n secureChannel: { pubKey: PubKey; certificate: HsmCertificate };\n }): Promise<void> => {\n logger.info(`[device] openSession`);\n const { secureChannel } = params;\n\n const path = getPathFromPathString(PATHS.CONFIDENTIALITY);\n const dataDerivation = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n const pubKey = Buffer.from(secureChannel.pubKey, \"hex\");\n\n const sigBuffer = Buffer.from(secureChannel.certificate.signature, \"base64\");\n const attestationPubBuffer = Buffer.from(secureChannel.certificate.attestationPub, \"base64\");\n const certBuffer = Buffer.from(secureChannel.certificate.certificate, \"base64\");\n const attestation = Buffer.concat([\n Buffer.from([sigBuffer.length]),\n sigBuffer,\n attestationPubBuffer,\n Buffer.from([certBuffer.length]),\n certBuffer,\n ]);\n\n const lengthAttestation = Buffer.alloc(2);\n lengthAttestation.writeUInt16BE(attestation.length, 0);\n\n const data = Buffer.concat([dataDerivation, pubKey, lengthAttestation, attestation]);\n\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x42, 0x00, SCRIPT_IDS.INIT_SESSION], data),\n );\n },\n\n register: async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n invariant(applicationBuf.length === 32, \"application hex is expected to have 32 bytes\");\n\n const userNameBuff = Buffer.from(name);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([userNameBuff.length]),\n userNameBuff,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);\n\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x01, 0x00, 0x00], data),\n );\n\n let i = 0;\n const rfu = response.slice(i, i + 1)[0]!;\n i += 1;\n const pubKey = response.slice(i, i + 65).toString(\"hex\");\n i += 65;\n const keyHandleLength = response.slice(i, i + 1)[0]!;\n i++;\n const keyHandle = response.slice(i, i + keyHandleLength);\n i += keyHandleLength;\n return {\n u2fRegister: removeStatus(response),\n keyHandle,\n rfu,\n pubKey,\n };\n },\n registerData: async (params: { challenge: string }): Promise<string> => {\n const { challenge: strChallenge } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const response = await run((transport) => transport.send(0xe0, 0x03, 0x00, 0x00, challenge));\n return removeStatus(response).toString(\"hex\");\n },\n\n setPairing: async ({ pairing }) => {\n logger.info(`[device] setPairing`);\n const psdPayload = Buffer.from(pairing.blob, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(psdPayload.length, 0);\n const final = Buffer.concat([length, psdPayload]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x4e, 0x00, 0x00], final));\n },\n\n // `ephemeralKey` is unused here: the firmware signs over the ephemeral it captured in its own\n // `G_nn_initiator_eph_pubkey` global at INITIALIZE_NN_HANDSHAKE, and INS 0x55 rejects any\n // payload. The arg only exists for the stateless device-api (see api-device.ts).\n signRefreshPskAuth: async (): Promise<string> => {\n logger.info(`[device] signRefreshPskAuth`);\n const res = await run((transport) => transport.send(0xe0, 0x55, 0x00, 0x00));\n return res.slice(0, res.length - STATUS_LENGTH).toString(\"base64\");\n },\n\n finalizePskRefresh: async (params: RefreshPskData): Promise<void> => {\n logger.info(`[device] finalizePskRefresh`);\n const payload = buildPskRefreshPayload(params);\n await run((transport) => sendByChunk(transport, [0xe0, 0x53, 0x00, 0x00], payload));\n },\n startKKPatternAsResponder: async (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n }): Promise<{ handshake: string; signature: string }> => {\n logger.info(`[device] startKKPatternAsResponder`);\n const data = buildAttestation(params);\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x4c, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n const buffer = removeStatus(bufWithStatus);\n const dataLength = buffer.readInt8(0);\n return {\n handshake: buffer.slice(1, dataLength + 1).toString(\"base64\"),\n signature: buffer.slice(dataLength + 1).toString(\"base64\"),\n };\n },\n startKPatternAsResponder: async (params) => {\n logger.info(`[device] startKPatternAsResponder`);\n const data = buildAttestation(params);\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x49, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n },\n startPskSession: async (params) => {\n logger.info(`[device] startPskSession`);\n // START_PSK_SESSION (0xe0 0x50): the device reads a raw `nonce(32) || partitionId(16)`\n // payload straight from cmd->data (lc must be exactly 48) — no length prefixes and no\n // attestation. The dispatcher also rejects any non-zero P1/P2 with SW_WRONG_P1P2, so\n // both stay 0 (unlike the K handshake, which ignores P2 = ACCOUNT_MANAGER_SESSION).\n invariant(\n params.nonce.length === 64,\n `PSK nonce must be 32 bytes (64 hex chars), got ${params.nonce.length} chars`,\n );\n invariant(\n params.partitionId.length === 32,\n `partitionId must be 16 bytes (32 hex chars), got ${params.partitionId.length} chars`,\n );\n const data = Buffer.concat([\n Buffer.from(params.nonce, \"hex\"),\n Buffer.from(params.partitionId, \"hex\"),\n ]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x50, 0x00, 0x00], data));\n },\n validateVaultOperation: async (params) => {\n logger.info(`[device] validateVaultOperation`);\n const path = getPathFromPathString(PATHS.VALIDATION);\n const paths = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n let nextActionId = 1;\n let finalResponse: Buffer | null = null;\n\n while (!finalResponse) {\n const screen = Buffer.from(params.actions[nextActionId - 1]!, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(screen.length, 0);\n const data = Buffer.concat([paths, length, screen]);\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x45, 0x00, 0x00], data),\n );\n const responseType = response.readInt8(0);\n let responseStatus = response.readUInt16BE(response.length - 2);\n switch (responseType) {\n case STREAMING_NEXT_ACTION:\n nextActionId = response.readUIntBE(1, 2);\n break;\n case STREAMING_RESPONSE:\n finalResponse = response.slice(3, response.length - 2);\n while (responseStatus !== 0x9000) {\n /* v8 ignore next -- @preserve */ {\n const resp = await run((transport) => transport.send(0x00, 0xc0, 0x00, 0x00));\n responseStatus = resp.readUInt16BE(resp.length - 2);\n finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);\n }\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(`Invalid response type: ${responseType}`);\n }\n }\n return finalResponse.toString(\"base64\");\n },\n\n sendAPDU: async (apduCommand: string) => {\n const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, \"hex\")));\n return Buffer.from(res).toString(\"hex\");\n },\n getVersion: async () => {\n const res = await run((transport) => transport.send(0xb0, 0x01, 0x00, 0x00));\n const appNameLen = res.readInt8(1);\n const appVersionLen = res.readInt8(2 + appNameLen);\n const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);\n\n const appVersion = Buffer.from(appVersionHex).toString();\n\n return appVersion;\n },\n poll,\n pollApp,\n };\n return device;\n}\n","import type { AppRouter } from \"@ledgerhq/revault-api\";\nimport { createTRPCClient, httpLink, type TRPCClient } from \"@trpc/client\";\nimport type { inferRouterInputs, inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nexport type TRPCClientOptions = {\n baseUrl: string;\n debugAuthToken?: string;\n rootAuthToken?: string;\n apiAccessToken?: string;\n psdAuth?: string;\n};\n\nexport type RevaultApiTRPCClient = TRPCClient<AppRouter>;\n\nexport type RouterInputs = inferRouterInputs<AppRouter>;\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n\nexport type TRPCContext = { context: Record<string, unknown> } | undefined;\n\nexport const createClient = (options: TRPCClientOptions): RevaultApiTRPCClient => {\n const trpc = createTRPCClient<AppRouter>({\n links: [\n httpLink({\n url: `${options.baseUrl}/trpc`,\n transformer: superjson,\n headers(opts) {\n // Extract headers from the operation context\n const contextHeaders = (opts.op.context?.headers as Record<string, string>) || {};\n\n return {\n ...(options.debugAuthToken\n ? { \"x-revault-debug-auth-token\": options.debugAuthToken }\n : {}),\n ...(options.rootAuthToken\n ? { \"x-revault-root-auth-token\": options.rootAuthToken }\n : {}),\n ...(options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}),\n ...(options.apiAccessToken\n ? { Authorization: `Bearer ${options.apiAccessToken}` }\n : {}),\n // Merge in any headers passed via context\n ...contextHeaders,\n };\n },\n }),\n ],\n });\n return trpc;\n};\n","import type {\n ApiChallenge,\n ClaimedRole,\n OnboardingSeedChallenge,\n PsdChallenge,\n UserRegistrationChallenge,\n UserRegistrationChallengeResponse,\n UserRegistrationDeviceData,\n UserRegistrationResponse,\n VaultRequestResponse,\n WrappingKeyResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { match } from \"ts-pattern\";\n\nimport { createApiDevice, type Device, isPskMissingError } from \"@/device\";\nimport { createRealDevice } from \"@/device/real-device\";\nimport type { Logger } from \"@/logger\";\nimport { createClient, type RouterOutputs, type TRPCClientOptions } from \"@/trpc\";\n\nimport { buildTrpcContext } from \"../utils\";\nimport type {\n ApproveRequestParams,\n CorrelationIdOpts,\n DecorateWithApiUserAndWorkspaceUnauthenticated,\n DecorateWithDevice,\n DecorateWithDeviceAndOnboarding,\n DecorateWithDeviceAndWorkspaceUnauthenticated,\n DecorateWithWorkspaceApiAuthenticated,\n DecorateWithWorkspacePsdAuthenticated,\n DecorateWithWorkspaceUnauthenticated,\n Engine,\n EngineBase,\n EngineOptions,\n OnboardingOperationParams,\n RegisterOnboardingDeviceParams,\n WithApiAuth,\n WithApiUser,\n WithDevice,\n WithOnboarding,\n WithPsdAuth,\n WithWorkspace,\n} from \"./types\";\n\nexport { fetchAll, fetchAllCursor } from \"../utils\";\nexport type * from \"./types\";\n\nconst PSK_NONCE_BYTE_LEN = 32;\n\n// Open the per-operation secure channel matching the crypto the HSM used at Prepare, branching\n// on the challenge — never on `enable_psk_secure_channel`, even when it's on. A 32-byte `handshake`\n// (hex, 64 chars) is the PSK HKDF nonce; longer is legacy Noise-K.\nconst openSecureChannel = (\n device: Device,\n challenge: Pick<PsdChallenge, \"handshake\" | \"handshakeAttestation\" | \"partitionId\">,\n): Promise<void> => {\n if (challenge.handshake.length === PSK_NONCE_BYTE_LEN * 2) {\n return device.startPskSession({\n nonce: challenge.handshake,\n partitionId: challenge.partitionId,\n });\n }\n return device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n};\n\ntype DeviceConfidentialityKey = Awaited<ReturnType<Device[\"getConfidentialityKey\"]>>;\ntype DevicePairing = Parameters<Device[\"setPairing\"]>[0][\"pairing\"];\ntype DeviceRefreshPskData = Parameters<Device[\"finalizePskRefresh\"]>[0];\n\ntype RefreshPskInput = {\n psdEphemeralKey: string;\n psdEphemeralKeyAttestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n signature: string;\n };\n validationKeySignature: string;\n};\n\nconst pairDevice = async ({\n device,\n getPairing,\n}: {\n device: Pick<Device, \"getConfidentialityKey\" | \"setPairing\">;\n getPairing: (confidentialityKey: DeviceConfidentialityKey) => Promise<DevicePairing>;\n}): Promise<void> => {\n const confidentialityKey = await device.getConfidentialityKey();\n const pairing = await getPairing(confidentialityKey);\n await device.setPairing({ pairing });\n};\n\nconst refreshPsk = async ({\n device,\n getRefreshPskData,\n}: {\n device: Pick<\n Device,\n \"finalizePskRefresh\" | \"getAttestation\" | \"initPairingHandshake\" | \"signRefreshPskAuth\"\n >;\n getRefreshPskData: (input: RefreshPskInput) => Promise<DeviceRefreshPskData>;\n}): Promise<void> => {\n // Shared refresh sub-chain: 0x46 (device NN init) + 0x55 (validation-key auth signature)\n // → HSM refresh-psk (single read-only re-delivery) → 0x53 (finalize). The HSM verifies\n // the device-attested ephemeral key and the validation-key signature, so we stitch the\n // per-ephemeral signature from INITIALIZE_NN_HANDSHAKE onto the device's static attestation\n // chain (INS_GET_ATTESTATION_CERTIFICATE) and pass the SIGN_REFRESH_PSK_AUTH signature\n // alongside. initPairingHandshake (0x46) must resolve first: the soft-device\n // signRefreshPskAuth needs the ephemeral it returns, and the firmware FSM requires 0x46\n // before 0x55.\n const eph = await device.initPairingHandshake();\n const [deviceAttestation, validationKeySignature] = await Promise.all([\n device.getAttestation(),\n device.signRefreshPskAuth({ ephemeralKey: eph.pubKey }),\n ]);\n const refresh = await getRefreshPskData({\n psdEphemeralKey: Buffer.from(eph.pubKey, \"hex\").toString(\"base64\"),\n psdEphemeralKeyAttestation: {\n codeHash: deviceAttestation.attestation.codeHash,\n attestationPub: deviceAttestation.attestation.attestationPub,\n certificate: deviceAttestation.attestation.certificate,\n signature: eph.signature,\n },\n validationKeySignature,\n });\n await device.finalizePskRefresh(refresh);\n};\n\nasync function genericRegister<T>({\n device,\n name,\n role,\n getChallenge,\n submitChallenge,\n onScreenDisplayed,\n}: {\n device: Device;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n getChallenge: (p: {\n pubKey: string;\n deviceData: UserRegistrationDeviceData;\n }) => Promise<UserRegistrationChallenge>;\n submitChallenge: (p: {\n pubKey: string;\n challengeResponse: UserRegistrationChallengeResponse;\n }) => Promise<T>;\n onScreenDisplayed?: () => void | Promise<void>;\n}): Promise<T> {\n const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([\n device.getAttestation(),\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n const ephemeralPubKey = await device.initPairingHandshake();\n const deviceData: UserRegistrationDeviceData = {\n name,\n pubKey: u2fPubKey.pubKey,\n psdModel: \"STAX\",\n confidentialityKey: confidentialityKey.pubKey,\n psdEphemeralKey: ephemeralPubKey.pubKey,\n psdEphemeralKeyAttestation: {\n ...attestation.attestation,\n signature: ephemeralPubKey.signature,\n },\n };\n const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });\n const pairingPayload = await device.finalizePairingHandshake({\n handshake: challenge.handshake,\n partitionId: challenge.ciphertext,\n handshakeAttestation: challenge.handshakeAttestation,\n });\n await onScreenDisplayed?.();\n const register = await device.register({\n challenge: challenge.challenge,\n u2fRegisterData: challenge.u2fRegisterData,\n name,\n role,\n });\n const validationPubKey = await device.getValidationPubKey();\n const registerData = await device.registerData({ challenge: challenge.challenge });\n const attestationOffset = 67 + register.u2fRegister.readInt8(66);\n const u2fRegister = Buffer.concat([\n register.u2fRegister.slice(0, attestationOffset),\n Buffer.from([attestation.buffer.length]),\n attestation.buffer,\n register.u2fRegister.slice(attestationOffset),\n ]).toString(\"hex\");\n const challengeResponse: UserRegistrationChallengeResponse = {\n registerData,\n certificate: {\n ...attestation.attestation,\n signature: validationPubKey.signature,\n },\n u2fRegister,\n u2fKeyHandle: register.keyHandle.toString(\"hex\"),\n validationKey: validationPubKey.pubKey,\n pairingPayload,\n };\n return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });\n}\n\nexport function createEngine(options: EngineOptions, logger: Logger): Engine {\n const clientOptions: TRPCClientOptions = {\n baseUrl: options.baseUrl,\n };\n const client = createClient(clientOptions);\n const apiDevice = createApiDevice(options, logger);\n\n const base: EngineBase = {\n client,\n createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),\n __options: options,\n };\n\n const withDeviceIndex: Engine[\"withDeviceIndex\"] = function <T>(\n this: Engine<T>,\n deviceIndex: number,\n ) {\n const device = apiDevice.with(deviceIndex);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withTransportId: Engine[\"withTransportId\"] = function <T>(\n this: Engine<T>,\n transportId: string,\n ) {\n const device = createRealDevice({ transportId }, logger);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withApiUser: Engine[\"withApiUser\"] = function <T>(this: Engine<T>) {\n const withApiUser: WithApiUser = { __isApiUser: true };\n return decorateEngine({ ...this, ...withApiUser } as Engine<T & WithApiUser>);\n };\n\n const withWorkspace: Engine[\"withWorkspace\"] = function <T>(\n this: Engine<T>,\n workspaceName: string,\n ) {\n const withWorkspace: WithWorkspace = { __workspaceName: workspaceName };\n return decorateEngine({ ...this, ...withWorkspace } as Engine<T & WithWorkspace>);\n };\n\n const withOnboarding: Engine[\"withOnboarding\"] = function <T>(\n this: Engine<T>,\n onboardingId: string,\n ) {\n const withOnboarding: WithOnboarding = { __onboardingId: onboardingId };\n return decorateEngine({ ...this, ...withOnboarding } as Engine<T & WithOnboarding>);\n };\n\n function decorateEngine<T>(\n engine: Engine<\n T &\n Partial<\n WithDevice & WithOnboarding & WithWorkspace & WithPsdAuth & WithApiUser & WithApiAuth\n >\n >,\n ): Engine<T> {\n function decorate<TEnhanced, TDecoration>(\n decorator: (engine: EngineBase & TEnhanced) => TDecoration,\n ): void {\n Object.assign(engine, decorator(engine as EngineBase & TEnhanced));\n }\n\n // DecorateWithDevice\n // -------------------------------------------------------------------------\n if (engine.device) {\n decorate<WithDevice, DecorateWithDevice<T>>(\n (engine) =>\n ({\n getWorkspaces: async (): Promise<string[]> => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });\n return workspaceNames;\n },\n\n getWorkspacesForSso: async (): Promise<\n RouterOutputs[\"auth\"][\"sso\"][\"findWorkspaces\"][\"workspaces\"]\n > => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaces } = await client.auth.sso.findWorkspaces.query({ pubKey });\n return workspaces;\n },\n }) satisfies DecorateWithDevice<T>,\n );\n }\n\n // DecorateWithWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {\n decorate<WithWorkspace, DecorateWithWorkspaceUnauthenticated<T>>((engine) => {\n const { __workspaceName } = engine;\n return {\n withPsdToken: function <T>(this: Engine<T>, token: string): Engine<T & WithPsdAuth> {\n const withPsdAuth: WithPsdAuth = { __psdToken: token };\n const psdAuth = `${__workspaceName}:${token}`;\n const client = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client, ...withPsdAuth } as Engine<T & WithPsdAuth>);\n },\n } satisfies DecorateWithWorkspaceUnauthenticated<T>;\n });\n }\n\n // DecorateWithDeviceAndOnboarding\n // -------------------------------------------------------------------------\n if (engine.device && engine.__onboardingId) {\n decorate<WithDevice & WithOnboarding, DecorateWithDeviceAndOnboarding>((engine) => {\n const { device, client, __onboardingId } = engine;\n\n // Whether PSK secure-channel provisioning is enabled for this onboarding's workspace.\n // On any failure default to false (legacy Noise-K) so a flag-read hiccup can't break\n // onboarding by forcing the PSK path.\n const isPskEnabled = async (): Promise<boolean> => {\n try {\n const enabled = await client.onboarding.getPskFeatureFlag.query({\n onboardingId: __onboardingId,\n });\n return enabled === true;\n } catch {\n return false;\n }\n };\n\n // Drive the device's pairing record + PSK to a fully-provisioned state.\n // Three-way switch on hasPairing() (when PSK is enabled):\n // - \"OK\" → nothing to do.\n // - \"NO_PAIRING\" → run the full pairing chain, then deliver a PSK via refresh.\n // - \"PSK_MISSING\" → pairing already exists; only run the PSK refresh sub-chain.\n // When PSK is disabled we reproduce the pre-PSK flow: pair only on NO_PAIRING, never run\n // the refresh sub-chain, and treat PSK_MISSING as a no-op (the missing-PSK is discarded).\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n const pskEnabled = await isPskEnabled();\n let pubKeyPromise: Promise<string> | undefined;\n const getPubKey = async (): Promise<string> => {\n pubKeyPromise ??= device.getU2FPubKey().then(({ pubKey }) => pubKey);\n return pubKeyPromise;\n };\n const pairCurrentDevice = async (): Promise<void> => {\n const pubKey = await getPubKey();\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.onboarding.pairDevicePartition.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data: {\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n },\n }),\n });\n };\n const refreshCurrentPsk = async (): Promise<void> => {\n const pubKey = await getPubKey();\n await refreshPsk({\n device,\n getRefreshPskData: (data) =>\n client.onboarding.refreshPsk.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data,\n }),\n });\n };\n\n await match([status, pskEnabled] as const)\n .with([\"NO_PAIRING\", false], async () => {\n await pairCurrentDevice();\n })\n .with([\"NO_PAIRING\", true], async () => {\n await pairCurrentDevice();\n await refreshCurrentPsk();\n })\n .with([\"PSK_MISSING\", false], async () => {\n // PSK FF is disabled and the vault-app returns PSK_MISSING => we can discard it\n return;\n })\n .with([\"PSK_MISSING\", true], async () => {\n await refreshCurrentPsk();\n })\n .exhaustive();\n }\n\n return {\n claimDevice: async (params: { role: ClaimedRole; deviceName: string }): Promise<void> => {\n const { role, deviceName } = params;\n const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await client.onboarding.claimDevice.mutate({\n onboardingId: __onboardingId,\n claim: { role, pubKey, deviceName, confidentialityKey },\n });\n },\n\n collectWrappingKeyFragment: async (\n wrappingKey: WrappingKeyResponse,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await device.openSession({\n secureChannel: {\n pubKey: wrappingKey.ephemeralPubKey,\n certificate: wrappingKey.ephemeralCertificate,\n },\n });\n const { attestation } = await device.getAttestation();\n await params?.onScreenDisplayed?.();\n const blob = await device.generateWrappingKeyFragment();\n await client.onboarding.submitWrappingKeyFragment.mutate({\n pubKey,\n onboardingId: __onboardingId,\n fragment: {\n blob,\n ephemeralPubKey: confidentialityKey.pubKey,\n ephemeralCertificate: {\n ...attestation,\n signature: confidentialityKey.signature,\n },\n },\n });\n },\n\n registerDevice: async (\n registerParams: RegisterOnboardingDeviceParams,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const { role, name } = registerParams;\n const getChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.generateMasterAdminRegistrationChallenge\n : client.onboarding.generateSharedOwnerRegistrationChallenge;\n const submitChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.submitMasterAdminRegistration\n : client.onboarding.submitSharedOwnerRegistration;\n await genericRegister({\n device: device,\n name,\n role,\n getChallenge: ({ pubKey, deviceData }) =>\n getChallengeMutation.mutate({\n onboardingId: __onboardingId,\n pubKey,\n deviceData,\n }),\n submitChallenge: ({ pubKey, challengeResponse }) =>\n submitChallengeMutation.mutate({\n onboardingId: engine.__onboardingId,\n pubKey,\n // FIXME this should be renamed to `challengeResponse` on backend side\n response: challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n\n reviewSharedOwner: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitReviewByMasterAdminSignature.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n reviewExternalSigners: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitExternalSignersRegistration.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n collectSeedFragment: async (\n challenge: OnboardingSeedChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const [{ pubKey }, { attestation }] = await Promise.all([\n device.getU2FPubKey(),\n device.getAttestation(),\n ]);\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const challengeResponse = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n const kkPattern = await device.startKKPatternAsResponder({\n partitionId: challenge.partitionId,\n handshake: challenge.kkHandshake,\n handshakeAttestation: challenge.kkHandshakeAttestation,\n });\n const approverBlob = await device.generateSeedFragment();\n await client.onboarding.submitSeedFragment.mutate({\n onboardingId: __onboardingId,\n pubKey,\n seedFragment: {\n challengeResponse,\n approverBlob,\n handshake: kkPattern.handshake,\n handshakeAttestation: {\n ...attestation,\n signature: kkPattern.signature,\n },\n },\n });\n },\n } satisfies DecorateWithDeviceAndOnboarding;\n });\n }\n\n // DecorateWithDeviceAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && !engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithDeviceAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { device, client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n opts?: {\n validityDurationSecs?: number;\n onScreenDisplayed?: () => void | Promise<void>;\n correlationId?: string;\n },\n ): Promise<Engine<T & WithPsdAuth>> {\n const { pubKey } = await device.getU2FPubKey();\n const challenge = await client.auth.psd.generateChallenge.mutate(\n {\n pubKey,\n workspaceName: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n await opts?.onScreenDisplayed?.();\n const authentication = await device.authenticate({\n challenge,\n workspaceName: __workspaceName,\n });\n const authPayload = {\n workspaceName: __workspaceName,\n pubKey,\n authentication,\n challengeId: challenge.challengeId,\n validityDurationSecs: opts?.validityDurationSecs,\n };\n const { token } = await client.auth.psd.authenticate.mutate(\n { ...authPayload },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withPsdAuth: WithPsdAuth = {\n __psdToken: token,\n };\n const psdAuth = `${engine.__workspaceName}:${token}`;\n const __authClient = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client: __authClient, ...withPsdAuth } as Engine<\n T & WithPsdAuth\n >);\n },\n\n register: (\n registration: UserRegistrationResponse,\n params?: OnboardingOperationParams,\n ): Promise<UserRegistrationResponse> => {\n return genericRegister({\n device,\n name: registration.name,\n role: registration.role,\n getChallenge: async ({ deviceData }) => {\n const challenge = await client.userRegistrations.generateChallenge.mutate({\n id: registration.id,\n workspaceName: __workspaceName,\n deviceData,\n });\n return challenge;\n },\n submitChallenge: ({ challengeResponse }) =>\n client.userRegistrations.submitChallenge.mutate({\n workspaceName: __workspaceName,\n id: registration.id,\n challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n } satisfies DecorateWithDeviceAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithApiUserAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {\n decorate<WithWorkspace & WithApiUser, DecorateWithApiUserAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n credentials: {\n apiKeyId: string;\n apiKeySecret: string;\n },\n opts?: { correlationId?: string },\n ): Promise<Engine<T & WithApiAuth>> {\n const res = await client.auth.authenticate.mutate(\n {\n apiKeyId: credentials.apiKeyId,\n apiKeySecret: credentials.apiKeySecret,\n workspace: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withApiAuth: WithApiAuth = {\n __apiAuth: res,\n };\n const __authClient = engine.createClient({ apiAccessToken: res.accessToken });\n return decorateEngine({ ...this, client: __authClient, ...withApiAuth } as Engine<\n T & WithApiAuth\n >);\n },\n } satisfies DecorateWithApiUserAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithWorkspacePsdAuthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithWorkspacePsdAuthenticated>((engine) => {\n const { client, device } = engine;\n\n // Whether PSK secure-channel provisioning is enabled for this workspace. On any failure\n // default to false (legacy Noise-K) so a flag-read hiccup can't force the PSK path.\n const isPskEnabled = async (): Promise<boolean> => {\n try {\n return (await client.debug.getPskFeatureFlag.query()) === true;\n } catch {\n return false;\n }\n };\n\n // Drive the device's pairing record + PSK to a fully-provisioned state. Same tri-state\n // switch as the onboarding decorator; routes through `client.debug.*` instead of\n // `client.onboarding.*` and pulls workspace context implicitly from `__psdToken`.\n // When PSK is disabled we reproduce the pre-PSK flow: pair only on NO_PAIRING, never run\n // the refresh sub-chain, and treat PSK_MISSING as a no-op (the missing-PSK is discarded).\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n const pskEnabled = await isPskEnabled();\n const pairCurrentDevice = async (): Promise<void> => {\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.debug.pairDevicePartition.mutate({\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n }),\n });\n };\n const refreshCurrentPsk = async (): Promise<void> => {\n await refreshPsk({\n device,\n getRefreshPskData: (data) => client.debug.refreshPsk.mutate(data),\n });\n };\n\n await match([status, pskEnabled] as const)\n .with([\"NO_PAIRING\", false], async () => {\n await pairCurrentDevice();\n })\n .with([\"NO_PAIRING\", true], async () => {\n await pairCurrentDevice();\n await refreshCurrentPsk();\n })\n .with([\"PSK_MISSING\", false], async () => {\n // PSK FF is disabled and the vault-app returns PSK_MISSING => we can discard it\n return;\n })\n .with([\"PSK_MISSING\", true], async () => {\n await refreshCurrentPsk();\n })\n .exhaustive();\n }\n\n const approveChallenge = async (\n challenge: PsdChallenge,\n params?: ApproveRequestParams,\n ): Promise<string> => {\n await enforcePairing();\n try {\n await openSecureChannel(device, challenge);\n } catch (err) {\n if (!isPskMissingError(err)) throw err;\n // PSK disabled = SElf not yet migrated. The HSM sends a Noise-K challenge; a\n // migrated device may emit SW_PSK_MISSING alongside a still-valid K-pattern session.\n // Discard and proceed — the channel is open.\n if (!(await isPskEnabled())) {\n logger.warning(\"Discarding SW_PSK_MISSING: PSK secure channel is disabled\");\n } else {\n // Defense-in-depth: a session opened before the PSK was wiped still hits\n // SW_PSK_MISSING here. Re-run enforcePairing() — it now sees PSK_MISSING and drives\n // the refresh sub-chain — then retry the secure-channel APDU once.\n await enforcePairing();\n await openSecureChannel(device, challenge);\n }\n }\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n return signature;\n };\n\n return {\n approve: async (\n request: VaultRequestResponse,\n params?: ApproveRequestParams,\n ): Promise<VaultRequestResponse> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n if (challenge.challengeType === \"PSD\") {\n const signature = await approveChallenge(challenge, params);\n await params?.onPsdChallengeSigned?.();\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"PSD\", signature },\n },\n buildTrpcContext(params),\n );\n }\n if (challenge.challengeType === \"SOFT\") {\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"SOFT\" },\n },\n buildTrpcContext(params),\n );\n }\n throw new Error(\"Challenge type must be either PSD or SOFT\");\n },\n\n approveChallenge,\n\n reject: (\n request: VaultRequestResponse,\n opts?: CorrelationIdOpts,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate(\n { id: request.id, data: null },\n buildTrpcContext(opts),\n );\n },\n } satisfies DecorateWithWorkspacePsdAuthenticated;\n });\n }\n\n // DecorateWithWorkspaceApiAuthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__apiAuth) {\n decorate<WithWorkspace & WithApiAuth, DecorateWithWorkspaceApiAuthenticated>((engine) => {\n const { client } = engine;\n return {\n getChallenge: async (request: VaultRequestResponse): Promise<ApiChallenge[\"payload\"]> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"API\", \"Challenge type must be API\");\n return challenge.payload;\n },\n\n approve: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n\n reject: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n } satisfies DecorateWithWorkspaceApiAuthenticated;\n });\n }\n\n return engine;\n }\n\n return {\n ...base,\n withDeviceIndex,\n withTransportId,\n withApiUser,\n withWorkspace,\n withOnboarding,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"engine.js","names":[],"sources":["../src/device/real-device.ts","../src/trpc.ts","../src/engine/index.ts"],"sourcesContent":["import { DisconnectedDevice, LockedDeviceError } from \"@ledgerhq/errors\";\nimport type Transport from \"@ledgerhq/hw-transport\";\nimport type { HsmCertificate, PubKey, RefreshPskData } from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\nimport { from, lastValueFrom } from \"rxjs\";\n\nimport type { Logger } from \"@/logger\";\n\nimport {\n APPID_VAULT_ADMINISTRATOR,\n PAGINATED_STATUS,\n PATHS,\n SCRIPT_IDS,\n STATUS_LENGTH,\n STR_ROLES,\n STREAMING_NEXT_ACTION,\n STREAMING_RESPONSE,\n} from \"./constants\";\nimport { withDevicePolling } from \"./device-access\";\nimport type { Device, PairingStatus } from \"./types\";\nimport { isTransportStatusError } from \"./utils\";\n\nconst MAX_CHUNK_LENGTH = 250;\n\ntype Options = {\n transportId: string;\n};\n\nconst getPathFromPathString = (pathString: string): number[] => {\n const parts = pathString.split(\"'/\").map((part) => Number.parseInt(part, 10));\n return parts.map((part) => (part | 0x80000000) >>> 0);\n};\n\nconst splitChunks = (chunk: number, buffer: Buffer): Buffer[] => {\n const chunks = [];\n for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {\n chunks.push(buffer.slice(i, i + size));\n }\n return chunks;\n};\n\nconst removeStatus = (result: Buffer): Buffer => result.slice(0, result.length - STATUS_LENGTH);\n\nconst sendByChunk = async (\n transport: Transport,\n command: number[], // eg [0xe0, 0x45, 0x00, 0x00]\n data: Buffer,\n chunkSize: number = MAX_CHUNK_LENGTH,\n): Promise<Buffer> => {\n const chunks = splitChunks(chunkSize, data);\n let response = Buffer.from([]);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const apdu = [...command];\n // command is 0xe0,0x45,0x00,0x00 for first chunk, then it's 0xe0,0x45,0x80,0x00\n /* v8 ignore next -- @preserve */\n apdu[2] = i && 0x80;\n response = (await transport.send(apdu[0]!, apdu[1]!, apdu[2], apdu[3]!, chunk, [\n 0x9000,\n ...PAGINATED_STATUS,\n ])) as Buffer<ArrayBuffer>;\n }\n return response;\n};\n\nconst buildAttestation = (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n}): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const cliMsgBuffer = Buffer.from(params.handshake, \"hex\");\n const cliMsgLengthBuffer = Buffer.alloc(1);\n cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);\n\n const pidBuffer = Buffer.from(params.partitionId, \"hex\");\n const pidLengthBuffer = Buffer.alloc(1);\n pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n cliMsgLengthBuffer,\n cliMsgBuffer,\n certChainDataLengthBuff,\n certChainData,\n pidLengthBuffer,\n pidBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n const toSend = Buffer.concat([totalLengthBuffer, data]);\n\n return toSend;\n};\n\n// Wire-format builder for FINALIZE_PSK_REFRESH (`0xE0 0x53`). Same layout as `buildAttestation`\n// (consumed by the device's `parse_nn_handshake_payload`), but the trailing TLV carries the\n// encrypted PairingPayload from `RefreshPsk` instead of a partition ID.\n//\n// Layout after the leading 2-byte total length:\n// [1] handshake length (the NN responder handshake, written from its actual decoded length)\n// [N] handshake bytes\n// [2] cert-chain-data length (BE)\n// [1] handshake-cert (DER signature) length\n// [N] handshake-cert bytes\n// [65] vault attestation pubkey (raw 0x04|x|y, no length prefix)\n// [1] att-cert length\n// [M] att-cert bytes\n// [1] ciphered-payload length\n// [K] encrypted PairingPayload bytes\nconst buildPskRefreshPayload = (params: RefreshPskData): Buffer => {\n const sigBuffer = Buffer.from(params.handshakeAttestation.signature, \"base64\");\n const sigLengthBuffer = Buffer.alloc(1);\n sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);\n\n const certBuffer = Buffer.from(params.handshakeAttestation.certificate, \"base64\");\n const certLengthBuffer = Buffer.alloc(1);\n certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);\n\n const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, \"base64\");\n\n const certChainData = Buffer.concat([\n sigLengthBuffer,\n sigBuffer,\n pubBuffer,\n certLengthBuffer,\n certBuffer,\n ]);\n\n const handshakeBuffer = Buffer.from(params.handshake, \"base64\");\n invariant(\n handshakeBuffer.length <= 255,\n `PSK refresh handshake too long: ${handshakeBuffer.length} bytes (max 255)`,\n );\n const handshakeLengthBuffer = Buffer.alloc(1);\n handshakeLengthBuffer.writeUInt8(handshakeBuffer.length, 0);\n\n const encryptedPayloadBuffer = Buffer.from(params.encryptedPairingPayload, \"base64\");\n invariant(\n encryptedPayloadBuffer.length <= 255,\n `PSK encrypted payload too long: ${encryptedPayloadBuffer.length} bytes (max 255)`,\n );\n const encryptedPayloadLengthBuffer = Buffer.alloc(1);\n encryptedPayloadLengthBuffer.writeUInt8(encryptedPayloadBuffer.length, 0);\n\n const certChainDataLengthBuff = Buffer.alloc(2);\n certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);\n\n const data = Buffer.concat([\n handshakeLengthBuffer,\n handshakeBuffer,\n certChainDataLengthBuff,\n certChainData,\n encryptedPayloadLengthBuffer,\n encryptedPayloadBuffer,\n ]);\n\n const totalLengthBuffer = Buffer.alloc(2);\n totalLengthBuffer.writeUInt16BE(data.length, 0);\n\n return Buffer.concat([totalLengthBuffer, data]);\n};\n\ntype RetryOnError = (err: Error) => boolean;\n/* v8 ignore next -- @preserve */\nconst genericRetryOnError: RetryOnError = (err) => {\n // device is locked\n if (err instanceof LockedDeviceError) return true;\n // user is on dashboard when receiving a Vault app apdu\n if (isTransportStatusError(err) && err.statusCode === 0x6d09) return true;\n // VG-24797 error that can happen in BLE in some situations (still unclear)\n if (err instanceof DisconnectedDevice) return true;\n\n // for everything else, we don't want to retry\n return false;\n};\n\nexport function createRealDevice(options: Options, logger: Logger): Device {\n const { transportId } = options;\n\n async function run<T>(\n job: (transport: Transport) => Promise<T>,\n retryOnError: RetryOnError = genericRetryOnError,\n ): Promise<T> {\n return lastValueFrom(\n withDevicePolling(transportId)<T>((transport) => from(job(transport)), retryOnError),\n );\n }\n\n /* v8 ignore next -- @preserve */\n const noRetry = (): boolean => false;\n /* v8 ignore next -- @preserve */\n const alwaysRetry = (): boolean => true;\n const poll = async (\n opts: { retryOnError?: RetryOnError } = {},\n ): Promise<{ isAppOpened: boolean }> => {\n // waiting for device to be turned on\n await run(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n async (_transport) => {},\n opts.retryOnError ?? alwaysRetry,\n );\n // checking if app is opened: should return directly on getPubKey\n try {\n await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });\n return { isAppOpened: true };\n } catch (err) {\n if (isTransportStatusError(err) && genericRetryOnError(err)) {\n return { isAppOpened: false };\n }\n throw err;\n }\n };\n\n const pollApp = async (appName: string): Promise<string> => {\n const res = await run((transport) =>\n transport.send(0xe0, 0xd8, 0x00, 0x00, Buffer.from(appName, \"utf8\")),\n );\n // little delay to give time to the app to be fully opened\n await new Promise((r) => setTimeout(r, 1e3));\n return res.toString(\"hex\");\n };\n\n const getPublicKey = async (\n pathString: string,\n { secp256k1, retryOnError }: { secp256k1: boolean; retryOnError?: RetryOnError },\n ): Promise<{ pubKey: string; signature: string }> => {\n logger.info(`[device] getPublicKey (${pathString})`);\n const path = getPathFromPathString(pathString);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const curve = secp256k1 ? 0x01 : 0x02;\n const response = await run(\n (transport) => transport.send(0xe0, 0x40, curve, 0x00, data),\n retryOnError ?? genericRetryOnError,\n );\n const pubKeyLength = response.readInt8(0);\n const pubKey = response\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = response\n .slice(pubKeyLength + 1, response.length - STATUS_LENGTH)\n .toString(\"base64\");\n return { pubKey, signature };\n };\n\n const device: Device = {\n authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {\n logger.info(`[device] Authenticate`);\n invariant(role !== \"READ_ONLY_API_KEY\", \"Invalid role for authenticate: READ_ONLY_API_KEY\");\n const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n const nameBuffer = Buffer.from(name);\n const workspaceBuffer = Buffer.from(workspaceName);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([nameBuffer.length]),\n nameBuffer,\n Buffer.from([workspaceBuffer.length]),\n workspaceBuffer,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([\n Buffer.from(challenge, \"base64\"),\n applicationBuffer,\n Buffer.from([keyHandle.length]),\n Buffer.from(keyHandle, \"hex\"),\n keyHandleDataLength,\n keyHandleData,\n ]);\n\n const authentication = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x02, 0x00, 0x00], data),\n );\n\n return removeStatus(authentication).toString(\"hex\");\n },\n\n finalizePairingHandshake: async (params: {\n handshake: string;\n partitionId: string;\n handshakeAttestation: HsmCertificate;\n }): Promise<string> => {\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x47, 0x00, 0x02], buildAttestation(params)),\n );\n return removeStatus(bufWithStatus).toString(\"hex\");\n },\n\n generateSeedFragment: async (): Promise<string> => {\n logger.info(`[device] generateSeedFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x00, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n generateWrappingKeyFragment: async (): Promise<string> => {\n logger.info(`[device] generateWrappingKeyFragment`);\n const path = getPathFromPathString(PATHS.KEY_MATERIAL);\n const data = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n const response = await run((transport) => transport.send(0xe0, 0x44, 0x01, 0x00, data));\n return removeStatus(response).toString(\"base64\");\n },\n getAttestation: async (): Promise<{\n attestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n };\n buffer: Buffer;\n }> => {\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x41, 0x00, 0x00));\n const buffer = removeStatus(bufWithStatus);\n const certLen = buffer.readInt8(32 + 65 + 1);\n return {\n attestation: {\n codeHash: buffer.slice(0, 32).toString(\"base64\"),\n attestationPub: buffer.slice(32, 32 + 65).toString(\"base64\"),\n certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString(\"base64\"),\n },\n buffer,\n };\n },\n getConfidentialityKey: async () => {\n logger.info(`[device] getConfidentialityKey`);\n const bufWithStatus = await run((transport) => transport.send(0xe0, 0x4d, 0x00, 0x00));\n const buf = removeStatus(bufWithStatus);\n const keyLength = buf[0]!;\n const key = buf.slice(1, 1 + keyLength);\n const sig = buf.slice(1 + keyLength + 1);\n return {\n confidentialityKeyCurve25519: key.toString(\"hex\"),\n confidentialityKeySignature: sig.toString(\"hex\"),\n };\n },\n getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),\n getDeviceUserId: async (): Promise<string> => {\n logger.info(`[device] getDeviceUserId`);\n const response = await run((transport) => transport.send(0xe0, 0x52, 0x00, 0x00));\n return removeStatus(response).toString(\"hex\").toUpperCase();\n },\n getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),\n getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),\n hasPairing: async (): Promise<PairingStatus> => {\n logger.info(`[device] hasPairing`);\n const apdu = [0xe0, 0x51, 0x00, 0x00, 0xb5];\n const res = await run((transport) => transport.exchange(Buffer.from(apdu)));\n\n // GET_PARTITION_IDS returns the partition list followed by a 2-byte SW. Inspect only\n // the trailing SW; the device may return data alongside non-`9000` SWs (notably 0x6065\n // — see below).\n const swHex = res.subarray(res.length - 2).toString(\"hex\");\n\n // 6f45 => no partition ID on the device (SW_NO_PARTITION_ID).\n // 6a87 => TEMPORARY hack: some firmware revs don't implement the APDU and return\n // \"incorrect length\"; treat as no pairing so revault drives the full pair-from-\n // scratch flow.\n if (swHex === \"6f45\" || swHex === \"6a87\") return \"NO_PAIRING\";\n\n // 6065 => SW_PSK_MISSING: a valid pairing record exists but its PSK field is the all-\n // zero sentinel. Skip the full pairing chain and run the refresh sub-chain.\n if (swHex === \"6065\") return \"PSK_MISSING\";\n\n // Anything else (typically 9000) => fully provisioned pairing with PSK.\n return \"OK\";\n },\n\n initPairingHandshake: async (): Promise<{ pubKey: string; signature: string }> => {\n const res = await run((transport) => transport.send(0xe0, 0x46, 0x00, 0x00));\n const pubKeyLength = res.readInt8(0);\n const pubKey = res\n .slice(1, pubKeyLength + 1)\n .toString(\"hex\")\n .toUpperCase();\n const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString(\"base64\");\n return { pubKey, signature };\n },\n\n openSession: async (params: {\n secureChannel: { pubKey: PubKey; certificate: HsmCertificate };\n }): Promise<void> => {\n logger.info(`[device] openSession`);\n const { secureChannel } = params;\n\n const path = getPathFromPathString(PATHS.CONFIDENTIALITY);\n const dataDerivation = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n const pubKey = Buffer.from(secureChannel.pubKey, \"hex\");\n\n const sigBuffer = Buffer.from(secureChannel.certificate.signature, \"base64\");\n const attestationPubBuffer = Buffer.from(secureChannel.certificate.attestationPub, \"base64\");\n const certBuffer = Buffer.from(secureChannel.certificate.certificate, \"base64\");\n const attestation = Buffer.concat([\n Buffer.from([sigBuffer.length]),\n sigBuffer,\n attestationPubBuffer,\n Buffer.from([certBuffer.length]),\n certBuffer,\n ]);\n\n const lengthAttestation = Buffer.alloc(2);\n lengthAttestation.writeUInt16BE(attestation.length, 0);\n\n const data = Buffer.concat([dataDerivation, pubKey, lengthAttestation, attestation]);\n\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x42, 0x00, SCRIPT_IDS.INIT_SESSION], data),\n );\n },\n\n register: async (params: {\n challenge: string;\n u2fRegisterData: string;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n }): Promise<{\n u2fRegister: Buffer;\n keyHandle: Buffer;\n rfu: number;\n pubKey: string;\n }> => {\n const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, \"hex\");\n invariant(applicationBuf.length === 32, \"application hex is expected to have 32 bytes\");\n\n const userNameBuff = Buffer.from(name);\n\n const keyHandleData = Buffer.concat([\n Buffer.from(STR_ROLES[role], \"hex\"),\n Buffer.from([userNameBuff.length]),\n userNameBuff,\n ]);\n\n const keyHandleDataLength = Buffer.alloc(2);\n keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);\n\n const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);\n\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x01, 0x00, 0x00], data),\n );\n\n let i = 0;\n const rfu = response.slice(i, i + 1)[0]!;\n i += 1;\n const pubKey = response.slice(i, i + 65).toString(\"hex\");\n i += 65;\n const keyHandleLength = response.slice(i, i + 1)[0]!;\n i++;\n const keyHandle = response.slice(i, i + keyHandleLength);\n i += keyHandleLength;\n return {\n u2fRegister: removeStatus(response),\n keyHandle,\n rfu,\n pubKey,\n };\n },\n registerData: async (params: { challenge: string }): Promise<string> => {\n const { challenge: strChallenge } = params;\n const challenge = Buffer.from(strChallenge, \"hex\");\n invariant(challenge.length === 32, \"challenge hex is expected to have 32 bytes\");\n const response = await run((transport) => transport.send(0xe0, 0x03, 0x00, 0x00, challenge));\n return removeStatus(response).toString(\"hex\");\n },\n\n setPairing: async ({ pairing }) => {\n logger.info(`[device] setPairing`);\n const psdPayload = Buffer.from(pairing.blob, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(psdPayload.length, 0);\n const final = Buffer.concat([length, psdPayload]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x4e, 0x00, 0x00], final));\n },\n\n // `ephemeralKey` is unused here: the firmware signs over the ephemeral it captured in its own\n // `G_nn_initiator_eph_pubkey` global at INITIALIZE_NN_HANDSHAKE, and INS 0x55 rejects any\n // payload. The arg only exists for the stateless device-api (see api-device.ts).\n signRefreshPskAuth: async (): Promise<string> => {\n logger.info(`[device] signRefreshPskAuth`);\n const res = await run((transport) => transport.send(0xe0, 0x55, 0x00, 0x00));\n return res.slice(0, res.length - STATUS_LENGTH).toString(\"base64\");\n },\n\n finalizePskRefresh: async (params: RefreshPskData): Promise<void> => {\n logger.info(`[device] finalizePskRefresh`);\n const payload = buildPskRefreshPayload(params);\n await run((transport) => sendByChunk(transport, [0xe0, 0x53, 0x00, 0x00], payload));\n },\n startKKPatternAsResponder: async (params: {\n handshake: string;\n handshakeAttestation: HsmCertificate;\n partitionId: string;\n }): Promise<{ handshake: string; signature: string }> => {\n logger.info(`[device] startKKPatternAsResponder`);\n const data = buildAttestation(params);\n const bufWithStatus = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x4c, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n const buffer = removeStatus(bufWithStatus);\n const dataLength = buffer.readInt8(0);\n return {\n handshake: buffer.slice(1, dataLength + 1).toString(\"base64\"),\n signature: buffer.slice(dataLength + 1).toString(\"base64\"),\n };\n },\n startKPatternAsResponder: async (params) => {\n logger.info(`[device] startKPatternAsResponder`);\n const data = buildAttestation(params);\n await run((transport) =>\n sendByChunk(transport, [0xe0, 0x49, 0x00, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data),\n );\n },\n startPskSession: async (params) => {\n logger.info(`[device] startPskSession`);\n // START_PSK_SESSION (0xe0 0x50): the device reads a raw `nonce(32) || partitionId(16)`\n // payload straight from cmd->data (lc must be exactly 48) — no length prefixes and no\n // attestation. The dispatcher also rejects any non-zero P1/P2 with SW_WRONG_P1P2, so\n // both stay 0 (unlike the K handshake, which ignores P2 = ACCOUNT_MANAGER_SESSION).\n invariant(\n params.nonce.length === 64,\n `PSK nonce must be 32 bytes (64 hex chars), got ${params.nonce.length} chars`,\n );\n invariant(\n params.partitionId.length === 32,\n `partitionId must be 16 bytes (32 hex chars), got ${params.partitionId.length} chars`,\n );\n const data = Buffer.concat([\n Buffer.from(params.nonce, \"hex\"),\n Buffer.from(params.partitionId, \"hex\"),\n ]);\n await run((transport) => sendByChunk(transport, [0xe0, 0x50, 0x00, 0x00], data));\n },\n validateVaultOperation: async (params) => {\n logger.info(`[device] validateVaultOperation`);\n const path = getPathFromPathString(PATHS.VALIDATION);\n const paths = Buffer.concat([\n Buffer.from([path.length]),\n ...path.map((derivation) => {\n const buf = Buffer.alloc(4);\n buf.writeUInt32BE(derivation, 0);\n return buf;\n }),\n ]);\n\n let nextActionId = 1;\n let finalResponse: Buffer | null = null;\n\n while (!finalResponse) {\n const screen = Buffer.from(params.actions[nextActionId - 1]!, \"base64\");\n const length = Buffer.alloc(2);\n length.writeUInt16BE(screen.length, 0);\n const data = Buffer.concat([paths, length, screen]);\n const response = await run((transport) =>\n sendByChunk(transport, [0xe0, 0x45, 0x00, 0x00], data),\n );\n const responseType = response.readInt8(0);\n let responseStatus = response.readUInt16BE(response.length - 2);\n switch (responseType) {\n case STREAMING_NEXT_ACTION:\n nextActionId = response.readUIntBE(1, 2);\n break;\n case STREAMING_RESPONSE:\n finalResponse = response.slice(3, response.length - 2);\n while (responseStatus !== 0x9000) {\n /* v8 ignore next -- @preserve */ {\n const resp = await run((transport) => transport.send(0x00, 0xc0, 0x00, 0x00));\n responseStatus = resp.readUInt16BE(resp.length - 2);\n finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);\n }\n }\n break;\n /* v8 ignore next -- @preserve */\n default:\n throw new Error(`Invalid response type: ${responseType}`);\n }\n }\n return finalResponse.toString(\"base64\");\n },\n\n sendAPDU: async (apduCommand: string) => {\n const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, \"hex\")));\n return Buffer.from(res).toString(\"hex\");\n },\n getVersion: async () => {\n const res = await run((transport) => transport.send(0xb0, 0x01, 0x00, 0x00));\n const appNameLen = res.readInt8(1);\n const appVersionLen = res.readInt8(2 + appNameLen);\n const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);\n\n const appVersion = Buffer.from(appVersionHex).toString();\n\n return appVersion;\n },\n poll,\n pollApp,\n };\n return device;\n}\n","import type { AppRouter } from \"@ledgerhq/revault-api\";\nimport { createTRPCClient, httpLink, type TRPCClient } from \"@trpc/client\";\nimport type { inferRouterInputs, inferRouterOutputs } from \"@trpc/server\";\nimport superjson from \"superjson\";\n\nexport type TRPCClientOptions = {\n baseUrl: string;\n debugAuthToken?: string;\n rootAuthToken?: string;\n apiAccessToken?: string;\n psdAuth?: string;\n};\n\nexport type RevaultApiTRPCClient = TRPCClient<AppRouter>;\n\nexport type RouterInputs = inferRouterInputs<AppRouter>;\nexport type RouterOutputs = inferRouterOutputs<AppRouter>;\n\nexport type TRPCContext = { context: Record<string, unknown> } | undefined;\n\nexport const createClient = (options: TRPCClientOptions): RevaultApiTRPCClient => {\n const trpc = createTRPCClient<AppRouter>({\n links: [\n httpLink({\n url: `${options.baseUrl}/trpc`,\n transformer: superjson,\n headers(opts) {\n // Extract headers from the operation context\n const contextHeaders = (opts.op.context?.headers as Record<string, string>) || {};\n\n return {\n ...(options.debugAuthToken\n ? { \"x-revault-debug-auth-token\": options.debugAuthToken }\n : {}),\n ...(options.rootAuthToken\n ? { \"x-revault-root-auth-token\": options.rootAuthToken }\n : {}),\n ...(options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {}),\n ...(options.apiAccessToken\n ? { Authorization: `Bearer ${options.apiAccessToken}` }\n : {}),\n // Merge in any headers passed via context\n ...contextHeaders,\n };\n },\n }),\n ],\n });\n return trpc;\n};\n","import type {\n ApiChallenge,\n ClaimedRole,\n OnboardingSeedChallenge,\n PsdChallenge,\n UserRegistrationChallenge,\n UserRegistrationChallengeResponse,\n UserRegistrationDeviceData,\n UserRegistrationResponse,\n VaultRequestResponse,\n WrappingKeyResponse,\n} from \"@ledgerhq/revault-api\";\nimport invariant from \"invariant\";\n\nimport { createApiDevice, type Device, isPskMissingError } from \"@/device\";\nimport { createRealDevice } from \"@/device/real-device\";\nimport type { Logger } from \"@/logger\";\nimport { createClient, type RouterOutputs, type TRPCClientOptions } from \"@/trpc\";\n\nimport { buildTrpcContext } from \"../utils\";\nimport type {\n ApproveRequestParams,\n CorrelationIdOpts,\n DecorateWithApiUserAndWorkspaceUnauthenticated,\n DecorateWithDevice,\n DecorateWithDeviceAndOnboarding,\n DecorateWithDeviceAndWorkspaceUnauthenticated,\n DecorateWithWorkspaceApiAuthenticated,\n DecorateWithWorkspacePsdAuthenticated,\n DecorateWithWorkspaceUnauthenticated,\n Engine,\n EngineBase,\n EngineOptions,\n OnboardingOperationParams,\n RegisterOnboardingDeviceParams,\n WithApiAuth,\n WithApiUser,\n WithDevice,\n WithOnboarding,\n WithPsdAuth,\n WithWorkspace,\n} from \"./types\";\n\nexport { fetchAll, fetchAllCursor } from \"../utils\";\nexport type * from \"./types\";\n\nconst PSK_NONCE_BYTE_LEN = 32;\n\n// Open the per-operation secure channel matching the crypto the HSM used at Prepare, branching\n// on the challenge shape. A 32-byte `handshake` (hex, 64 chars) is the PSK HKDF nonce;\n// longer is legacy Noise-K.\nconst openSecureChannel = (\n device: Device,\n challenge: Pick<PsdChallenge, \"handshake\" | \"handshakeAttestation\" | \"partitionId\">,\n): Promise<void> => {\n if (challenge.handshake.length === PSK_NONCE_BYTE_LEN * 2) {\n return device.startPskSession({\n nonce: challenge.handshake,\n partitionId: challenge.partitionId,\n });\n }\n return device.startKPatternAsResponder({\n handshake: challenge.handshake,\n handshakeAttestation: challenge.handshakeAttestation,\n partitionId: challenge.partitionId,\n });\n};\n\ntype DeviceConfidentialityKey = Awaited<ReturnType<Device[\"getConfidentialityKey\"]>>;\ntype DevicePairing = Parameters<Device[\"setPairing\"]>[0][\"pairing\"];\ntype DeviceRefreshPskData = Parameters<Device[\"finalizePskRefresh\"]>[0];\n\ntype RefreshPskInput = {\n psdEphemeralKey: string;\n psdEphemeralKeyAttestation: {\n codeHash: string;\n attestationPub: string;\n certificate: string;\n signature: string;\n };\n validationKeySignature: string;\n};\n\nconst pairDevice = async ({\n device,\n getPairing,\n}: {\n device: Pick<Device, \"getConfidentialityKey\" | \"setPairing\">;\n getPairing: (confidentialityKey: DeviceConfidentialityKey) => Promise<DevicePairing>;\n}): Promise<void> => {\n const confidentialityKey = await device.getConfidentialityKey();\n const pairing = await getPairing(confidentialityKey);\n await device.setPairing({ pairing });\n};\n\nconst refreshPsk = async ({\n device,\n getRefreshPskData,\n}: {\n device: Pick<\n Device,\n \"finalizePskRefresh\" | \"getAttestation\" | \"initPairingHandshake\" | \"signRefreshPskAuth\"\n >;\n getRefreshPskData: (input: RefreshPskInput) => Promise<DeviceRefreshPskData>;\n}): Promise<void> => {\n // Shared refresh sub-chain: 0x46 (device NN init) + 0x55 (validation-key auth signature)\n // → HSM refresh-psk (single read-only re-delivery) → 0x53 (finalize). The HSM verifies\n // the device-attested ephemeral key and the validation-key signature, so we stitch the\n // per-ephemeral signature from INITIALIZE_NN_HANDSHAKE onto the device's static attestation\n // chain (INS_GET_ATTESTATION_CERTIFICATE) and pass the SIGN_REFRESH_PSK_AUTH signature\n // alongside. initPairingHandshake (0x46) must resolve first: the soft-device\n // signRefreshPskAuth needs the ephemeral it returns, and the firmware FSM requires 0x46\n // before 0x55.\n const eph = await device.initPairingHandshake();\n const [deviceAttestation, validationKeySignature] = await Promise.all([\n device.getAttestation(),\n device.signRefreshPskAuth({ ephemeralKey: eph.pubKey }),\n ]);\n const refresh = await getRefreshPskData({\n psdEphemeralKey: Buffer.from(eph.pubKey, \"hex\").toString(\"base64\"),\n psdEphemeralKeyAttestation: {\n codeHash: deviceAttestation.attestation.codeHash,\n attestationPub: deviceAttestation.attestation.attestationPub,\n certificate: deviceAttestation.attestation.certificate,\n signature: eph.signature,\n },\n validationKeySignature,\n });\n await device.finalizePskRefresh(refresh);\n};\n\nasync function genericRegister<T>({\n device,\n name,\n role,\n getChallenge,\n submitChallenge,\n onScreenDisplayed,\n}: {\n device: Device;\n name: string;\n role: \"ADMIN\" | \"SHARED_OWNER\" | \"OPERATOR\";\n getChallenge: (p: {\n pubKey: string;\n deviceData: UserRegistrationDeviceData;\n }) => Promise<UserRegistrationChallenge>;\n submitChallenge: (p: {\n pubKey: string;\n challengeResponse: UserRegistrationChallengeResponse;\n }) => Promise<T>;\n onScreenDisplayed?: () => void | Promise<void>;\n}): Promise<T> {\n const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([\n device.getAttestation(),\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n const ephemeralPubKey = await device.initPairingHandshake();\n const deviceData: UserRegistrationDeviceData = {\n name,\n pubKey: u2fPubKey.pubKey,\n psdModel: \"STAX\",\n confidentialityKey: confidentialityKey.pubKey,\n psdEphemeralKey: ephemeralPubKey.pubKey,\n psdEphemeralKeyAttestation: {\n ...attestation.attestation,\n signature: ephemeralPubKey.signature,\n },\n };\n const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });\n const pairingPayload = await device.finalizePairingHandshake({\n handshake: challenge.handshake,\n partitionId: challenge.ciphertext,\n handshakeAttestation: challenge.handshakeAttestation,\n });\n await onScreenDisplayed?.();\n const register = await device.register({\n challenge: challenge.challenge,\n u2fRegisterData: challenge.u2fRegisterData,\n name,\n role,\n });\n const validationPubKey = await device.getValidationPubKey();\n const registerData = await device.registerData({ challenge: challenge.challenge });\n const attestationOffset = 67 + register.u2fRegister.readInt8(66);\n const u2fRegister = Buffer.concat([\n register.u2fRegister.slice(0, attestationOffset),\n Buffer.from([attestation.buffer.length]),\n attestation.buffer,\n register.u2fRegister.slice(attestationOffset),\n ]).toString(\"hex\");\n const challengeResponse: UserRegistrationChallengeResponse = {\n registerData,\n certificate: {\n ...attestation.attestation,\n signature: validationPubKey.signature,\n },\n u2fRegister,\n u2fKeyHandle: register.keyHandle.toString(\"hex\"),\n validationKey: validationPubKey.pubKey,\n pairingPayload,\n };\n return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });\n}\n\nexport function createEngine(options: EngineOptions, logger: Logger): Engine {\n const clientOptions: TRPCClientOptions = {\n baseUrl: options.baseUrl,\n };\n const client = createClient(clientOptions);\n const apiDevice = createApiDevice(options, logger);\n\n const base: EngineBase = {\n client,\n createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),\n __options: options,\n };\n\n const withDeviceIndex: Engine[\"withDeviceIndex\"] = function <T>(\n this: Engine<T>,\n deviceIndex: number,\n ) {\n const device = apiDevice.with(deviceIndex);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withTransportId: Engine[\"withTransportId\"] = function <T>(\n this: Engine<T>,\n transportId: string,\n ) {\n const device = createRealDevice({ transportId }, logger);\n const withPsd: WithDevice = { device };\n return decorateEngine({ ...this, ...withPsd } as Engine<T & WithDevice>);\n };\n\n const withApiUser: Engine[\"withApiUser\"] = function <T>(this: Engine<T>) {\n const withApiUser: WithApiUser = { __isApiUser: true };\n return decorateEngine({ ...this, ...withApiUser } as Engine<T & WithApiUser>);\n };\n\n const withWorkspace: Engine[\"withWorkspace\"] = function <T>(\n this: Engine<T>,\n workspaceName: string,\n ) {\n const withWorkspace: WithWorkspace = { __workspaceName: workspaceName };\n return decorateEngine({ ...this, ...withWorkspace } as Engine<T & WithWorkspace>);\n };\n\n const withOnboarding: Engine[\"withOnboarding\"] = function <T>(\n this: Engine<T>,\n onboardingId: string,\n ) {\n const withOnboarding: WithOnboarding = { __onboardingId: onboardingId };\n return decorateEngine({ ...this, ...withOnboarding } as Engine<T & WithOnboarding>);\n };\n\n function decorateEngine<T>(\n engine: Engine<\n T &\n Partial<\n WithDevice & WithOnboarding & WithWorkspace & WithPsdAuth & WithApiUser & WithApiAuth\n >\n >,\n ): Engine<T> {\n function decorate<TEnhanced, TDecoration>(\n decorator: (engine: EngineBase & TEnhanced) => TDecoration,\n ): void {\n Object.assign(engine, decorator(engine as EngineBase & TEnhanced));\n }\n\n // DecorateWithDevice\n // -------------------------------------------------------------------------\n if (engine.device) {\n decorate<WithDevice, DecorateWithDevice<T>>(\n (engine) =>\n ({\n getWorkspaces: async (): Promise<string[]> => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });\n return workspaceNames;\n },\n\n getWorkspacesForSso: async (): Promise<\n RouterOutputs[\"auth\"][\"sso\"][\"findWorkspaces\"][\"workspaces\"]\n > => {\n const { device, client } = engine;\n const { pubKey } = await device.getU2FPubKey();\n const { workspaces } = await client.auth.sso.findWorkspaces.query({ pubKey });\n return workspaces;\n },\n }) satisfies DecorateWithDevice<T>,\n );\n }\n\n // DecorateWithWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {\n decorate<WithWorkspace, DecorateWithWorkspaceUnauthenticated<T>>((engine) => {\n const { __workspaceName } = engine;\n return {\n withPsdToken: function <T>(this: Engine<T>, token: string): Engine<T & WithPsdAuth> {\n const withPsdAuth: WithPsdAuth = { __psdToken: token };\n const psdAuth = `${__workspaceName}:${token}`;\n const client = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client, ...withPsdAuth } as Engine<T & WithPsdAuth>);\n },\n } satisfies DecorateWithWorkspaceUnauthenticated<T>;\n });\n }\n\n // DecorateWithDeviceAndOnboarding\n // -------------------------------------------------------------------------\n if (engine.device && engine.__onboardingId) {\n decorate<WithDevice & WithOnboarding, DecorateWithDeviceAndOnboarding>((engine) => {\n const { device, client, __onboardingId } = engine;\n\n // Drive the device's pairing record + PSK to a fully-provisioned state.\n // - \"OK\" → nothing to do.\n // - \"NO_PAIRING\" → run the full pairing chain, then deliver a PSK via refresh.\n // - \"PSK_MISSING\" → pairing already exists; only run the PSK refresh sub-chain.\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n let pubKeyPromise: Promise<string> | undefined;\n const getPubKey = async (): Promise<string> => {\n pubKeyPromise ??= device.getU2FPubKey().then(({ pubKey }) => pubKey);\n return pubKeyPromise;\n };\n const refreshCurrentPsk = async (): Promise<void> => {\n const pubKey = await getPubKey();\n await refreshPsk({\n device,\n getRefreshPskData: (data) =>\n client.onboarding.refreshPsk.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data,\n }),\n });\n };\n\n if (status === \"NO_PAIRING\") {\n const pubKey = await getPubKey();\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.onboarding.pairDevicePartition.mutate({\n pubKey,\n onboardingId: __onboardingId,\n data: {\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n },\n }),\n });\n }\n\n await refreshCurrentPsk();\n }\n\n return {\n claimDevice: async (params: { role: ClaimedRole; deviceName: string }): Promise<void> => {\n const { role, deviceName } = params;\n const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await client.onboarding.claimDevice.mutate({\n onboardingId: __onboardingId,\n claim: { role, pubKey, deviceName, confidentialityKey },\n });\n },\n\n collectWrappingKeyFragment: async (\n wrappingKey: WrappingKeyResponse,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const [{ pubKey }, confidentialityKey] = await Promise.all([\n device.getU2FPubKey(),\n device.getConfidentialityPubKey(),\n ]);\n await device.openSession({\n secureChannel: {\n pubKey: wrappingKey.ephemeralPubKey,\n certificate: wrappingKey.ephemeralCertificate,\n },\n });\n const { attestation } = await device.getAttestation();\n await params?.onScreenDisplayed?.();\n const blob = await device.generateWrappingKeyFragment();\n await client.onboarding.submitWrappingKeyFragment.mutate({\n pubKey,\n onboardingId: __onboardingId,\n fragment: {\n blob,\n ephemeralPubKey: confidentialityKey.pubKey,\n ephemeralCertificate: {\n ...attestation,\n signature: confidentialityKey.signature,\n },\n },\n });\n },\n\n registerDevice: async (\n registerParams: RegisterOnboardingDeviceParams,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n const { role, name } = registerParams;\n const getChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.generateMasterAdminRegistrationChallenge\n : client.onboarding.generateSharedOwnerRegistrationChallenge;\n const submitChallengeMutation =\n role === \"ADMIN\"\n ? client.onboarding.submitMasterAdminRegistration\n : client.onboarding.submitSharedOwnerRegistration;\n await genericRegister({\n device: device,\n name,\n role,\n getChallenge: ({ pubKey, deviceData }) =>\n getChallengeMutation.mutate({\n onboardingId: __onboardingId,\n pubKey,\n deviceData,\n }),\n submitChallenge: ({ pubKey, challengeResponse }) =>\n submitChallengeMutation.mutate({\n onboardingId: engine.__onboardingId,\n pubKey,\n // FIXME this should be renamed to `challengeResponse` on backend side\n response: challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n\n reviewSharedOwner: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitReviewByMasterAdminSignature.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n reviewExternalSigners: async (\n challenge: PsdChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const { pubKey } = await device.getU2FPubKey();\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n await client.onboarding.submitExternalSignersRegistration.mutate({\n onboardingId: __onboardingId,\n pubKey,\n signature,\n });\n },\n\n collectSeedFragment: async (\n challenge: OnboardingSeedChallenge,\n params?: OnboardingOperationParams,\n ): Promise<void> => {\n await enforcePairing();\n const [{ pubKey }, { attestation }] = await Promise.all([\n device.getU2FPubKey(),\n device.getAttestation(),\n ]);\n await openSecureChannel(device, challenge);\n await params?.onScreenDisplayed?.();\n const challengeResponse = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n const kkPattern = await device.startKKPatternAsResponder({\n partitionId: challenge.partitionId,\n handshake: challenge.kkHandshake,\n handshakeAttestation: challenge.kkHandshakeAttestation,\n });\n const approverBlob = await device.generateSeedFragment();\n await client.onboarding.submitSeedFragment.mutate({\n onboardingId: __onboardingId,\n pubKey,\n seedFragment: {\n challengeResponse,\n approverBlob,\n handshake: kkPattern.handshake,\n handshakeAttestation: {\n ...attestation,\n signature: kkPattern.signature,\n },\n },\n });\n },\n } satisfies DecorateWithDeviceAndOnboarding;\n });\n }\n\n // DecorateWithDeviceAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && !engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithDeviceAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { device, client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n opts?: {\n validityDurationSecs?: number;\n onScreenDisplayed?: () => void | Promise<void>;\n correlationId?: string;\n },\n ): Promise<Engine<T & WithPsdAuth>> {\n const { pubKey } = await device.getU2FPubKey();\n const challenge = await client.auth.psd.generateChallenge.mutate(\n {\n pubKey,\n workspaceName: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n await opts?.onScreenDisplayed?.();\n const authentication = await device.authenticate({\n challenge,\n workspaceName: __workspaceName,\n });\n const authPayload = {\n workspaceName: __workspaceName,\n pubKey,\n authentication,\n challengeId: challenge.challengeId,\n validityDurationSecs: opts?.validityDurationSecs,\n };\n const { token } = await client.auth.psd.authenticate.mutate(\n { ...authPayload },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withPsdAuth: WithPsdAuth = {\n __psdToken: token,\n };\n const psdAuth = `${engine.__workspaceName}:${token}`;\n const __authClient = engine.createClient({ psdAuth });\n return decorateEngine({ ...this, client: __authClient, ...withPsdAuth } as Engine<\n T & WithPsdAuth\n >);\n },\n\n register: (\n registration: UserRegistrationResponse,\n params?: OnboardingOperationParams,\n ): Promise<UserRegistrationResponse> => {\n return genericRegister({\n device,\n name: registration.name,\n role: registration.role,\n getChallenge: async ({ deviceData }) => {\n const challenge = await client.userRegistrations.generateChallenge.mutate({\n id: registration.id,\n workspaceName: __workspaceName,\n deviceData,\n });\n return challenge;\n },\n submitChallenge: ({ challengeResponse }) =>\n client.userRegistrations.submitChallenge.mutate({\n workspaceName: __workspaceName,\n id: registration.id,\n challengeResponse,\n }),\n onScreenDisplayed: params?.onScreenDisplayed,\n });\n },\n } satisfies DecorateWithDeviceAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithApiUserAndWorkspaceUnauthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {\n decorate<WithWorkspace & WithApiUser, DecorateWithApiUserAndWorkspaceUnauthenticated<T>>(\n (engine) => {\n const { client, __workspaceName } = engine;\n return {\n login: async function <T>(\n this: Engine<T>,\n credentials: {\n apiKeyId: string;\n apiKeySecret: string;\n },\n opts?: { correlationId?: string },\n ): Promise<Engine<T & WithApiAuth>> {\n const res = await client.auth.authenticate.mutate(\n {\n apiKeyId: credentials.apiKeyId,\n apiKeySecret: credentials.apiKeySecret,\n workspace: __workspaceName,\n },\n buildTrpcContext({ correlationId: opts?.correlationId }),\n );\n const withApiAuth: WithApiAuth = {\n __apiAuth: res,\n };\n const __authClient = engine.createClient({ apiAccessToken: res.accessToken });\n return decorateEngine({ ...this, client: __authClient, ...withApiAuth } as Engine<\n T & WithApiAuth\n >);\n },\n } satisfies DecorateWithApiUserAndWorkspaceUnauthenticated<T>;\n },\n );\n }\n\n // DecorateWithWorkspacePsdAuthenticated\n // -------------------------------------------------------------------------\n if (engine.device && engine.__workspaceName && engine.__psdToken) {\n decorate<WithDevice & WithWorkspace, DecorateWithWorkspacePsdAuthenticated>((engine) => {\n const { client, device } = engine;\n\n // Drive the device's pairing record + PSK to a fully-provisioned state. Same tri-state\n // switch as the onboarding decorator; routes through `client.debug.*` instead of\n // `client.onboarding.*` and pulls workspace context implicitly from `__psdToken`.\n async function enforcePairing(): Promise<void> {\n const status = await device.hasPairing();\n if (status === \"OK\") return;\n\n const refreshCurrentPsk = async (): Promise<void> => {\n await refreshPsk({\n device,\n getRefreshPskData: (data) => client.debug.refreshPsk.mutate(data),\n });\n };\n\n if (status === \"NO_PAIRING\") {\n await pairDevice({\n device,\n getPairing: (confidentialityKey) =>\n client.debug.pairDevicePartition.mutate({\n confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,\n confidentialityKeySignature: confidentialityKey.confidentialityKeySignature,\n }),\n });\n }\n\n await refreshCurrentPsk();\n }\n\n const approveChallenge = async (\n challenge: PsdChallenge,\n params?: ApproveRequestParams,\n ): Promise<string> => {\n await enforcePairing();\n try {\n await openSecureChannel(device, challenge);\n } catch (err) {\n if (!isPskMissingError(err)) throw err;\n // Defense-in-depth: a session opened before the PSK was wiped still hits\n // SW_PSK_MISSING here. Re-run enforcePairing() — it now sees PSK_MISSING and drives\n // the refresh sub-chain — then retry the secure-channel APDU once.\n await enforcePairing();\n await openSecureChannel(device, challenge);\n }\n await params?.onScreenDisplayed?.();\n const signature = await device.validateVaultOperation({\n actions: challenge.wActions,\n });\n return signature;\n };\n\n return {\n approve: async (\n request: VaultRequestResponse,\n params?: ApproveRequestParams,\n ): Promise<VaultRequestResponse> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n if (challenge.challengeType === \"PSD\") {\n const signature = await approveChallenge(challenge, params);\n await params?.onPsdChallengeSigned?.();\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"PSD\", signature },\n },\n buildTrpcContext(params),\n );\n }\n if (challenge.challengeType === \"SOFT\") {\n return client.requests.approve.mutate(\n {\n id: request.id,\n data: { challengeType: \"SOFT\" },\n },\n buildTrpcContext(params),\n );\n }\n throw new Error(\"Challenge type must be either PSD or SOFT\");\n },\n\n approveChallenge,\n\n reject: (\n request: VaultRequestResponse,\n opts?: CorrelationIdOpts,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate(\n { id: request.id, data: null },\n buildTrpcContext(opts),\n );\n },\n } satisfies DecorateWithWorkspacePsdAuthenticated;\n });\n }\n\n // DecorateWithWorkspaceApiAuthenticated\n // -------------------------------------------------------------------------\n if (engine.__workspaceName && engine.__apiAuth) {\n decorate<WithWorkspace & WithApiAuth, DecorateWithWorkspaceApiAuthenticated>((engine) => {\n const { client } = engine;\n return {\n getChallenge: async (request: VaultRequestResponse): Promise<ApiChallenge[\"payload\"]> => {\n const { challenge } = await client.requests.getChallenge.query({ id: request.id });\n invariant(challenge.challengeType === \"API\", \"Challenge type must be API\");\n return challenge.payload;\n },\n\n approve: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.approve.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n\n reject: (\n request: VaultRequestResponse,\n signature: string,\n ): Promise<VaultRequestResponse> => {\n return client.requests.reject.mutate({\n id: request.id,\n data: { challengeType: \"API\", signature },\n });\n },\n } satisfies DecorateWithWorkspaceApiAuthenticated;\n });\n }\n\n return engine;\n }\n\n return {\n ...base,\n withDeviceIndex,\n withTransportId,\n withApiUser,\n withWorkspace,\n withOnboarding,\n };\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/revault-sdk",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.9",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"ts-pattern": "^5.9.0",
|
|
65
65
|
"uuid": "^14.0.0",
|
|
66
66
|
"zod": "^4.4.3",
|
|
67
|
-
"@ledgerhq/revault-api": "1.
|
|
67
|
+
"@ledgerhq/revault-api": "1.82.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@eslint/js": "^9.39.4",
|