@ledgerhq/revault-sdk 0.25.0 → 0.25.1

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.
Files changed (88) hide show
  1. package/lib/bake.cjs +1214 -1359
  2. package/lib/bake.cjs.map +1 -1
  3. package/lib/bake.d.cts +564 -562
  4. package/lib/bake.d.ts +564 -562
  5. package/lib/bake.js +1204 -1359
  6. package/lib/bake.js.map +1 -1
  7. package/lib/chunk-CKQMccvm.cjs +28 -0
  8. package/lib/crypto-BDBF_rfw.cjs +268 -0
  9. package/lib/crypto-BDBF_rfw.cjs.map +1 -0
  10. package/lib/crypto-CPCBrCSZ.js +245 -0
  11. package/lib/crypto-CPCBrCSZ.js.map +1 -0
  12. package/lib/crypto.cjs +5 -11
  13. package/lib/crypto.d.cts +10 -7
  14. package/lib/crypto.d.ts +10 -7
  15. package/lib/crypto.js +2 -11
  16. package/lib/device-0lcfYGHr.cjs +793 -0
  17. package/lib/device-0lcfYGHr.cjs.map +1 -0
  18. package/lib/device-B8Fww8_6.js +719 -0
  19. package/lib/device-B8Fww8_6.js.map +1 -0
  20. package/lib/device.cjs +6 -13
  21. package/lib/device.d.cts +2 -50
  22. package/lib/device.d.ts +2 -50
  23. package/lib/device.js +2 -13
  24. package/lib/engine.cjs +835 -886
  25. package/lib/engine.cjs.map +1 -1
  26. package/lib/engine.d.cts +3 -25
  27. package/lib/engine.d.ts +3 -25
  28. package/lib/engine.js +828 -885
  29. package/lib/engine.js.map +1 -1
  30. package/lib/index--fscLDTT.d.ts +237 -0
  31. package/lib/index-BE7oUpCb.d.cts +237 -0
  32. package/lib/index-C4Xjiv0k.d.cts +23 -0
  33. package/lib/index-CVjhPoZh.d.ts +23 -0
  34. package/lib/index.cjs +0 -1
  35. package/lib/index.d.cts +10 -5
  36. package/lib/index.d.ts +10 -5
  37. package/lib/index.js +1 -1
  38. package/lib/logger-Cme0iL1f.d.cts +10 -0
  39. package/lib/logger-DWLViq7U.d.ts +10 -0
  40. package/lib/onboarding.cjs +179 -181
  41. package/lib/onboarding.cjs.map +1 -1
  42. package/lib/onboarding.d.cts +1751 -1722
  43. package/lib/onboarding.d.ts +1751 -1722
  44. package/lib/onboarding.js +175 -181
  45. package/lib/onboarding.js.map +1 -1
  46. package/lib/trpc-CWGPr8Ox.d.ts +20 -0
  47. package/lib/trpc-C_dUOB1u.d.cts +20 -0
  48. package/lib/types-4CfR5--z.d.ts +203 -0
  49. package/lib/types-Byf9V35t.d.cts +203 -0
  50. package/lib/types-CQROu0nu.d.cts +6 -0
  51. package/lib/types-_QeBv1U4.d.ts +6 -0
  52. package/lib/types.cjs +0 -1
  53. package/lib/types.d.cts +3 -4
  54. package/lib/types.d.ts +3 -4
  55. package/lib/types.js +1 -1
  56. package/lib/utils-BGbdjOP9.js +61 -0
  57. package/lib/utils-BGbdjOP9.js.map +1 -0
  58. package/lib/utils-DbSFXp4c.cjs +86 -0
  59. package/lib/utils-DbSFXp4c.cjs.map +1 -0
  60. package/package.json +6 -6
  61. package/lib/chunk-2WGM7EWA.cjs +0 -282
  62. package/lib/chunk-2WGM7EWA.cjs.map +0 -1
  63. package/lib/chunk-AXI72NFY.js +0 -50
  64. package/lib/chunk-AXI72NFY.js.map +0 -1
  65. package/lib/chunk-DRMYBKL3.cjs +0 -820
  66. package/lib/chunk-DRMYBKL3.cjs.map +0 -1
  67. package/lib/chunk-KV5FO7N5.js +0 -282
  68. package/lib/chunk-KV5FO7N5.js.map +0 -1
  69. package/lib/chunk-LH4QQXUH.cjs +0 -50
  70. package/lib/chunk-LH4QQXUH.cjs.map +0 -1
  71. package/lib/chunk-PFZIW6UP.js +0 -820
  72. package/lib/chunk-PFZIW6UP.js.map +0 -1
  73. package/lib/crypto.cjs.map +0 -1
  74. package/lib/crypto.js.map +0 -1
  75. package/lib/device.cjs.map +0 -1
  76. package/lib/device.js.map +0 -1
  77. package/lib/index.cjs.map +0 -1
  78. package/lib/index.js.map +0 -1
  79. package/lib/logger-C-TPbnjv.d.cts +0 -9
  80. package/lib/logger-C-TPbnjv.d.ts +0 -9
  81. package/lib/types-C-ngtI5m.d.ts +0 -202
  82. package/lib/types-CpGEbAxh.d.cts +0 -19
  83. package/lib/types-CpGEbAxh.d.ts +0 -19
  84. package/lib/types-CryvY9pW.d.cts +0 -202
  85. package/lib/types-DJfbanPz.d.cts +0 -167
  86. package/lib/types-DJfbanPz.d.ts +0 -167
  87. package/lib/types.cjs.map +0 -1
  88. package/lib/types.js.map +0 -1
package/lib/engine.js CHANGED
@@ -1,899 +1,842 @@
1
- import {
2
- buildTrpcContext,
3
- fetchAll,
4
- fetchAllCursor
5
- } from "./chunk-AXI72NFY.js";
6
- import {
7
- APPID_VAULT_ADMINISTRATOR,
8
- DisconnectedDevice,
9
- LockedDeviceError,
10
- PAGINATED_STATUS,
11
- PATHS,
12
- SCRIPT_IDS,
13
- STATUS_LENGTH,
14
- STREAMING_NEXT_ACTION,
15
- STREAMING_RESPONSE,
16
- STR_ROLES,
17
- createApiDevice,
18
- isTransportStatusError,
19
- withDevicePolling
20
- } from "./chunk-PFZIW6UP.js";
21
-
22
- // src/engine/index.ts
23
- import invariant2 from "invariant";
24
-
25
- // src/device/real-device.ts
1
+ import { a as DisconnectedDevice, c as APPID_VAULT_ADMINISTRATOR, d as SCRIPT_IDS, f as STR_ROLES, i as withDevicePolling, l as PAGINATED_STATUS, n as isTransportStatusError, o as LockedDeviceError, s as createApiDevice, u as PATHS } from "./device-B8Fww8_6.js";
2
+ import { i as fetchAllCursor, r as fetchAll, t as buildTrpcContext } from "./utils-BGbdjOP9.js";
26
3
  import invariant from "invariant";
27
4
  import { from, lastValueFrom } from "rxjs";
28
- var MAX_CHUNK_LENGTH = 250;
29
- var getPathFromPathString = (pathString) => {
30
- const parts = pathString.split("'/").map((part) => Number.parseInt(part, 10));
31
- return parts.map((part) => (part | 2147483648) >>> 0);
5
+ import { createTRPCClient, httpLink } from "@trpc/client";
6
+ import superjson from "superjson";
7
+ //#region src/device/real-device.ts
8
+ const MAX_CHUNK_LENGTH = 250;
9
+ const getPathFromPathString = (pathString) => {
10
+ return pathString.split("'/").map((part) => Number.parseInt(part, 10)).map((part) => (part | 2147483648) >>> 0);
32
11
  };
33
- var splitChunks = (chunk, buffer) => {
34
- const chunks = [];
35
- for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) {
36
- chunks.push(buffer.slice(i, i + size));
37
- }
38
- return chunks;
12
+ const splitChunks = (chunk, buffer) => {
13
+ const chunks = [];
14
+ for (let i = 0, size = chunk; i < buffer.length; i += size, size = chunk) chunks.push(buffer.slice(i, i + size));
15
+ return chunks;
39
16
  };
40
- var removeStatus = (result) => result.slice(0, result.length - STATUS_LENGTH);
41
- var sendByChunk = async (transport, command, data, chunkSize = MAX_CHUNK_LENGTH) => {
42
- const chunks = splitChunks(chunkSize, data);
43
- let response = Buffer.from([]);
44
- for (let i = 0; i < chunks.length; i++) {
45
- const chunk = chunks[i];
46
- const apdu = [...command];
47
- apdu[2] = i && 128;
48
- response = await transport.send(apdu[0], apdu[1], apdu[2], apdu[3], chunk, [
49
- 36864,
50
- ...PAGINATED_STATUS
51
- ]);
52
- }
53
- return response;
17
+ const removeStatus = (result) => result.slice(0, result.length - 2);
18
+ const sendByChunk = async (transport, command, data, chunkSize = MAX_CHUNK_LENGTH) => {
19
+ const chunks = splitChunks(chunkSize, data);
20
+ let response = Buffer.from([]);
21
+ for (let i = 0; i < chunks.length; i++) {
22
+ const chunk = chunks[i];
23
+ const apdu = [...command];
24
+ /* v8 ignore next -- @preserve */
25
+ apdu[2] = i && 128;
26
+ response = await transport.send(apdu[0], apdu[1], apdu[2], apdu[3], chunk, [36864, ...PAGINATED_STATUS]);
27
+ }
28
+ return response;
54
29
  };
55
- var buildAttestation = (params) => {
56
- const sigBuffer = Buffer.from(params.handshakeAttestation.signature, "base64");
57
- const sigLengthBuffer = Buffer.alloc(1);
58
- sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);
59
- const certBuffer = Buffer.from(params.handshakeAttestation.certificate, "base64");
60
- const certLengthBuffer = Buffer.alloc(1);
61
- certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);
62
- const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, "base64");
63
- const certChainData = Buffer.concat([
64
- sigLengthBuffer,
65
- sigBuffer,
66
- pubBuffer,
67
- certLengthBuffer,
68
- certBuffer
69
- ]);
70
- const cliMsgBuffer = Buffer.from(params.handshake, "hex");
71
- const cliMsgLengthBuffer = Buffer.alloc(1);
72
- cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);
73
- const pidBuffer = Buffer.from(params.partitionId, "hex");
74
- const pidLengthBuffer = Buffer.alloc(1);
75
- pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);
76
- const certChainDataLengthBuff = Buffer.alloc(2);
77
- certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);
78
- const data = Buffer.concat([
79
- cliMsgLengthBuffer,
80
- cliMsgBuffer,
81
- certChainDataLengthBuff,
82
- certChainData,
83
- pidLengthBuffer,
84
- pidBuffer
85
- ]);
86
- const totalLengthBuffer = Buffer.alloc(2);
87
- totalLengthBuffer.writeUInt16BE(data.length, 0);
88
- const toSend = Buffer.concat([totalLengthBuffer, data]);
89
- return toSend;
30
+ const buildAttestation = (params) => {
31
+ const sigBuffer = Buffer.from(params.handshakeAttestation.signature, "base64");
32
+ const sigLengthBuffer = Buffer.alloc(1);
33
+ sigLengthBuffer.writeUIntBE(sigBuffer.length, 0, 1);
34
+ const certBuffer = Buffer.from(params.handshakeAttestation.certificate, "base64");
35
+ const certLengthBuffer = Buffer.alloc(1);
36
+ certLengthBuffer.writeUIntBE(certBuffer.length, 0, 1);
37
+ const pubBuffer = Buffer.from(params.handshakeAttestation.attestationPub, "base64");
38
+ const certChainData = Buffer.concat([
39
+ sigLengthBuffer,
40
+ sigBuffer,
41
+ pubBuffer,
42
+ certLengthBuffer,
43
+ certBuffer
44
+ ]);
45
+ const cliMsgBuffer = Buffer.from(params.handshake, "hex");
46
+ const cliMsgLengthBuffer = Buffer.alloc(1);
47
+ cliMsgLengthBuffer.writeUIntBE(cliMsgBuffer.length, 0, 1);
48
+ const pidBuffer = Buffer.from(params.partitionId, "hex");
49
+ const pidLengthBuffer = Buffer.alloc(1);
50
+ pidLengthBuffer.writeUIntBE(pidBuffer.length, 0, 1);
51
+ const certChainDataLengthBuff = Buffer.alloc(2);
52
+ certChainDataLengthBuff.writeUInt16BE(certChainData.length, 0);
53
+ const data = Buffer.concat([
54
+ cliMsgLengthBuffer,
55
+ cliMsgBuffer,
56
+ certChainDataLengthBuff,
57
+ certChainData,
58
+ pidLengthBuffer,
59
+ pidBuffer
60
+ ]);
61
+ const totalLengthBuffer = Buffer.alloc(2);
62
+ totalLengthBuffer.writeUInt16BE(data.length, 0);
63
+ return Buffer.concat([totalLengthBuffer, data]);
90
64
  };
91
- var genericRetryOnError = (err) => {
92
- if (err instanceof LockedDeviceError) return true;
93
- if (isTransportStatusError(err) && err.statusCode === 27913) return true;
94
- if (err instanceof DisconnectedDevice) return true;
95
- return false;
65
+ /* v8 ignore next -- @preserve */
66
+ const genericRetryOnError = (err) => {
67
+ if (err instanceof LockedDeviceError) return true;
68
+ if (isTransportStatusError(err) && err.statusCode === 27913) return true;
69
+ if (err instanceof DisconnectedDevice) return true;
70
+ return false;
96
71
  };
97
72
  function createRealDevice(options, logger) {
98
- const { transportId } = options;
99
- async function run(job, retryOnError = genericRetryOnError) {
100
- return lastValueFrom(
101
- withDevicePolling(transportId)((transport) => from(job(transport)), retryOnError)
102
- );
103
- }
104
- const noRetry = () => false;
105
- const alwaysRetry = () => true;
106
- const poll = async (opts = {}) => {
107
- await run(
108
- // eslint-disable-next-line @typescript-eslint/no-empty-function
109
- async (_transport) => {
110
- },
111
- opts.retryOnError ?? alwaysRetry
112
- );
113
- try {
114
- await getPublicKey(PATHS.U2F, { secp256k1: true, retryOnError: noRetry });
115
- return { isAppOpened: true };
116
- } catch (err) {
117
- if (isTransportStatusError(err) && genericRetryOnError(err)) {
118
- return { isAppOpened: false };
119
- }
120
- throw err;
121
- }
122
- };
123
- const pollApp = async (appName) => {
124
- const res = await run(
125
- (transport) => transport.send(224, 216, 0, 0, Buffer.from(appName, "utf8"))
126
- );
127
- await new Promise((r) => setTimeout(r, 1e3));
128
- return res.toString("hex");
129
- };
130
- const getPublicKey = async (pathString, { secp256k1, retryOnError }) => {
131
- logger.info(`[device] getPublicKey (${pathString})`);
132
- const path = getPathFromPathString(pathString);
133
- const data = Buffer.concat([
134
- Buffer.from([path.length]),
135
- ...path.map((derivation) => {
136
- const buf = Buffer.alloc(4);
137
- buf.writeUInt32BE(derivation, 0);
138
- return buf;
139
- })
140
- ]);
141
- const curve = secp256k1 ? 1 : 2;
142
- const response = await run(
143
- (transport) => transport.send(224, 64, curve, 0, data),
144
- retryOnError ?? genericRetryOnError
145
- );
146
- const pubKeyLength = response.readInt8(0);
147
- const pubKey = response.slice(1, pubKeyLength + 1).toString("hex").toUpperCase();
148
- const signature = response.slice(pubKeyLength + 1, response.length - STATUS_LENGTH).toString("base64");
149
- return { pubKey, signature };
150
- };
151
- const device = {
152
- authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {
153
- logger.info(`[device] Authenticate`);
154
- invariant(role !== "READ_ONLY_API_KEY", "Invalid role for authenticate: READ_ONLY_API_KEY");
155
- const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, "hex");
156
- const nameBuffer = Buffer.from(name);
157
- const workspaceBuffer = Buffer.from(workspaceName);
158
- const keyHandleData = Buffer.concat([
159
- Buffer.from(STR_ROLES[role], "hex"),
160
- Buffer.from([nameBuffer.length]),
161
- nameBuffer,
162
- Buffer.from([workspaceBuffer.length]),
163
- workspaceBuffer
164
- ]);
165
- const keyHandleDataLength = Buffer.alloc(2);
166
- keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);
167
- const data = Buffer.concat([
168
- Buffer.from(challenge, "base64"),
169
- applicationBuffer,
170
- Buffer.from([keyHandle.length]),
171
- Buffer.from(keyHandle, "hex"),
172
- keyHandleDataLength,
173
- keyHandleData
174
- ]);
175
- const authentication = await run(
176
- (transport) => sendByChunk(transport, [224, 2, 0, 0], data)
177
- );
178
- return removeStatus(authentication).toString("hex");
179
- },
180
- finalizePairingHandshake: async (params) => {
181
- const bufWithStatus = await run(
182
- (transport) => sendByChunk(transport, [224, 71, 0, 2], buildAttestation(params))
183
- );
184
- return removeStatus(bufWithStatus).toString("hex");
185
- },
186
- generateSeedFragment: async () => {
187
- logger.info(`[device] generateSeedFragment`);
188
- const path = getPathFromPathString(PATHS.KEY_MATERIAL);
189
- const data = Buffer.concat([
190
- Buffer.from([path.length]),
191
- ...path.map((derivation) => {
192
- const buf = Buffer.alloc(4);
193
- buf.writeUInt32BE(derivation, 0);
194
- return buf;
195
- })
196
- ]);
197
- const response = await run((transport) => transport.send(224, 68, 0, 0, data));
198
- return removeStatus(response).toString("base64");
199
- },
200
- generateWrappingKeyFragment: async () => {
201
- logger.info(`[device] generateWrappingKeyFragment`);
202
- const path = getPathFromPathString(PATHS.KEY_MATERIAL);
203
- const data = Buffer.concat([
204
- Buffer.from([path.length]),
205
- ...path.map((derivation) => {
206
- const buf = Buffer.alloc(4);
207
- buf.writeUInt32BE(derivation, 0);
208
- return buf;
209
- })
210
- ]);
211
- const response = await run((transport) => transport.send(224, 68, 1, 0, data));
212
- return removeStatus(response).toString("base64");
213
- },
214
- getAttestation: async () => {
215
- const bufWithStatus = await run((transport) => transport.send(224, 65, 0, 0));
216
- const buffer = removeStatus(bufWithStatus);
217
- const certLen = buffer.readInt8(32 + 65 + 1);
218
- return {
219
- attestation: {
220
- codeHash: buffer.slice(0, 32).toString("base64"),
221
- attestationPub: buffer.slice(32, 32 + 65).toString("base64"),
222
- certificate: buffer.slice(32 + 65, 32 + 65 + 2 + certLen).toString("base64")
223
- },
224
- buffer
225
- };
226
- },
227
- getConfidentialityKey: async () => {
228
- logger.info(`[device] getConfidentialityKey`);
229
- const bufWithStatus = await run((transport) => transport.send(224, 77, 0, 0));
230
- const buf = removeStatus(bufWithStatus);
231
- const keyLength = buf[0];
232
- const key = buf.slice(1, 1 + keyLength);
233
- const sig = buf.slice(1 + keyLength + 1);
234
- return {
235
- confidentialityKeyCurve25519: key.toString("hex"),
236
- confidentialityKeySignature: sig.toString("hex")
237
- };
238
- },
239
- getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),
240
- getDeviceUserId: async () => {
241
- logger.info(`[device] getDeviceUserId`);
242
- const response = await run((transport) => transport.send(224, 82, 0, 0));
243
- return removeStatus(response).toString("hex").toUpperCase();
244
- },
245
- getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),
246
- getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),
247
- hasPairing: async () => {
248
- logger.info(`[device] hasPairing`);
249
- const apdu = [224, 81, 0, 0, 181];
250
- const res = await run((transport) => transport.exchange(Buffer.from(apdu)));
251
- const hex = Buffer.from(res).toString("hex");
252
- return hex !== "6f45" && hex !== "6a87";
253
- },
254
- initPairingHandshake: async () => {
255
- const res = await run((transport) => transport.send(224, 70, 0, 0));
256
- const pubKeyLength = res.readInt8(0);
257
- const pubKey = res.slice(1, pubKeyLength + 1).toString("hex").toUpperCase();
258
- const signature = res.slice(pubKeyLength + 1, res.length - STATUS_LENGTH).toString("base64");
259
- return { pubKey, signature };
260
- },
261
- openSession: async (params) => {
262
- logger.info(`[device] openSession`);
263
- const { secureChannel } = params;
264
- const path = getPathFromPathString(PATHS.CONFIDENTIALITY);
265
- const dataDerivation = Buffer.concat([
266
- Buffer.from([path.length]),
267
- ...path.map((derivation) => {
268
- const buf = Buffer.alloc(4);
269
- buf.writeUInt32BE(derivation, 0);
270
- return buf;
271
- })
272
- ]);
273
- const pubKey = Buffer.from(secureChannel.pubKey, "hex");
274
- const sigBuffer = Buffer.from(secureChannel.certificate.signature, "base64");
275
- const attestationPubBuffer = Buffer.from(secureChannel.certificate.attestationPub, "base64");
276
- const certBuffer = Buffer.from(secureChannel.certificate.certificate, "base64");
277
- const attestation = Buffer.concat([
278
- Buffer.from([sigBuffer.length]),
279
- sigBuffer,
280
- attestationPubBuffer,
281
- Buffer.from([certBuffer.length]),
282
- certBuffer
283
- ]);
284
- const lengthAttestation = Buffer.alloc(2);
285
- lengthAttestation.writeUInt16BE(attestation.length, 0);
286
- const data = Buffer.concat([dataDerivation, pubKey, lengthAttestation, attestation]);
287
- await run(
288
- (transport) => sendByChunk(transport, [224, 66, 0, SCRIPT_IDS.INIT_SESSION], data)
289
- );
290
- },
291
- register: async (params) => {
292
- const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;
293
- const challenge = Buffer.from(strChallenge, "hex");
294
- invariant(challenge.length === 32, "challenge hex is expected to have 32 bytes");
295
- const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, "hex");
296
- invariant(applicationBuf.length === 32, "application hex is expected to have 32 bytes");
297
- const userNameBuff = Buffer.from(name);
298
- const keyHandleData = Buffer.concat([
299
- Buffer.from(STR_ROLES[role], "hex"),
300
- Buffer.from([userNameBuff.length]),
301
- userNameBuff
302
- ]);
303
- const keyHandleDataLength = Buffer.alloc(2);
304
- keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);
305
- const data = Buffer.concat([challenge, applicationBuf, keyHandleDataLength, keyHandleData]);
306
- const response = await run(
307
- (transport) => sendByChunk(transport, [224, 1, 0, 0], data)
308
- );
309
- let i = 0;
310
- const rfu = response.slice(i, i + 1)[0];
311
- i += 1;
312
- const pubKey = response.slice(i, i + 65).toString("hex");
313
- i += 65;
314
- const keyHandleLength = response.slice(i, i + 1)[0];
315
- i++;
316
- const keyHandle = response.slice(i, i + keyHandleLength);
317
- i += keyHandleLength;
318
- return {
319
- u2fRegister: removeStatus(response),
320
- keyHandle,
321
- rfu,
322
- pubKey
323
- };
324
- },
325
- registerData: async (params) => {
326
- const { challenge: strChallenge } = params;
327
- const challenge = Buffer.from(strChallenge, "hex");
328
- invariant(challenge.length === 32, "challenge hex is expected to have 32 bytes");
329
- const response = await run((transport) => transport.send(224, 3, 0, 0, challenge));
330
- return removeStatus(response).toString("hex");
331
- },
332
- setPairing: async ({ pairing }) => {
333
- logger.info(`[device] setPairing`);
334
- const psdPayload = Buffer.from(pairing.blob, "base64");
335
- const length = Buffer.alloc(2);
336
- length.writeUInt16BE(psdPayload.length, 0);
337
- const final = Buffer.concat([length, psdPayload]);
338
- await run((transport) => sendByChunk(transport, [224, 78, 0, 0], final));
339
- },
340
- startKKPatternAsResponder: async (params) => {
341
- logger.info(`[device] startKKPatternAsResponder`);
342
- const data = buildAttestation(params);
343
- const bufWithStatus = await run(
344
- (transport) => sendByChunk(transport, [224, 76, 0, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data)
345
- );
346
- const buffer = removeStatus(bufWithStatus);
347
- const dataLength = buffer.readInt8(0);
348
- return {
349
- handshake: buffer.slice(1, dataLength + 1).toString("base64"),
350
- signature: buffer.slice(dataLength + 1).toString("base64")
351
- };
352
- },
353
- startKPatternAsResponder: async (params) => {
354
- logger.info(`[device] startKPatternAsResponder`);
355
- const data = buildAttestation(params);
356
- await run(
357
- (transport) => sendByChunk(transport, [224, 73, 0, SCRIPT_IDS.ACCOUNT_MANAGER_SESSION], data)
358
- );
359
- },
360
- validateVaultOperation: async (params) => {
361
- logger.info(`[device] validateVaultOperation`);
362
- const path = getPathFromPathString(PATHS.VALIDATION);
363
- const paths = Buffer.concat([
364
- Buffer.from([path.length]),
365
- ...path.map((derivation) => {
366
- const buf = Buffer.alloc(4);
367
- buf.writeUInt32BE(derivation, 0);
368
- return buf;
369
- })
370
- ]);
371
- let nextActionId = 1;
372
- let finalResponse = null;
373
- while (!finalResponse) {
374
- const screen = Buffer.from(params.actions[nextActionId - 1], "base64");
375
- const length = Buffer.alloc(2);
376
- length.writeUInt16BE(screen.length, 0);
377
- const data = Buffer.concat([paths, length, screen]);
378
- const response = await run(
379
- (transport) => sendByChunk(transport, [224, 69, 0, 0], data)
380
- );
381
- const responseType = response.readInt8(0);
382
- let responseStatus = response.readUInt16BE(response.length - 2);
383
- switch (responseType) {
384
- case STREAMING_NEXT_ACTION:
385
- nextActionId = response.readUIntBE(1, 2);
386
- break;
387
- case STREAMING_RESPONSE:
388
- finalResponse = response.slice(3, response.length - 2);
389
- while (responseStatus !== 36864) {
390
- {
391
- const resp = await run((transport) => transport.send(0, 192, 0, 0));
392
- responseStatus = resp.readUInt16BE(resp.length - 2);
393
- finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);
394
- }
395
- }
396
- break;
397
- /* v8 ignore next -- @preserve */
398
- default:
399
- throw new Error(`Invalid response type: ${responseType}`);
400
- }
401
- }
402
- return finalResponse.toString("base64");
403
- },
404
- sendAPDU: async (apduCommand) => {
405
- const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, "hex")));
406
- return Buffer.from(res).toString("hex");
407
- },
408
- getVersion: async () => {
409
- const res = await run((transport) => transport.send(176, 1, 0, 0));
410
- const appNameLen = res.readInt8(1);
411
- const appVersionLen = res.readInt8(2 + appNameLen);
412
- const appVersionHex = res.slice(2 + 1 + appNameLen, 2 + appNameLen + appVersionLen + 1);
413
- const appVersion = Buffer.from(appVersionHex).toString();
414
- return appVersion;
415
- },
416
- poll,
417
- pollApp
418
- };
419
- return device;
73
+ const { transportId } = options;
74
+ async function run(job, retryOnError = genericRetryOnError) {
75
+ return lastValueFrom(withDevicePolling(transportId)((transport) => from(job(transport)), retryOnError));
76
+ }
77
+ /* v8 ignore next -- @preserve */
78
+ const noRetry = () => false;
79
+ /* v8 ignore next -- @preserve */
80
+ const alwaysRetry = () => true;
81
+ const poll = async (opts = {}) => {
82
+ await run(async (_transport) => {}, opts.retryOnError ?? alwaysRetry);
83
+ try {
84
+ await getPublicKey(PATHS.U2F, {
85
+ secp256k1: true,
86
+ retryOnError: noRetry
87
+ });
88
+ return { isAppOpened: true };
89
+ } catch (err) {
90
+ if (isTransportStatusError(err) && genericRetryOnError(err)) return { isAppOpened: false };
91
+ throw err;
92
+ }
93
+ };
94
+ const pollApp = async (appName) => {
95
+ const res = await run((transport) => transport.send(224, 216, 0, 0, Buffer.from(appName, "utf8")));
96
+ await new Promise((r) => setTimeout(r, 1e3));
97
+ return res.toString("hex");
98
+ };
99
+ const getPublicKey = async (pathString, { secp256k1, retryOnError }) => {
100
+ logger.info(`[device] getPublicKey (${pathString})`);
101
+ const path = getPathFromPathString(pathString);
102
+ const data = Buffer.concat([Buffer.from([path.length]), ...path.map((derivation) => {
103
+ const buf = Buffer.alloc(4);
104
+ buf.writeUInt32BE(derivation, 0);
105
+ return buf;
106
+ })]);
107
+ const curve = secp256k1 ? 1 : 2;
108
+ const response = await run((transport) => transport.send(224, 64, curve, 0, data), retryOnError ?? genericRetryOnError);
109
+ const pubKeyLength = response.readInt8(0);
110
+ return {
111
+ pubKey: response.slice(1, pubKeyLength + 1).toString("hex").toUpperCase(),
112
+ signature: response.slice(pubKeyLength + 1, response.length - 2).toString("base64")
113
+ };
114
+ };
115
+ return {
116
+ authenticate: async ({ challenge: { challenge, name, role, keyHandle }, workspaceName }) => {
117
+ logger.info(`[device] Authenticate`);
118
+ invariant(role !== "READ_ONLY_API_KEY", "Invalid role for authenticate: READ_ONLY_API_KEY");
119
+ const applicationBuffer = Buffer.from(APPID_VAULT_ADMINISTRATOR, "hex");
120
+ const nameBuffer = Buffer.from(name);
121
+ const workspaceBuffer = Buffer.from(workspaceName);
122
+ const keyHandleData = Buffer.concat([
123
+ Buffer.from(STR_ROLES[role], "hex"),
124
+ Buffer.from([nameBuffer.length]),
125
+ nameBuffer,
126
+ Buffer.from([workspaceBuffer.length]),
127
+ workspaceBuffer
128
+ ]);
129
+ const keyHandleDataLength = Buffer.alloc(2);
130
+ keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);
131
+ const data = Buffer.concat([
132
+ Buffer.from(challenge, "base64"),
133
+ applicationBuffer,
134
+ Buffer.from([keyHandle.length]),
135
+ Buffer.from(keyHandle, "hex"),
136
+ keyHandleDataLength,
137
+ keyHandleData
138
+ ]);
139
+ return removeStatus(await run((transport) => sendByChunk(transport, [
140
+ 224,
141
+ 2,
142
+ 0,
143
+ 0
144
+ ], data))).toString("hex");
145
+ },
146
+ finalizePairingHandshake: async (params) => {
147
+ return removeStatus(await run((transport) => sendByChunk(transport, [
148
+ 224,
149
+ 71,
150
+ 0,
151
+ 2
152
+ ], buildAttestation(params)))).toString("hex");
153
+ },
154
+ generateSeedFragment: async () => {
155
+ logger.info(`[device] generateSeedFragment`);
156
+ const path = getPathFromPathString(PATHS.KEY_MATERIAL);
157
+ const data = Buffer.concat([Buffer.from([path.length]), ...path.map((derivation) => {
158
+ const buf = Buffer.alloc(4);
159
+ buf.writeUInt32BE(derivation, 0);
160
+ return buf;
161
+ })]);
162
+ return removeStatus(await run((transport) => transport.send(224, 68, 0, 0, data))).toString("base64");
163
+ },
164
+ generateWrappingKeyFragment: async () => {
165
+ logger.info(`[device] generateWrappingKeyFragment`);
166
+ const path = getPathFromPathString(PATHS.KEY_MATERIAL);
167
+ const data = Buffer.concat([Buffer.from([path.length]), ...path.map((derivation) => {
168
+ const buf = Buffer.alloc(4);
169
+ buf.writeUInt32BE(derivation, 0);
170
+ return buf;
171
+ })]);
172
+ return removeStatus(await run((transport) => transport.send(224, 68, 1, 0, data))).toString("base64");
173
+ },
174
+ getAttestation: async () => {
175
+ const buffer = removeStatus(await run((transport) => transport.send(224, 65, 0, 0)));
176
+ const certLen = buffer.readInt8(98);
177
+ return {
178
+ attestation: {
179
+ codeHash: buffer.slice(0, 32).toString("base64"),
180
+ attestationPub: buffer.slice(32, 97).toString("base64"),
181
+ certificate: buffer.slice(97, 99 + certLen).toString("base64")
182
+ },
183
+ buffer
184
+ };
185
+ },
186
+ getConfidentialityKey: async () => {
187
+ logger.info(`[device] getConfidentialityKey`);
188
+ const buf = removeStatus(await run((transport) => transport.send(224, 77, 0, 0)));
189
+ const keyLength = buf[0];
190
+ const key = buf.slice(1, 1 + keyLength);
191
+ const sig = buf.slice(1 + keyLength + 1);
192
+ return {
193
+ confidentialityKeyCurve25519: key.toString("hex"),
194
+ confidentialityKeySignature: sig.toString("hex")
195
+ };
196
+ },
197
+ getConfidentialityPubKey: () => getPublicKey(PATHS.CONFIDENTIALITY, { secp256k1: true }),
198
+ getDeviceUserId: async () => {
199
+ logger.info(`[device] getDeviceUserId`);
200
+ return removeStatus(await run((transport) => transport.send(224, 82, 0, 0))).toString("hex").toUpperCase();
201
+ },
202
+ getU2FPubKey: () => getPublicKey(PATHS.U2F, { secp256k1: false }),
203
+ getValidationPubKey: () => getPublicKey(PATHS.VALIDATION, { secp256k1: true }),
204
+ hasPairing: async () => {
205
+ logger.info(`[device] hasPairing`);
206
+ const apdu = [
207
+ 224,
208
+ 81,
209
+ 0,
210
+ 0,
211
+ 181
212
+ ];
213
+ const res = await run((transport) => transport.exchange(Buffer.from(apdu)));
214
+ const hex = Buffer.from(res).toString("hex");
215
+ return hex !== "6f45" && hex !== "6a87";
216
+ },
217
+ initPairingHandshake: async () => {
218
+ const res = await run((transport) => transport.send(224, 70, 0, 0));
219
+ const pubKeyLength = res.readInt8(0);
220
+ return {
221
+ pubKey: res.slice(1, pubKeyLength + 1).toString("hex").toUpperCase(),
222
+ signature: res.slice(pubKeyLength + 1, res.length - 2).toString("base64")
223
+ };
224
+ },
225
+ openSession: async (params) => {
226
+ logger.info(`[device] openSession`);
227
+ const { secureChannel } = params;
228
+ const path = getPathFromPathString(PATHS.CONFIDENTIALITY);
229
+ const dataDerivation = Buffer.concat([Buffer.from([path.length]), ...path.map((derivation) => {
230
+ const buf = Buffer.alloc(4);
231
+ buf.writeUInt32BE(derivation, 0);
232
+ return buf;
233
+ })]);
234
+ const pubKey = Buffer.from(secureChannel.pubKey, "hex");
235
+ const sigBuffer = Buffer.from(secureChannel.certificate.signature, "base64");
236
+ const attestationPubBuffer = Buffer.from(secureChannel.certificate.attestationPub, "base64");
237
+ const certBuffer = Buffer.from(secureChannel.certificate.certificate, "base64");
238
+ const attestation = Buffer.concat([
239
+ Buffer.from([sigBuffer.length]),
240
+ sigBuffer,
241
+ attestationPubBuffer,
242
+ Buffer.from([certBuffer.length]),
243
+ certBuffer
244
+ ]);
245
+ const lengthAttestation = Buffer.alloc(2);
246
+ lengthAttestation.writeUInt16BE(attestation.length, 0);
247
+ const data = Buffer.concat([
248
+ dataDerivation,
249
+ pubKey,
250
+ lengthAttestation,
251
+ attestation
252
+ ]);
253
+ await run((transport) => sendByChunk(transport, [
254
+ 224,
255
+ 66,
256
+ 0,
257
+ SCRIPT_IDS.INIT_SESSION
258
+ ], data));
259
+ },
260
+ register: async (params) => {
261
+ const { challenge: strChallenge, u2fRegisterData: _, name, role } = params;
262
+ const challenge = Buffer.from(strChallenge, "hex");
263
+ invariant(challenge.length === 32, "challenge hex is expected to have 32 bytes");
264
+ const applicationBuf = Buffer.from(APPID_VAULT_ADMINISTRATOR, "hex");
265
+ invariant(applicationBuf.length === 32, "application hex is expected to have 32 bytes");
266
+ const userNameBuff = Buffer.from(name);
267
+ const keyHandleData = Buffer.concat([
268
+ Buffer.from(STR_ROLES[role], "hex"),
269
+ Buffer.from([userNameBuff.length]),
270
+ userNameBuff
271
+ ]);
272
+ const keyHandleDataLength = Buffer.alloc(2);
273
+ keyHandleDataLength.writeUInt16BE(keyHandleData.length, 0);
274
+ const data = Buffer.concat([
275
+ challenge,
276
+ applicationBuf,
277
+ keyHandleDataLength,
278
+ keyHandleData
279
+ ]);
280
+ const response = await run((transport) => sendByChunk(transport, [
281
+ 224,
282
+ 1,
283
+ 0,
284
+ 0
285
+ ], data));
286
+ let i = 0;
287
+ const rfu = response.slice(i, i + 1)[0];
288
+ i += 1;
289
+ const pubKey = response.slice(i, i + 65).toString("hex");
290
+ i += 65;
291
+ const keyHandleLength = response.slice(i, i + 1)[0];
292
+ i++;
293
+ const keyHandle = response.slice(i, i + keyHandleLength);
294
+ i += keyHandleLength;
295
+ return {
296
+ u2fRegister: removeStatus(response),
297
+ keyHandle,
298
+ rfu,
299
+ pubKey
300
+ };
301
+ },
302
+ registerData: async (params) => {
303
+ const { challenge: strChallenge } = params;
304
+ const challenge = Buffer.from(strChallenge, "hex");
305
+ invariant(challenge.length === 32, "challenge hex is expected to have 32 bytes");
306
+ return removeStatus(await run((transport) => transport.send(224, 3, 0, 0, challenge))).toString("hex");
307
+ },
308
+ setPairing: async ({ pairing }) => {
309
+ logger.info(`[device] setPairing`);
310
+ const psdPayload = Buffer.from(pairing.blob, "base64");
311
+ const length = Buffer.alloc(2);
312
+ length.writeUInt16BE(psdPayload.length, 0);
313
+ const final = Buffer.concat([length, psdPayload]);
314
+ await run((transport) => sendByChunk(transport, [
315
+ 224,
316
+ 78,
317
+ 0,
318
+ 0
319
+ ], final));
320
+ },
321
+ startKKPatternAsResponder: async (params) => {
322
+ logger.info(`[device] startKKPatternAsResponder`);
323
+ const data = buildAttestation(params);
324
+ const buffer = removeStatus(await run((transport) => sendByChunk(transport, [
325
+ 224,
326
+ 76,
327
+ 0,
328
+ SCRIPT_IDS.ACCOUNT_MANAGER_SESSION
329
+ ], data)));
330
+ const dataLength = buffer.readInt8(0);
331
+ return {
332
+ handshake: buffer.slice(1, dataLength + 1).toString("base64"),
333
+ signature: buffer.slice(dataLength + 1).toString("base64")
334
+ };
335
+ },
336
+ startKPatternAsResponder: async (params) => {
337
+ logger.info(`[device] startKPatternAsResponder`);
338
+ const data = buildAttestation(params);
339
+ await run((transport) => sendByChunk(transport, [
340
+ 224,
341
+ 73,
342
+ 0,
343
+ SCRIPT_IDS.ACCOUNT_MANAGER_SESSION
344
+ ], data));
345
+ },
346
+ validateVaultOperation: async (params) => {
347
+ logger.info(`[device] validateVaultOperation`);
348
+ const path = getPathFromPathString(PATHS.VALIDATION);
349
+ const paths = Buffer.concat([Buffer.from([path.length]), ...path.map((derivation) => {
350
+ const buf = Buffer.alloc(4);
351
+ buf.writeUInt32BE(derivation, 0);
352
+ return buf;
353
+ })]);
354
+ let nextActionId = 1;
355
+ let finalResponse = null;
356
+ while (!finalResponse) {
357
+ const screen = Buffer.from(params.actions[nextActionId - 1], "base64");
358
+ const length = Buffer.alloc(2);
359
+ length.writeUInt16BE(screen.length, 0);
360
+ const data = Buffer.concat([
361
+ paths,
362
+ length,
363
+ screen
364
+ ]);
365
+ const response = await run((transport) => sendByChunk(transport, [
366
+ 224,
367
+ 69,
368
+ 0,
369
+ 0
370
+ ], data));
371
+ const responseType = response.readInt8(0);
372
+ let responseStatus = response.readUInt16BE(response.length - 2);
373
+ switch (responseType) {
374
+ case 1:
375
+ nextActionId = response.readUIntBE(1, 2);
376
+ break;
377
+ case 2:
378
+ finalResponse = response.slice(3, response.length - 2);
379
+ while (responseStatus !== 36864) {
380
+ const resp = await run((transport) => transport.send(0, 192, 0, 0));
381
+ responseStatus = resp.readUInt16BE(resp.length - 2);
382
+ finalResponse = Buffer.concat([finalResponse, removeStatus(resp)]);
383
+ }
384
+ break;
385
+ default: throw new Error(`Invalid response type: ${responseType}`);
386
+ }
387
+ }
388
+ return finalResponse.toString("base64");
389
+ },
390
+ sendAPDU: async (apduCommand) => {
391
+ const res = await run((transport) => transport.exchange(Buffer.from(apduCommand, "hex")));
392
+ return Buffer.from(res).toString("hex");
393
+ },
394
+ getVersion: async () => {
395
+ const res = await run((transport) => transport.send(176, 1, 0, 0));
396
+ const appNameLen = res.readInt8(1);
397
+ const appVersionLen = res.readInt8(2 + appNameLen);
398
+ const appVersionHex = res.slice(3 + appNameLen, 2 + appNameLen + appVersionLen + 1);
399
+ return Buffer.from(appVersionHex).toString();
400
+ },
401
+ poll,
402
+ pollApp
403
+ };
420
404
  }
421
-
422
- // src/trpc.ts
423
- import { createTRPCClient, httpLink } from "@trpc/client";
424
- import superjson from "superjson";
425
- var createClient = (options) => {
426
- const trpc = createTRPCClient({
427
- links: [
428
- httpLink({
429
- url: `${options.baseUrl}/trpc`,
430
- transformer: superjson,
431
- headers(opts) {
432
- const contextHeaders = opts.op.context?.headers || {};
433
- return {
434
- ...options.debugAuthToken ? { "x-revault-debug-auth-token": options.debugAuthToken } : {},
435
- ...options.rootAuthToken ? { "x-revault-root-auth-token": options.rootAuthToken } : {},
436
- ...options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {},
437
- ...options.apiAccessToken ? { Authorization: `Bearer ${options.apiAccessToken}` } : {},
438
- // Merge in any headers passed via context
439
- ...contextHeaders
440
- };
441
- }
442
- })
443
- ]
444
- });
445
- return trpc;
405
+ //#endregion
406
+ //#region src/trpc.ts
407
+ const createClient = (options) => {
408
+ return createTRPCClient({ links: [httpLink({
409
+ url: `${options.baseUrl}/trpc`,
410
+ transformer: superjson,
411
+ headers(opts) {
412
+ const contextHeaders = opts.op.context?.headers || {};
413
+ return {
414
+ ...options.debugAuthToken ? { "x-revault-debug-auth-token": options.debugAuthToken } : {},
415
+ ...options.rootAuthToken ? { "x-revault-root-auth-token": options.rootAuthToken } : {},
416
+ ...options.psdAuth ? { Authorization: `PsdAuth ${options.psdAuth}` } : {},
417
+ ...options.apiAccessToken ? { Authorization: `Bearer ${options.apiAccessToken}` } : {},
418
+ ...contextHeaders
419
+ };
420
+ }
421
+ })] });
446
422
  };
447
-
448
- // src/engine/index.ts
449
- async function genericRegister({
450
- device,
451
- name,
452
- role,
453
- getChallenge,
454
- submitChallenge,
455
- onScreenDisplayed
456
- }) {
457
- const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([
458
- device.getAttestation(),
459
- device.getU2FPubKey(),
460
- device.getConfidentialityPubKey()
461
- ]);
462
- const ephemeralPubKey = await device.initPairingHandshake();
463
- const deviceData = {
464
- name,
465
- pubKey: u2fPubKey.pubKey,
466
- psdModel: "STAX",
467
- confidentialityKey: confidentialityKey.pubKey,
468
- psdEphemeralKey: ephemeralPubKey.pubKey,
469
- psdEphemeralKeyAttestation: {
470
- ...attestation.attestation,
471
- signature: ephemeralPubKey.signature
472
- }
473
- };
474
- const challenge = await getChallenge({ pubKey: u2fPubKey.pubKey, deviceData });
475
- const pairingPayload = await device.finalizePairingHandshake({
476
- handshake: challenge.handshake,
477
- partitionId: challenge.ciphertext,
478
- handshakeAttestation: challenge.handshakeAttestation
479
- });
480
- await onScreenDisplayed?.();
481
- const register = await device.register({
482
- challenge: challenge.challenge,
483
- u2fRegisterData: challenge.u2fRegisterData,
484
- name,
485
- role
486
- });
487
- const validationPubKey = await device.getValidationPubKey();
488
- const registerData = await device.registerData({ challenge: challenge.challenge });
489
- const attestationOffset = 67 + register.u2fRegister.readInt8(66);
490
- const u2fRegister = Buffer.concat([
491
- register.u2fRegister.slice(0, attestationOffset),
492
- Buffer.from([attestation.buffer.length]),
493
- attestation.buffer,
494
- register.u2fRegister.slice(attestationOffset)
495
- ]).toString("hex");
496
- const challengeResponse = {
497
- registerData,
498
- certificate: {
499
- ...attestation.attestation,
500
- signature: validationPubKey.signature
501
- },
502
- u2fRegister,
503
- u2fKeyHandle: register.keyHandle.toString("hex"),
504
- validationKey: validationPubKey.pubKey,
505
- pairingPayload
506
- };
507
- return submitChallenge({ pubKey: u2fPubKey.pubKey, challengeResponse });
423
+ //#endregion
424
+ //#region src/engine/index.ts
425
+ async function genericRegister({ device, name, role, getChallenge, submitChallenge, onScreenDisplayed }) {
426
+ const [attestation, u2fPubKey, confidentialityKey] = await Promise.all([
427
+ device.getAttestation(),
428
+ device.getU2FPubKey(),
429
+ device.getConfidentialityPubKey()
430
+ ]);
431
+ const ephemeralPubKey = await device.initPairingHandshake();
432
+ const deviceData = {
433
+ name,
434
+ pubKey: u2fPubKey.pubKey,
435
+ psdModel: "STAX",
436
+ confidentialityKey: confidentialityKey.pubKey,
437
+ psdEphemeralKey: ephemeralPubKey.pubKey,
438
+ psdEphemeralKeyAttestation: {
439
+ ...attestation.attestation,
440
+ signature: ephemeralPubKey.signature
441
+ }
442
+ };
443
+ const challenge = await getChallenge({
444
+ pubKey: u2fPubKey.pubKey,
445
+ deviceData
446
+ });
447
+ const pairingPayload = await device.finalizePairingHandshake({
448
+ handshake: challenge.handshake,
449
+ partitionId: challenge.ciphertext,
450
+ handshakeAttestation: challenge.handshakeAttestation
451
+ });
452
+ await onScreenDisplayed?.();
453
+ const register = await device.register({
454
+ challenge: challenge.challenge,
455
+ u2fRegisterData: challenge.u2fRegisterData,
456
+ name,
457
+ role
458
+ });
459
+ const validationPubKey = await device.getValidationPubKey();
460
+ const registerData = await device.registerData({ challenge: challenge.challenge });
461
+ const attestationOffset = 67 + register.u2fRegister.readInt8(66);
462
+ const u2fRegister = Buffer.concat([
463
+ register.u2fRegister.slice(0, attestationOffset),
464
+ Buffer.from([attestation.buffer.length]),
465
+ attestation.buffer,
466
+ register.u2fRegister.slice(attestationOffset)
467
+ ]).toString("hex");
468
+ const challengeResponse = {
469
+ registerData,
470
+ certificate: {
471
+ ...attestation.attestation,
472
+ signature: validationPubKey.signature
473
+ },
474
+ u2fRegister,
475
+ u2fKeyHandle: register.keyHandle.toString("hex"),
476
+ validationKey: validationPubKey.pubKey,
477
+ pairingPayload
478
+ };
479
+ return submitChallenge({
480
+ pubKey: u2fPubKey.pubKey,
481
+ challengeResponse
482
+ });
508
483
  }
509
484
  function createEngine(options, logger) {
510
- const clientOptions = {
511
- baseUrl: options.baseUrl
512
- };
513
- const client = createClient(clientOptions);
514
- const apiDevice = createApiDevice(options, logger);
515
- const base = {
516
- client,
517
- createClient: (overrides) => createClient({ ...clientOptions, ...overrides }),
518
- __options: options
519
- };
520
- const withDeviceIndex = function(deviceIndex) {
521
- const device = apiDevice.with(deviceIndex);
522
- const withPsd = { device };
523
- return decorateEngine({ ...this, ...withPsd });
524
- };
525
- const withTransportId = function(transportId) {
526
- const device = createRealDevice({ transportId }, logger);
527
- const withPsd = { device };
528
- return decorateEngine({ ...this, ...withPsd });
529
- };
530
- const withApiUser = function() {
531
- const withApiUser2 = { __isApiUser: true };
532
- return decorateEngine({ ...this, ...withApiUser2 });
533
- };
534
- const withWorkspace = function(workspaceName) {
535
- const withWorkspace2 = { __workspaceName: workspaceName };
536
- return decorateEngine({ ...this, ...withWorkspace2 });
537
- };
538
- const withOnboarding = function(onboardingId) {
539
- const withOnboarding2 = { __onboardingId: onboardingId };
540
- return decorateEngine({ ...this, ...withOnboarding2 });
541
- };
542
- function decorateEngine(engine) {
543
- function decorate(decorator) {
544
- Object.assign(engine, decorator(engine));
545
- }
546
- if (engine.device) {
547
- decorate(
548
- (engine2) => ({
549
- getWorkspaces: async () => {
550
- const { device, client: client2 } = engine2;
551
- const { pubKey } = await device.getU2FPubKey();
552
- const { workspaceNames } = await client2.auth.psd.findWorkspaceNames.query({ pubKey });
553
- return workspaceNames;
554
- },
555
- getWorkspacesForSso: async () => {
556
- const { device, client: client2 } = engine2;
557
- const { pubKey } = await device.getU2FPubKey();
558
- const { workspaces } = await client2.auth.sso.findWorkspaces.query({ pubKey });
559
- return workspaces;
560
- }
561
- })
562
- );
563
- }
564
- if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) {
565
- decorate((engine2) => {
566
- const { __workspaceName } = engine2;
567
- return {
568
- withPsdToken: function(token) {
569
- const withPsdAuth = { __psdToken: token };
570
- const psdAuth = `${__workspaceName}:${token}`;
571
- const client2 = engine2.createClient({ psdAuth });
572
- return decorateEngine({ ...this, client: client2, ...withPsdAuth });
573
- }
574
- };
575
- });
576
- }
577
- if (engine.device && engine.__onboardingId) {
578
- decorate((engine2) => {
579
- const { device, client: client2, __onboardingId } = engine2;
580
- async function enforcePairing() {
581
- if (await device.hasPairing()) return;
582
- const [{ pubKey }, confidentialityKey] = await Promise.all([
583
- device.getU2FPubKey(),
584
- device.getConfidentialityKey()
585
- ]);
586
- const pairing = await client2.onboarding.pairDevicePartition.mutate({
587
- pubKey,
588
- onboardingId: __onboardingId,
589
- data: {
590
- confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
591
- confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
592
- }
593
- });
594
- await device.setPairing({ pairing });
595
- }
596
- return {
597
- claimDevice: async (params) => {
598
- const { role, deviceName } = params;
599
- const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([
600
- device.getU2FPubKey(),
601
- device.getConfidentialityPubKey()
602
- ]);
603
- await client2.onboarding.claimDevice.mutate({
604
- onboardingId: __onboardingId,
605
- claim: { role, pubKey, deviceName, confidentialityKey }
606
- });
607
- },
608
- collectWrappingKeyFragment: async (wrappingKey, params) => {
609
- const [{ pubKey }, confidentialityKey] = await Promise.all([
610
- device.getU2FPubKey(),
611
- device.getConfidentialityPubKey()
612
- ]);
613
- await device.openSession({
614
- secureChannel: {
615
- pubKey: wrappingKey.ephemeralPubKey,
616
- certificate: wrappingKey.ephemeralCertificate
617
- }
618
- });
619
- const { attestation } = await device.getAttestation();
620
- await params?.onScreenDisplayed?.();
621
- const blob = await device.generateWrappingKeyFragment();
622
- await client2.onboarding.submitWrappingKeyFragment.mutate({
623
- pubKey,
624
- onboardingId: __onboardingId,
625
- fragment: {
626
- blob,
627
- ephemeralPubKey: confidentialityKey.pubKey,
628
- ephemeralCertificate: {
629
- ...attestation,
630
- signature: confidentialityKey.signature
631
- }
632
- }
633
- });
634
- },
635
- registerDevice: async (registerParams, params) => {
636
- const { role, name } = registerParams;
637
- const getChallengeMutation = role === "ADMIN" ? client2.onboarding.generateMasterAdminRegistrationChallenge : client2.onboarding.generateSharedOwnerRegistrationChallenge;
638
- const submitChallengeMutation = role === "ADMIN" ? client2.onboarding.submitMasterAdminRegistration : client2.onboarding.submitSharedOwnerRegistration;
639
- await genericRegister({
640
- device,
641
- name,
642
- role,
643
- getChallenge: ({ pubKey, deviceData }) => getChallengeMutation.mutate({
644
- onboardingId: __onboardingId,
645
- pubKey,
646
- deviceData
647
- }),
648
- submitChallenge: ({ pubKey, challengeResponse }) => submitChallengeMutation.mutate({
649
- onboardingId: engine2.__onboardingId,
650
- pubKey,
651
- // FIXME this should be renamed to `challengeResponse` on backend side
652
- response: challengeResponse
653
- }),
654
- onScreenDisplayed: params?.onScreenDisplayed
655
- });
656
- },
657
- reviewSharedOwner: async (challenge, params) => {
658
- await enforcePairing();
659
- const { pubKey } = await device.getU2FPubKey();
660
- await device.startKPatternAsResponder({
661
- handshake: challenge.handshake,
662
- handshakeAttestation: challenge.handshakeAttestation,
663
- partitionId: challenge.partitionId
664
- });
665
- await params?.onScreenDisplayed?.();
666
- const signature = await device.validateVaultOperation({
667
- actions: challenge.wActions
668
- });
669
- await client2.onboarding.submitReviewByMasterAdminSignature.mutate({
670
- onboardingId: __onboardingId,
671
- pubKey,
672
- signature
673
- });
674
- },
675
- collectSeedFragment: async (challenge, params) => {
676
- await enforcePairing();
677
- const [{ pubKey }, { attestation }] = await Promise.all([
678
- device.getU2FPubKey(),
679
- device.getAttestation()
680
- ]);
681
- await device.startKPatternAsResponder({
682
- handshake: challenge.handshake,
683
- handshakeAttestation: challenge.handshakeAttestation,
684
- partitionId: challenge.partitionId
685
- });
686
- await params?.onScreenDisplayed?.();
687
- const challengeResponse = await device.validateVaultOperation({
688
- actions: challenge.wActions
689
- });
690
- const kkPattern = await device.startKKPatternAsResponder({
691
- partitionId: challenge.partitionId,
692
- handshake: challenge.kkHandshake,
693
- handshakeAttestation: challenge.kkHandshakeAttestation
694
- });
695
- const approverBlob = await device.generateSeedFragment();
696
- await client2.onboarding.submitSeedFragment.mutate({
697
- onboardingId: __onboardingId,
698
- pubKey,
699
- seedFragment: {
700
- challengeResponse,
701
- approverBlob,
702
- handshake: kkPattern.handshake,
703
- handshakeAttestation: {
704
- ...attestation,
705
- signature: kkPattern.signature
706
- }
707
- }
708
- });
709
- }
710
- };
711
- });
712
- }
713
- if (engine.device && engine.__workspaceName && !engine.__psdToken) {
714
- decorate(
715
- (engine2) => {
716
- const { device, client: client2, __workspaceName } = engine2;
717
- return {
718
- login: async function(opts) {
719
- const { pubKey } = await device.getU2FPubKey();
720
- const challenge = await client2.auth.psd.generateChallenge.mutate(
721
- {
722
- pubKey,
723
- workspaceName: __workspaceName
724
- },
725
- buildTrpcContext({ correlationId: opts?.correlationId })
726
- );
727
- await opts?.onScreenDisplayed?.();
728
- const authentication = await device.authenticate({
729
- challenge,
730
- workspaceName: __workspaceName
731
- });
732
- const authPayload = {
733
- workspaceName: __workspaceName,
734
- pubKey,
735
- authentication,
736
- challengeId: challenge.challengeId,
737
- validityDurationSecs: opts?.validityDurationSecs
738
- };
739
- const { token } = await client2.auth.psd.authenticate.mutate(
740
- { ...authPayload },
741
- buildTrpcContext({ correlationId: opts?.correlationId })
742
- );
743
- const withPsdAuth = {
744
- __psdToken: token
745
- };
746
- const psdAuth = `${engine2.__workspaceName}:${token}`;
747
- const __authClient = engine2.createClient({ psdAuth });
748
- return decorateEngine({ ...this, client: __authClient, ...withPsdAuth });
749
- },
750
- register: (registration) => {
751
- return genericRegister({
752
- device,
753
- name: registration.name,
754
- role: registration.role,
755
- getChallenge: async ({ deviceData }) => {
756
- const challenge = await client2.userRegistrations.generateChallenge.mutate({
757
- id: registration.id,
758
- workspaceName: __workspaceName,
759
- deviceData
760
- });
761
- return challenge;
762
- },
763
- submitChallenge: ({ challengeResponse }) => client2.userRegistrations.submitChallenge.mutate({
764
- workspaceName: __workspaceName,
765
- id: registration.id,
766
- challengeResponse
767
- })
768
- });
769
- }
770
- };
771
- }
772
- );
773
- }
774
- if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) {
775
- decorate(
776
- (engine2) => {
777
- const { client: client2, __workspaceName } = engine2;
778
- return {
779
- login: async function(credentials, opts) {
780
- const res = await client2.auth.authenticate.mutate(
781
- {
782
- apiKeyId: credentials.apiKeyId,
783
- apiKeySecret: credentials.apiKeySecret,
784
- workspace: __workspaceName
785
- },
786
- buildTrpcContext({ correlationId: opts?.correlationId })
787
- );
788
- const withApiAuth = {
789
- __apiAuth: res
790
- };
791
- const __authClient = engine2.createClient({ apiAccessToken: res.accessToken });
792
- return decorateEngine({ ...this, client: __authClient, ...withApiAuth });
793
- }
794
- };
795
- }
796
- );
797
- }
798
- if (engine.device && engine.__workspaceName && engine.__psdToken) {
799
- decorate((engine2) => {
800
- const { client: client2, device } = engine2;
801
- async function enforcePairing() {
802
- if (await device.hasPairing()) return;
803
- const confidentialityKey = await device.getConfidentialityKey();
804
- const pairing = await client2.debug.pairDevicePartition.mutate({
805
- confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
806
- confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
807
- });
808
- await device.setPairing({ pairing });
809
- }
810
- const approveChallenge = async (challenge, params) => {
811
- await enforcePairing();
812
- await device.startKPatternAsResponder({
813
- handshake: challenge.handshake,
814
- handshakeAttestation: challenge.handshakeAttestation,
815
- partitionId: challenge.partitionId
816
- });
817
- await params?.onScreenDisplayed?.();
818
- const signature = await device.validateVaultOperation({
819
- actions: challenge.wActions
820
- });
821
- return signature;
822
- };
823
- return {
824
- approve: async (request, params) => {
825
- const { challenge } = await client2.requests.getChallenge.query({ id: request.id });
826
- if (challenge.challengeType === "PSD") {
827
- const signature = await approveChallenge(challenge, params);
828
- await params?.onPsdChallengeSigned?.();
829
- return client2.requests.approve.mutate(
830
- {
831
- id: request.id,
832
- data: { challengeType: "PSD", signature }
833
- },
834
- buildTrpcContext(params)
835
- );
836
- }
837
- if (challenge.challengeType === "SOFT") {
838
- return client2.requests.approve.mutate(
839
- {
840
- id: request.id,
841
- data: { challengeType: "SOFT" }
842
- },
843
- buildTrpcContext(params)
844
- );
845
- }
846
- throw new Error("Challenge type must be either PSD or SOFT");
847
- },
848
- approveChallenge,
849
- reject: (request, opts) => {
850
- return client2.requests.reject.mutate(
851
- { id: request.id, data: null },
852
- buildTrpcContext(opts)
853
- );
854
- }
855
- };
856
- });
857
- }
858
- if (engine.__workspaceName && engine.__apiAuth) {
859
- decorate((engine2) => {
860
- const { client: client2 } = engine2;
861
- return {
862
- getChallenge: async (request) => {
863
- const { challenge } = await client2.requests.getChallenge.query({ id: request.id });
864
- invariant2(challenge.challengeType === "API", "Challenge type must be API");
865
- return challenge.payload;
866
- },
867
- approve: (request, signature) => {
868
- return client2.requests.approve.mutate({
869
- id: request.id,
870
- data: { challengeType: "API", signature }
871
- });
872
- },
873
- reject: (request, signature) => {
874
- return client2.requests.reject.mutate({
875
- id: request.id,
876
- data: { challengeType: "API", signature }
877
- });
878
- }
879
- };
880
- });
881
- }
882
- return engine;
883
- }
884
- return {
885
- ...base,
886
- withDeviceIndex,
887
- withTransportId,
888
- withApiUser,
889
- withWorkspace,
890
- withOnboarding
891
- };
485
+ const clientOptions = { baseUrl: options.baseUrl };
486
+ const client = createClient(clientOptions);
487
+ const apiDevice = createApiDevice(options, logger);
488
+ const base = {
489
+ client,
490
+ createClient: (overrides) => createClient({
491
+ ...clientOptions,
492
+ ...overrides
493
+ }),
494
+ __options: options
495
+ };
496
+ const withDeviceIndex = function(deviceIndex) {
497
+ const withPsd = { device: apiDevice.with(deviceIndex) };
498
+ return decorateEngine({
499
+ ...this,
500
+ ...withPsd
501
+ });
502
+ };
503
+ const withTransportId = function(transportId) {
504
+ const withPsd = { device: createRealDevice({ transportId }, logger) };
505
+ return decorateEngine({
506
+ ...this,
507
+ ...withPsd
508
+ });
509
+ };
510
+ const withApiUser = function() {
511
+ const withApiUser = { __isApiUser: true };
512
+ return decorateEngine({
513
+ ...this,
514
+ ...withApiUser
515
+ });
516
+ };
517
+ const withWorkspace = function(workspaceName) {
518
+ const withWorkspace = { __workspaceName: workspaceName };
519
+ return decorateEngine({
520
+ ...this,
521
+ ...withWorkspace
522
+ });
523
+ };
524
+ const withOnboarding = function(onboardingId) {
525
+ const withOnboarding = { __onboardingId: onboardingId };
526
+ return decorateEngine({
527
+ ...this,
528
+ ...withOnboarding
529
+ });
530
+ };
531
+ function decorateEngine(engine) {
532
+ function decorate(decorator) {
533
+ Object.assign(engine, decorator(engine));
534
+ }
535
+ if (engine.device) decorate((engine) => ({
536
+ getWorkspaces: async () => {
537
+ const { device, client } = engine;
538
+ const { pubKey } = await device.getU2FPubKey();
539
+ const { workspaceNames } = await client.auth.psd.findWorkspaceNames.query({ pubKey });
540
+ return workspaceNames;
541
+ },
542
+ getWorkspacesForSso: async () => {
543
+ const { device, client } = engine;
544
+ const { pubKey } = await device.getU2FPubKey();
545
+ const { workspaces } = await client.auth.sso.findWorkspaces.query({ pubKey });
546
+ return workspaces;
547
+ }
548
+ }));
549
+ if (engine.__workspaceName && !engine.__psdToken && !engine.__apiAuth) decorate((engine) => {
550
+ const { __workspaceName } = engine;
551
+ return { withPsdToken: function(token) {
552
+ const withPsdAuth = { __psdToken: token };
553
+ const psdAuth = `${__workspaceName}:${token}`;
554
+ const client = engine.createClient({ psdAuth });
555
+ return decorateEngine({
556
+ ...this,
557
+ client,
558
+ ...withPsdAuth
559
+ });
560
+ } };
561
+ });
562
+ if (engine.device && engine.__onboardingId) decorate((engine) => {
563
+ const { device, client, __onboardingId } = engine;
564
+ async function enforcePairing() {
565
+ if (await device.hasPairing()) return;
566
+ const [{ pubKey }, confidentialityKey] = await Promise.all([device.getU2FPubKey(), device.getConfidentialityKey()]);
567
+ const pairing = await client.onboarding.pairDevicePartition.mutate({
568
+ pubKey,
569
+ onboardingId: __onboardingId,
570
+ data: {
571
+ confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
572
+ confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
573
+ }
574
+ });
575
+ await device.setPairing({ pairing });
576
+ }
577
+ return {
578
+ claimDevice: async (params) => {
579
+ const { role, deviceName } = params;
580
+ const [{ pubKey }, { pubKey: confidentialityKey }] = await Promise.all([device.getU2FPubKey(), device.getConfidentialityPubKey()]);
581
+ await client.onboarding.claimDevice.mutate({
582
+ onboardingId: __onboardingId,
583
+ claim: {
584
+ role,
585
+ pubKey,
586
+ deviceName,
587
+ confidentialityKey
588
+ }
589
+ });
590
+ },
591
+ collectWrappingKeyFragment: async (wrappingKey, params) => {
592
+ const [{ pubKey }, confidentialityKey] = await Promise.all([device.getU2FPubKey(), device.getConfidentialityPubKey()]);
593
+ await device.openSession({ secureChannel: {
594
+ pubKey: wrappingKey.ephemeralPubKey,
595
+ certificate: wrappingKey.ephemeralCertificate
596
+ } });
597
+ const { attestation } = await device.getAttestation();
598
+ await params?.onScreenDisplayed?.();
599
+ const blob = await device.generateWrappingKeyFragment();
600
+ await client.onboarding.submitWrappingKeyFragment.mutate({
601
+ pubKey,
602
+ onboardingId: __onboardingId,
603
+ fragment: {
604
+ blob,
605
+ ephemeralPubKey: confidentialityKey.pubKey,
606
+ ephemeralCertificate: {
607
+ ...attestation,
608
+ signature: confidentialityKey.signature
609
+ }
610
+ }
611
+ });
612
+ },
613
+ registerDevice: async (registerParams, params) => {
614
+ const { role, name } = registerParams;
615
+ const getChallengeMutation = role === "ADMIN" ? client.onboarding.generateMasterAdminRegistrationChallenge : client.onboarding.generateSharedOwnerRegistrationChallenge;
616
+ const submitChallengeMutation = role === "ADMIN" ? client.onboarding.submitMasterAdminRegistration : client.onboarding.submitSharedOwnerRegistration;
617
+ await genericRegister({
618
+ device,
619
+ name,
620
+ role,
621
+ getChallenge: ({ pubKey, deviceData }) => getChallengeMutation.mutate({
622
+ onboardingId: __onboardingId,
623
+ pubKey,
624
+ deviceData
625
+ }),
626
+ submitChallenge: ({ pubKey, challengeResponse }) => submitChallengeMutation.mutate({
627
+ onboardingId: engine.__onboardingId,
628
+ pubKey,
629
+ response: challengeResponse
630
+ }),
631
+ onScreenDisplayed: params?.onScreenDisplayed
632
+ });
633
+ },
634
+ reviewSharedOwner: async (challenge, params) => {
635
+ await enforcePairing();
636
+ const { pubKey } = await device.getU2FPubKey();
637
+ await device.startKPatternAsResponder({
638
+ handshake: challenge.handshake,
639
+ handshakeAttestation: challenge.handshakeAttestation,
640
+ partitionId: challenge.partitionId
641
+ });
642
+ await params?.onScreenDisplayed?.();
643
+ const signature = await device.validateVaultOperation({ actions: challenge.wActions });
644
+ await client.onboarding.submitReviewByMasterAdminSignature.mutate({
645
+ onboardingId: __onboardingId,
646
+ pubKey,
647
+ signature
648
+ });
649
+ },
650
+ collectSeedFragment: async (challenge, params) => {
651
+ await enforcePairing();
652
+ const [{ pubKey }, { attestation }] = await Promise.all([device.getU2FPubKey(), device.getAttestation()]);
653
+ await device.startKPatternAsResponder({
654
+ handshake: challenge.handshake,
655
+ handshakeAttestation: challenge.handshakeAttestation,
656
+ partitionId: challenge.partitionId
657
+ });
658
+ await params?.onScreenDisplayed?.();
659
+ const challengeResponse = await device.validateVaultOperation({ actions: challenge.wActions });
660
+ const kkPattern = await device.startKKPatternAsResponder({
661
+ partitionId: challenge.partitionId,
662
+ handshake: challenge.kkHandshake,
663
+ handshakeAttestation: challenge.kkHandshakeAttestation
664
+ });
665
+ const approverBlob = await device.generateSeedFragment();
666
+ await client.onboarding.submitSeedFragment.mutate({
667
+ onboardingId: __onboardingId,
668
+ pubKey,
669
+ seedFragment: {
670
+ challengeResponse,
671
+ approverBlob,
672
+ handshake: kkPattern.handshake,
673
+ handshakeAttestation: {
674
+ ...attestation,
675
+ signature: kkPattern.signature
676
+ }
677
+ }
678
+ });
679
+ }
680
+ };
681
+ });
682
+ if (engine.device && engine.__workspaceName && !engine.__psdToken) decorate((engine) => {
683
+ const { device, client, __workspaceName } = engine;
684
+ return {
685
+ login: async function(opts) {
686
+ const { pubKey } = await device.getU2FPubKey();
687
+ const challenge = await client.auth.psd.generateChallenge.mutate({
688
+ pubKey,
689
+ workspaceName: __workspaceName
690
+ }, buildTrpcContext({ correlationId: opts?.correlationId }));
691
+ await opts?.onScreenDisplayed?.();
692
+ const authPayload = {
693
+ workspaceName: __workspaceName,
694
+ pubKey,
695
+ authentication: await device.authenticate({
696
+ challenge,
697
+ workspaceName: __workspaceName
698
+ }),
699
+ challengeId: challenge.challengeId,
700
+ validityDurationSecs: opts?.validityDurationSecs
701
+ };
702
+ const { token } = await client.auth.psd.authenticate.mutate({ ...authPayload }, buildTrpcContext({ correlationId: opts?.correlationId }));
703
+ const withPsdAuth = { __psdToken: token };
704
+ const psdAuth = `${engine.__workspaceName}:${token}`;
705
+ const __authClient = engine.createClient({ psdAuth });
706
+ return decorateEngine({
707
+ ...this,
708
+ client: __authClient,
709
+ ...withPsdAuth
710
+ });
711
+ },
712
+ register: (registration) => {
713
+ return genericRegister({
714
+ device,
715
+ name: registration.name,
716
+ role: registration.role,
717
+ getChallenge: async ({ deviceData }) => {
718
+ return await client.userRegistrations.generateChallenge.mutate({
719
+ id: registration.id,
720
+ workspaceName: __workspaceName,
721
+ deviceData
722
+ });
723
+ },
724
+ submitChallenge: ({ challengeResponse }) => client.userRegistrations.submitChallenge.mutate({
725
+ workspaceName: __workspaceName,
726
+ id: registration.id,
727
+ challengeResponse
728
+ })
729
+ });
730
+ }
731
+ };
732
+ });
733
+ if (engine.__workspaceName && engine.__isApiUser && !engine.__apiAuth) decorate((engine) => {
734
+ const { client, __workspaceName } = engine;
735
+ return { login: async function(credentials, opts) {
736
+ const res = await client.auth.authenticate.mutate({
737
+ apiKeyId: credentials.apiKeyId,
738
+ apiKeySecret: credentials.apiKeySecret,
739
+ workspace: __workspaceName
740
+ }, buildTrpcContext({ correlationId: opts?.correlationId }));
741
+ const withApiAuth = { __apiAuth: res };
742
+ const __authClient = engine.createClient({ apiAccessToken: res.accessToken });
743
+ return decorateEngine({
744
+ ...this,
745
+ client: __authClient,
746
+ ...withApiAuth
747
+ });
748
+ } };
749
+ });
750
+ if (engine.device && engine.__workspaceName && engine.__psdToken) decorate((engine) => {
751
+ const { client, device } = engine;
752
+ async function enforcePairing() {
753
+ if (await device.hasPairing()) return;
754
+ const confidentialityKey = await device.getConfidentialityKey();
755
+ const pairing = await client.debug.pairDevicePartition.mutate({
756
+ confidentialityKeyCurve25519: confidentialityKey.confidentialityKeyCurve25519,
757
+ confidentialityKeySignature: confidentialityKey.confidentialityKeySignature
758
+ });
759
+ await device.setPairing({ pairing });
760
+ }
761
+ const approveChallenge = async (challenge, params) => {
762
+ await enforcePairing();
763
+ await device.startKPatternAsResponder({
764
+ handshake: challenge.handshake,
765
+ handshakeAttestation: challenge.handshakeAttestation,
766
+ partitionId: challenge.partitionId
767
+ });
768
+ await params?.onScreenDisplayed?.();
769
+ return await device.validateVaultOperation({ actions: challenge.wActions });
770
+ };
771
+ return {
772
+ approve: async (request, params) => {
773
+ const { challenge } = await client.requests.getChallenge.query({ id: request.id });
774
+ if (challenge.challengeType === "PSD") {
775
+ const signature = await approveChallenge(challenge, params);
776
+ await params?.onPsdChallengeSigned?.();
777
+ return client.requests.approve.mutate({
778
+ id: request.id,
779
+ data: {
780
+ challengeType: "PSD",
781
+ signature
782
+ }
783
+ }, buildTrpcContext(params));
784
+ }
785
+ if (challenge.challengeType === "SOFT") return client.requests.approve.mutate({
786
+ id: request.id,
787
+ data: { challengeType: "SOFT" }
788
+ }, buildTrpcContext(params));
789
+ throw new Error("Challenge type must be either PSD or SOFT");
790
+ },
791
+ approveChallenge,
792
+ reject: (request, opts) => {
793
+ return client.requests.reject.mutate({
794
+ id: request.id,
795
+ data: null
796
+ }, buildTrpcContext(opts));
797
+ }
798
+ };
799
+ });
800
+ if (engine.__workspaceName && engine.__apiAuth) decorate((engine) => {
801
+ const { client } = engine;
802
+ return {
803
+ getChallenge: async (request) => {
804
+ const { challenge } = await client.requests.getChallenge.query({ id: request.id });
805
+ invariant(challenge.challengeType === "API", "Challenge type must be API");
806
+ return challenge.payload;
807
+ },
808
+ approve: (request, signature) => {
809
+ return client.requests.approve.mutate({
810
+ id: request.id,
811
+ data: {
812
+ challengeType: "API",
813
+ signature
814
+ }
815
+ });
816
+ },
817
+ reject: (request, signature) => {
818
+ return client.requests.reject.mutate({
819
+ id: request.id,
820
+ data: {
821
+ challengeType: "API",
822
+ signature
823
+ }
824
+ });
825
+ }
826
+ };
827
+ });
828
+ return engine;
829
+ }
830
+ return {
831
+ ...base,
832
+ withDeviceIndex,
833
+ withTransportId,
834
+ withApiUser,
835
+ withWorkspace,
836
+ withOnboarding
837
+ };
892
838
  }
893
- export {
894
- createEngine,
895
- fetchAll,
896
- fetchAllCursor
897
- };
898
- /* v8 ignore next -- @preserve */
839
+ //#endregion
840
+ export { createEngine, fetchAll, fetchAllCursor };
841
+
899
842
  //# sourceMappingURL=engine.js.map