@calimero-network/mero-js 25.0.7 → 25.1.0
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/README.md +25 -0
- package/dist/agent-gate/chacha20poly1305.d.ts +20 -0
- package/dist/agent-gate/chacha20poly1305.js +148 -0
- package/dist/agent-gate/gate.d.ts +115 -0
- package/dist/agent-gate/gate.js +232 -0
- package/dist/agent-gate/hpke.d.ts +23 -0
- package/dist/agent-gate/hpke.js +84 -0
- package/dist/agent-gate/index.d.ts +4 -0
- package/dist/agent-gate/index.js +2 -0
- package/dist/agent-gate/policy.d.ts +65 -0
- package/dist/agent-gate/policy.js +103 -0
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +550 -101
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +550 -101
- package/dist/index.mjs.map +4 -4
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,10 +31,13 @@ var index_exports = {};
|
|
|
31
31
|
__export(index_exports, {
|
|
32
32
|
ACCOUNT_HA_AUDIENCE: () => ACCOUNT_HA_AUDIENCE,
|
|
33
33
|
ACCOUNT_OWNERSHIP_AUDIENCE: () => ACCOUNT_OWNERSHIP_AUDIENCE,
|
|
34
|
+
AGENT_ATTEST_DOMAIN: () => AGENT_ATTEST_DOMAIN,
|
|
35
|
+
AGENT_PROVISION_INFO_DOMAIN: () => AGENT_PROVISION_INFO_DOMAIN,
|
|
34
36
|
AccountHaRefusedError: () => AccountHaRefusedError,
|
|
35
37
|
AccountLinkedToSeveralUsersError: () => AccountLinkedToSeveralUsersError,
|
|
36
38
|
AccountNotLinkedError: () => AccountNotLinkedError,
|
|
37
39
|
AdminApiClient: () => AdminApiClient,
|
|
40
|
+
AgentGateError: () => AgentGateError,
|
|
38
41
|
AuthApiClient: () => AuthApiClient,
|
|
39
42
|
AuthRevokedError: () => AuthRevokedError,
|
|
40
43
|
CAPABILITIES: () => CAPABILITIES,
|
|
@@ -51,6 +54,7 @@ __export(index_exports, {
|
|
|
51
54
|
INVITED_ROLE: () => INVITED_ROLE,
|
|
52
55
|
IntentRefusedError: () => IntentRefusedError,
|
|
53
56
|
InvitationNotClaimableError: () => InvitationNotClaimableError,
|
|
57
|
+
KMS_RELEASE_SIGNER: () => KMS_RELEASE_SIGNER,
|
|
54
58
|
LocalStorageTokenStore: () => LocalStorageTokenStore,
|
|
55
59
|
MAX_INVITATION_VALIDITY_SECS: () => MAX_INVITATION_VALIDITY_SECS,
|
|
56
60
|
MemoryTokenStore: () => MemoryTokenStore,
|
|
@@ -89,8 +93,11 @@ __export(index_exports, {
|
|
|
89
93
|
accountRootSignerFromPhrase: () => accountRootSignerFromPhrase,
|
|
90
94
|
adminChangedOp: () => adminChangedOp,
|
|
91
95
|
admitterAddrsFromNetworkStatus: () => admitterAddrsFromNetworkStatus,
|
|
96
|
+
agentKeyBinding: () => agentKeyBinding,
|
|
97
|
+
agentQuoteVerifier: () => agentQuoteVerifier,
|
|
92
98
|
applicationIdForBundle: () => applicationIdForBundle,
|
|
93
99
|
attemptRelayNodeKey: () => attemptRelayNodeKey,
|
|
100
|
+
attestAgent: () => attestAgent,
|
|
94
101
|
attestKeyBinding: () => attestKeyBinding,
|
|
95
102
|
attestRelayNodeKey: () => attestRelayNodeKey,
|
|
96
103
|
authorNonceLookup: () => authorNonceLookup,
|
|
@@ -104,6 +111,7 @@ __export(index_exports, {
|
|
|
104
111
|
capMask: () => capMask,
|
|
105
112
|
capNames: () => capNames,
|
|
106
113
|
carryExecutorAccount: () => carryExecutorAccount,
|
|
114
|
+
checkOwner: () => checkOwner,
|
|
107
115
|
classifyError: () => classifyError,
|
|
108
116
|
clearDelegatedCredential: () => clearDelegatedCredential,
|
|
109
117
|
clearDelegatedSession: () => clearDelegatedSession,
|
|
@@ -171,6 +179,7 @@ __export(index_exports, {
|
|
|
171
179
|
foundDelegatedNamespace: () => foundDelegatedNamespace,
|
|
172
180
|
foundedNamespaceId: () => foundedNamespaceId,
|
|
173
181
|
generateAccountRoot: () => generateAccountRoot,
|
|
182
|
+
generateOwnerKey: () => generateOwnerKey,
|
|
174
183
|
generateSessionKey: () => generateSessionKey,
|
|
175
184
|
governGroup: () => governGroup,
|
|
176
185
|
governRoot: () => governRoot,
|
|
@@ -211,6 +220,7 @@ __export(index_exports, {
|
|
|
211
220
|
normaliseAccount: () => normaliseAccount,
|
|
212
221
|
ownerOpDigest: () => ownerOpDigest,
|
|
213
222
|
ownerOpSigningPayload: () => ownerOpSigningPayload,
|
|
223
|
+
ownerPublicKey: () => ownerPublicKey,
|
|
214
224
|
parseAuthCallback: () => parseAuthCallback,
|
|
215
225
|
parseCreationWarrant: () => parseCreationWarrant,
|
|
216
226
|
parseDeviceCredential: () => parseDeviceCredential,
|
|
@@ -220,6 +230,8 @@ __export(index_exports, {
|
|
|
220
230
|
pinRelayNodeKey: () => pinRelayNodeKey,
|
|
221
231
|
presenceStatementBytes: () => presenceStatementBytes,
|
|
222
232
|
probeNodeHealth: () => probeNodeHealth,
|
|
233
|
+
provisionAgent: () => provisionAgent,
|
|
234
|
+
provisionInfo: () => provisionInfo,
|
|
223
235
|
readCloudLinkCallback: () => readCloudLinkCallback,
|
|
224
236
|
readDelegatedCredential: () => readDelegatedCredential,
|
|
225
237
|
readDelegatedSession: () => readDelegatedSession,
|
|
@@ -229,6 +241,7 @@ __export(index_exports, {
|
|
|
229
241
|
redeemInvitation: () => redeemInvitation,
|
|
230
242
|
relayForContext: () => relayForContext,
|
|
231
243
|
relayTransportFetch: () => relayTransportFetch,
|
|
244
|
+
releaseAgent: () => releaseAgent,
|
|
232
245
|
rememberGroupNamespace: () => rememberGroupNamespace,
|
|
233
246
|
rememberRelay: () => rememberRelay,
|
|
234
247
|
reportDataOf: () => reportDataOf,
|
|
@@ -275,7 +288,9 @@ __export(index_exports, {
|
|
|
275
288
|
transportKeyBinding: () => transportKeyBinding,
|
|
276
289
|
trustSignedRelease: () => trustSignedRelease,
|
|
277
290
|
trustedMeasurementsFromReleases: () => trustedMeasurementsFromReleases,
|
|
291
|
+
validateAgentId: () => validateAgentId,
|
|
278
292
|
verifyDeviceCredential: () => verifyDeviceCredential,
|
|
293
|
+
verifySignedAgentPolicy: () => verifySignedAgentPolicy,
|
|
279
294
|
verifySignedNodeRelease: () => verifySignedNodeRelease,
|
|
280
295
|
withCap: () => withCap,
|
|
281
296
|
withRetry: () => withRetry,
|
|
@@ -333,14 +348,14 @@ function extractErrorMessage(bodyText) {
|
|
|
333
348
|
return void 0;
|
|
334
349
|
}
|
|
335
350
|
var HTTPError = class extends Error {
|
|
336
|
-
constructor(status, statusText,
|
|
351
|
+
constructor(status, statusText, url2, headers, bodyText) {
|
|
337
352
|
const explanation = extractErrorMessage(bodyText) ?? (status === 0 && bodyText?.trim() ? bodyText.trim() : void 0);
|
|
338
353
|
super(
|
|
339
354
|
explanation ? `HTTP ${status} ${statusText}: ${explanation}` : `HTTP ${status} ${statusText}`
|
|
340
355
|
);
|
|
341
356
|
this.status = status;
|
|
342
357
|
this.statusText = statusText;
|
|
343
|
-
this.url =
|
|
358
|
+
this.url = url2;
|
|
344
359
|
this.headers = headers;
|
|
345
360
|
this.bodyText = bodyText;
|
|
346
361
|
this.name = "HTTPError";
|
|
@@ -357,8 +372,8 @@ var HTTPError = class extends Error {
|
|
|
357
372
|
}
|
|
358
373
|
};
|
|
359
374
|
var AuthRevokedError = class extends HTTPError {
|
|
360
|
-
constructor(reason, status, statusText,
|
|
361
|
-
super(status, statusText,
|
|
375
|
+
constructor(reason, status, statusText, url2, headers, bodyText) {
|
|
376
|
+
super(status, statusText, url2, headers, bodyText);
|
|
362
377
|
this.reason = reason;
|
|
363
378
|
this.name = "AuthRevokedError";
|
|
364
379
|
this.message = `Authentication revoked (${reason}): HTTP ${status} ${statusText}`;
|
|
@@ -371,12 +386,12 @@ function headersToRecord(headers) {
|
|
|
371
386
|
});
|
|
372
387
|
return record;
|
|
373
388
|
}
|
|
374
|
-
function pathForProof(
|
|
389
|
+
function pathForProof(url2) {
|
|
375
390
|
try {
|
|
376
|
-
return new URL(
|
|
391
|
+
return new URL(url2).pathname;
|
|
377
392
|
} catch {
|
|
378
|
-
const query =
|
|
379
|
-
return query === -1 ?
|
|
393
|
+
const query = url2.indexOf("?");
|
|
394
|
+
return query === -1 ? url2 : url2.slice(0, query);
|
|
380
395
|
}
|
|
381
396
|
}
|
|
382
397
|
var WebHttpClient = class {
|
|
@@ -442,7 +457,7 @@ var WebHttpClient = class {
|
|
|
442
457
|
}
|
|
443
458
|
async makeRequest(path, init, retryCount = 0, requestStartTime) {
|
|
444
459
|
const MAX_RETRY_ATTEMPTS = 1;
|
|
445
|
-
const
|
|
460
|
+
const url2 = this.buildUrl(path);
|
|
446
461
|
const startTime = requestStartTime ?? Date.now();
|
|
447
462
|
const signal = this.createAbortSignal(init);
|
|
448
463
|
const headers = await this.buildHeaders(init?.headers);
|
|
@@ -467,7 +482,7 @@ var WebHttpClient = class {
|
|
|
467
482
|
headersObj,
|
|
468
483
|
await this.transport.authorizeRequest({
|
|
469
484
|
method,
|
|
470
|
-
path: new URL(
|
|
485
|
+
path: new URL(url2).pathname,
|
|
471
486
|
// Narrowed by the guard above; `BodyInit` is wider than what can be
|
|
472
487
|
// signed.
|
|
473
488
|
body
|
|
@@ -527,7 +542,7 @@ var WebHttpClient = class {
|
|
|
527
542
|
if (this.transport.getProof) {
|
|
528
543
|
const proof = await this.transport.getProof({
|
|
529
544
|
method: requestInit.method ?? "GET",
|
|
530
|
-
path: pathForProof(
|
|
545
|
+
path: pathForProof(url2),
|
|
531
546
|
body: requestInit.body
|
|
532
547
|
});
|
|
533
548
|
if (proof) {
|
|
@@ -535,13 +550,13 @@ var WebHttpClient = class {
|
|
|
535
550
|
}
|
|
536
551
|
}
|
|
537
552
|
try {
|
|
538
|
-
const response = await this.transport.fetch(
|
|
553
|
+
const response = await this.transport.fetch(url2, requestInit);
|
|
539
554
|
if (!response.ok) {
|
|
540
555
|
const bodyText = await this.getBodyText(response);
|
|
541
556
|
const httpError = new HTTPError(
|
|
542
557
|
response.status,
|
|
543
558
|
response.statusText,
|
|
544
|
-
|
|
559
|
+
url2,
|
|
545
560
|
response.headers,
|
|
546
561
|
bodyText
|
|
547
562
|
);
|
|
@@ -559,7 +574,7 @@ var WebHttpClient = class {
|
|
|
559
574
|
authError,
|
|
560
575
|
response.status,
|
|
561
576
|
response.statusText,
|
|
562
|
-
|
|
577
|
+
url2,
|
|
563
578
|
response.headers,
|
|
564
579
|
bodyText
|
|
565
580
|
);
|
|
@@ -624,7 +639,7 @@ var WebHttpClient = class {
|
|
|
624
639
|
throw new HTTPError(
|
|
625
640
|
0,
|
|
626
641
|
"Network Error",
|
|
627
|
-
|
|
642
|
+
url2,
|
|
628
643
|
new Headers(),
|
|
629
644
|
error instanceof Error ? error.message : "Unknown error"
|
|
630
645
|
);
|
|
@@ -727,7 +742,7 @@ function createBrowserHttpClient(options) {
|
|
|
727
742
|
const transport2 = {
|
|
728
743
|
// globalThis.fetch must be called as a method on globalThis, not through a
|
|
729
744
|
// variable, or browsers throw "Illegal invocation".
|
|
730
|
-
fetch: (
|
|
745
|
+
fetch: (url2, init) => options.fetch ? options.fetch(url2, init) : globalThis.fetch(url2, init),
|
|
731
746
|
baseUrl: options.baseUrl,
|
|
732
747
|
getAuthToken: options.getAuthToken,
|
|
733
748
|
getProof: options.getProof,
|
|
@@ -754,7 +769,7 @@ function createNodeHttpClient(options) {
|
|
|
754
769
|
// Wrap fetch in arrow function to prevent "Illegal invocation" error
|
|
755
770
|
// For globalThis.fetch, call it directly to preserve 'this' context
|
|
756
771
|
// For custom implementations, calling through the variable is safe
|
|
757
|
-
fetch: isDefaultFetch ? (
|
|
772
|
+
fetch: isDefaultFetch ? (url2, init) => globalThis.fetch(url2, init) : (url2, init) => fetchImpl(url2, init),
|
|
758
773
|
baseUrl: options.baseUrl,
|
|
759
774
|
getAuthToken: options.getAuthToken,
|
|
760
775
|
getProof: options.getProof,
|
|
@@ -1330,10 +1345,10 @@ function compareSemverId(a, b) {
|
|
|
1330
1345
|
if (nb) return 1;
|
|
1331
1346
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
1332
1347
|
}
|
|
1333
|
-
async function fetchRegistry(
|
|
1348
|
+
async function fetchRegistry(url2, kind, context) {
|
|
1334
1349
|
return withRetry(
|
|
1335
1350
|
async () => {
|
|
1336
|
-
const resp = await fetch(
|
|
1351
|
+
const resp = await fetch(url2, { signal: AbortSignal.timeout(1e4) });
|
|
1337
1352
|
if (!resp.ok) {
|
|
1338
1353
|
const err = new Error(
|
|
1339
1354
|
`registry ${kind} fetch failed (${resp.status}) for ${context}`
|
|
@@ -1385,9 +1400,9 @@ var AdminApiClient = class {
|
|
|
1385
1400
|
* the running `Context.applicationVersion` to detect "a new version exists".
|
|
1386
1401
|
*/
|
|
1387
1402
|
async getRegistryVersions(registryUrl, packageName) {
|
|
1388
|
-
const
|
|
1389
|
-
|
|
1390
|
-
const resp = await fetchRegistry(
|
|
1403
|
+
const url2 = new URL("/api/v2/bundles", new URL(registryUrl).origin);
|
|
1404
|
+
url2.searchParams.set("package", packageName);
|
|
1405
|
+
const resp = await fetchRegistry(url2.toString(), "versions", packageName);
|
|
1391
1406
|
const bundles = await resp.json();
|
|
1392
1407
|
return (Array.isArray(bundles) ? bundles : []).map((b) => b.appVersion).filter((v) => typeof v === "string").sort((a, b) => compareSemver(b, a));
|
|
1393
1408
|
}
|
|
@@ -2705,11 +2720,11 @@ function createAdminApiClientFromHttpClient(httpClient, _config) {
|
|
|
2705
2720
|
}
|
|
2706
2721
|
|
|
2707
2722
|
// src/auth/index.ts
|
|
2708
|
-
function parseAuthCallback(
|
|
2723
|
+
function parseAuthCallback(url2) {
|
|
2709
2724
|
try {
|
|
2710
|
-
const hashIndex =
|
|
2725
|
+
const hashIndex = url2.indexOf("#");
|
|
2711
2726
|
if (hashIndex === -1) return null;
|
|
2712
|
-
const hash =
|
|
2727
|
+
const hash = url2.substring(hashIndex + 1);
|
|
2713
2728
|
const params = new URLSearchParams(hash);
|
|
2714
2729
|
const accessToken = params.get("access_token");
|
|
2715
2730
|
if (!accessToken) return null;
|
|
@@ -3066,7 +3081,7 @@ var SseClient = class {
|
|
|
3066
3081
|
throw new Error("SseClient needs either `getAuthToken` or `authorize`");
|
|
3067
3082
|
}
|
|
3068
3083
|
this.reconnectDelayMs = opts.reconnectDelayMs ?? 3e3;
|
|
3069
|
-
this.fetchImpl = (
|
|
3084
|
+
this.fetchImpl = (url2, init) => opts.fetch ? opts.fetch(url2, init) : globalThis.fetch(url2, init);
|
|
3070
3085
|
}
|
|
3071
3086
|
on(event, handler) {
|
|
3072
3087
|
const key = event;
|
|
@@ -3131,10 +3146,10 @@ var SseClient = class {
|
|
|
3131
3146
|
this.closed = false;
|
|
3132
3147
|
this.abortController = new AbortController();
|
|
3133
3148
|
try {
|
|
3134
|
-
const
|
|
3135
|
-
const response = await this.fetchImpl(
|
|
3149
|
+
const url2 = `${this.baseUrl}/sse`;
|
|
3150
|
+
const response = await this.fetchImpl(url2, {
|
|
3136
3151
|
headers: {
|
|
3137
|
-
...await this.authorize({ method: "GET", path: new URL(
|
|
3152
|
+
...await this.authorize({ method: "GET", path: new URL(url2).pathname }),
|
|
3138
3153
|
"Accept": "text/event-stream"
|
|
3139
3154
|
},
|
|
3140
3155
|
signal: this.abortController.signal
|
|
@@ -3147,7 +3162,7 @@ var SseClient = class {
|
|
|
3147
3162
|
terminal,
|
|
3148
3163
|
response.status,
|
|
3149
3164
|
response.statusText,
|
|
3150
|
-
|
|
3165
|
+
url2,
|
|
3151
3166
|
response.headers,
|
|
3152
3167
|
bodyText
|
|
3153
3168
|
);
|
|
@@ -3155,7 +3170,7 @@ var SseClient = class {
|
|
|
3155
3170
|
throw new HTTPError(
|
|
3156
3171
|
response.status,
|
|
3157
3172
|
response.statusText,
|
|
3158
|
-
|
|
3173
|
+
url2,
|
|
3159
3174
|
response.headers,
|
|
3160
3175
|
bodyText
|
|
3161
3176
|
);
|
|
@@ -3334,12 +3349,12 @@ var SseClient = class {
|
|
|
3334
3349
|
const params = {};
|
|
3335
3350
|
if (ids.contextIds && ids.contextIds.length > 0) params.contextIds = ids.contextIds;
|
|
3336
3351
|
if (ids.groupIds && ids.groupIds.length > 0) params.groupIds = ids.groupIds;
|
|
3337
|
-
const
|
|
3352
|
+
const url2 = `${this.baseUrl}/sse/subscription`;
|
|
3338
3353
|
const body = JSON.stringify({ id: this.sessionId, method, params });
|
|
3339
|
-
const response = await this.fetchImpl(
|
|
3354
|
+
const response = await this.fetchImpl(url2, {
|
|
3340
3355
|
method: "POST",
|
|
3341
3356
|
headers: {
|
|
3342
|
-
...await this.authorize({ method: "POST", path: new URL(
|
|
3357
|
+
...await this.authorize({ method: "POST", path: new URL(url2).pathname, body }),
|
|
3343
3358
|
"Content-Type": "application/json"
|
|
3344
3359
|
},
|
|
3345
3360
|
body,
|
|
@@ -6250,14 +6265,14 @@ function reportDataOf(quote) {
|
|
|
6250
6265
|
}
|
|
6251
6266
|
async function attestRelayNodeKey(opts) {
|
|
6252
6267
|
const nonce2 = crypto.getRandomValues(new Uint8Array(32));
|
|
6253
|
-
const
|
|
6268
|
+
const url2 = `${opts.relayUrl.replace(/\/+$/, "")}/admin-api/tee/attest`;
|
|
6254
6269
|
const body = JSON.stringify({
|
|
6255
6270
|
nonce: hex(nonce2),
|
|
6256
6271
|
bindNodeKey: true,
|
|
6257
6272
|
...opts.verify?.includeCollateral ? { includeCollateral: true } : {}
|
|
6258
6273
|
});
|
|
6259
6274
|
const init = { method: "POST", headers: { "Content-Type": "application/json" }, body };
|
|
6260
|
-
const response = opts.fetch ? await opts.fetch(
|
|
6275
|
+
const response = opts.fetch ? await opts.fetch(url2, init) : await globalThis.fetch(url2, init);
|
|
6261
6276
|
if (!response.ok) {
|
|
6262
6277
|
const text = await response.text().catch(() => "");
|
|
6263
6278
|
throw new Error(`the relay would not attest (HTTP ${response.status})${text ? `: ${text}` : ""}`);
|
|
@@ -6579,13 +6594,13 @@ function createSealedFetch(options) {
|
|
|
6579
6594
|
};
|
|
6580
6595
|
return async (input, init) => {
|
|
6581
6596
|
const request = new Request(input, init);
|
|
6582
|
-
const
|
|
6583
|
-
if (
|
|
6584
|
-
throw new Error(`Refusing to send ${
|
|
6597
|
+
const url2 = new URL(request.url);
|
|
6598
|
+
if (url2.origin !== base.origin || !url2.pathname.startsWith(`${basePath}/`)) {
|
|
6599
|
+
throw new Error(`Refusing to send ${url2.href} outside the sealed node at ${options.baseUrl}`);
|
|
6585
6600
|
}
|
|
6586
6601
|
const headers = [];
|
|
6587
6602
|
request.headers.forEach((value, name) => headers.push([name, value]));
|
|
6588
|
-
const head = { method: request.method, path:
|
|
6603
|
+
const head = { method: request.method, path: url2.pathname.slice(basePath.length) + url2.search, headers };
|
|
6589
6604
|
const body = new Uint8Array(await request.arrayBuffer());
|
|
6590
6605
|
const send = async (open2) => {
|
|
6591
6606
|
const { requestId, header, envelope } = await sealRequest(open2, head, body);
|
|
@@ -6807,7 +6822,7 @@ function createQuoteVerifier(options) {
|
|
|
6807
6822
|
const allowedMrtd = measurements(options.allowedMrtd ?? [], "allowedMrtd");
|
|
6808
6823
|
const allowedImages = (options.allowedMeasurements ?? []).map((image, index) => {
|
|
6809
6824
|
const label2 = `allowedMeasurements[${index}]`;
|
|
6810
|
-
return REGISTERS.map((
|
|
6825
|
+
return REGISTERS.map((register2) => measurements([image?.[register2] ?? ""], `${label2}.${register2}`)[0]).join();
|
|
6811
6826
|
});
|
|
6812
6827
|
const allowedRtmr = [
|
|
6813
6828
|
measurements(options.allowedRtmr0 ?? [], "allowedRtmr0"),
|
|
@@ -6856,7 +6871,7 @@ function createQuoteVerifier(options) {
|
|
|
6856
6871
|
if (td.tdAttributes?.length !== 8 || (td.tdAttributes[0] & 1) !== 0) {
|
|
6857
6872
|
throw new Error("The quote is from a debug TD, or its TD attributes cannot be read");
|
|
6858
6873
|
}
|
|
6859
|
-
const measured = [td.mrTd, td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3].map((
|
|
6874
|
+
const measured = [td.mrTd, td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3].map((register2) => hex(register2));
|
|
6860
6875
|
if (allowedImages.length > 0 && !allowedImages.includes(measured.join())) {
|
|
6861
6876
|
throw new Error(
|
|
6862
6877
|
`The measurements (MRTD ${measured[0]}, RTMR0-3 ${measured.slice(1).join(", ")}) are not an image this verifier trusts`
|
|
@@ -6866,10 +6881,10 @@ function createQuoteVerifier(options) {
|
|
|
6866
6881
|
throw new Error(`MRTD ${measured[0]} is not an image this verifier trusts`);
|
|
6867
6882
|
}
|
|
6868
6883
|
const registers = [td.rtMr0, td.rtMr1, td.rtMr2, td.rtMr3];
|
|
6869
|
-
registers.forEach((
|
|
6884
|
+
registers.forEach((register2, index) => {
|
|
6870
6885
|
const allowed = allowedRtmr[index];
|
|
6871
|
-
if (allowed.length > 0 && !allowed.includes(hex(
|
|
6872
|
-
throw new Error(`RTMR${index} ${hex(
|
|
6886
|
+
if (allowed.length > 0 && !allowed.includes(hex(register2))) {
|
|
6887
|
+
throw new Error(`RTMR${index} ${hex(register2)} is not one this verifier trusts`);
|
|
6873
6888
|
}
|
|
6874
6889
|
});
|
|
6875
6890
|
if (hex(td.reportData) !== `${nonce2}${reportDataSuffix}`.toLowerCase()) {
|
|
@@ -7346,7 +7361,7 @@ async function verifySignedNodeRelease(publishedMrtds, bundle, options = {}) {
|
|
|
7346
7361
|
throw new Error(`The signed release is a ${JSON.stringify(release?.role)} release, not a node one`);
|
|
7347
7362
|
}
|
|
7348
7363
|
const profiles = Object.values(release.profiles ?? {});
|
|
7349
|
-
const measured = (image) => MEASUREMENTS.every((
|
|
7364
|
+
const measured = (image) => MEASUREMENTS.every((register2) => /^[0-9a-f]{96}$/i.test(String(image?.[register2])));
|
|
7350
7365
|
if (typeof release.tag !== "string" || profiles.length === 0 || !profiles.every(measured)) {
|
|
7351
7366
|
throw new Error("The signed file is not a release's published-mrtds.json: it lists no measured profiles");
|
|
7352
7367
|
}
|
|
@@ -7355,17 +7370,17 @@ async function verifySignedNodeRelease(publishedMrtds, bundle, options = {}) {
|
|
|
7355
7370
|
}
|
|
7356
7371
|
return release;
|
|
7357
7372
|
}
|
|
7358
|
-
async function fetchNodeRelease(
|
|
7359
|
-
const response = await (options.fetch ?? fetch)(
|
|
7360
|
-
if (!response.ok) throw new Error(`Fetching the node release from ${
|
|
7373
|
+
async function fetchNodeRelease(url2, options = {}) {
|
|
7374
|
+
const response = await (options.fetch ?? fetch)(url2, { headers: { accept: "application/json" } });
|
|
7375
|
+
if (!response.ok) throw new Error(`Fetching the node release from ${url2} failed: HTTP ${response.status}`);
|
|
7361
7376
|
let release;
|
|
7362
7377
|
try {
|
|
7363
7378
|
release = (await response.json())?.data;
|
|
7364
7379
|
} catch {
|
|
7365
|
-
throw new Error(`${
|
|
7380
|
+
throw new Error(`${url2} did not answer with JSON`);
|
|
7366
7381
|
}
|
|
7367
7382
|
if (typeof release?.version !== "string" || typeof release.publishedMrtds !== "string" || typeof release.bundle !== "string") {
|
|
7368
|
-
throw new Error(`${
|
|
7383
|
+
throw new Error(`${url2} did not answer with a signed node release`);
|
|
7369
7384
|
}
|
|
7370
7385
|
return { version: release.version, publishedMrtds: release.publishedMrtds, bundle: release.bundle };
|
|
7371
7386
|
}
|
|
@@ -7387,20 +7402,20 @@ function infoUrl(baseUrl) {
|
|
|
7387
7402
|
return `${baseUrl.replace(/\/+$/, "")}/admin-api/tee/info`;
|
|
7388
7403
|
}
|
|
7389
7404
|
async function readNodeReleaseVersion(baseUrl, givenFetch) {
|
|
7390
|
-
const
|
|
7391
|
-
const response = await givenFetch(
|
|
7405
|
+
const url2 = infoUrl(baseUrl);
|
|
7406
|
+
const response = await givenFetch(url2, { headers: { accept: "application/json" } });
|
|
7392
7407
|
if (response.status === 403) {
|
|
7393
7408
|
const code = await response.json().then((body) => body?.error?.code).catch(() => void 0);
|
|
7394
7409
|
if (code === "sealed_required") return void 0;
|
|
7395
7410
|
}
|
|
7396
|
-
if (!response.ok) throw new Error(`Fetching ${
|
|
7411
|
+
if (!response.ok) throw new Error(`Fetching ${url2} failed: HTTP ${response.status}`);
|
|
7397
7412
|
let osImage;
|
|
7398
7413
|
try {
|
|
7399
7414
|
osImage = (await response.json())?.data?.osImage;
|
|
7400
7415
|
} catch {
|
|
7401
|
-
throw new Error(`${
|
|
7416
|
+
throw new Error(`${url2} did not answer with JSON`);
|
|
7402
7417
|
}
|
|
7403
|
-
if (typeof osImage !== "string") throw new Error(`${
|
|
7418
|
+
if (typeof osImage !== "string") throw new Error(`${url2} did not name the node's image`);
|
|
7404
7419
|
return nodeReleaseVersionFromImage(osImage);
|
|
7405
7420
|
}
|
|
7406
7421
|
function cloudNodeReleaseUrl(cloudUrl, version) {
|
|
@@ -9010,8 +9025,8 @@ function createProofAuthorizer(credential) {
|
|
|
9010
9025
|
return { [REQUEST_PROOF_HEADER]: proof };
|
|
9011
9026
|
};
|
|
9012
9027
|
}
|
|
9013
|
-
function signedPath(
|
|
9014
|
-
return new URL(
|
|
9028
|
+
function signedPath(url2) {
|
|
9029
|
+
return new URL(url2).pathname;
|
|
9015
9030
|
}
|
|
9016
9031
|
|
|
9017
9032
|
// src/presence/statement.ts
|
|
@@ -9198,7 +9213,7 @@ var MeroClient = class {
|
|
|
9198
9213
|
const authorizeRequest = this.proofAuthorizer;
|
|
9199
9214
|
this.relayAdmin = createAdminApiClientFromHttpClient(
|
|
9200
9215
|
createHttpClient({
|
|
9201
|
-
fetch: (
|
|
9216
|
+
fetch: (url2, init) => fetchImpl ? fetchImpl(url2, init) : globalThis.fetch(url2, init),
|
|
9202
9217
|
baseUrl: relay.relayUrl,
|
|
9203
9218
|
authorizeRequest
|
|
9204
9219
|
}),
|
|
@@ -9841,9 +9856,9 @@ function writeRelayMap(account, map) {
|
|
|
9841
9856
|
}
|
|
9842
9857
|
function rememberRelay(account, relayUrl, at) {
|
|
9843
9858
|
const map = readRelayMap(account);
|
|
9844
|
-
const
|
|
9845
|
-
if (at.namespaceId) map.namespaces[at.namespaceId] =
|
|
9846
|
-
if (at.contextId) map.contexts[at.contextId] =
|
|
9859
|
+
const url2 = relayOrigin(relayUrl);
|
|
9860
|
+
if (at.namespaceId) map.namespaces[at.namespaceId] = url2;
|
|
9861
|
+
if (at.contextId) map.contexts[at.contextId] = url2;
|
|
9847
9862
|
writeRelayMap(account, map);
|
|
9848
9863
|
}
|
|
9849
9864
|
function relayForContext(account, contextId) {
|
|
@@ -10226,7 +10241,7 @@ function beginLinkState(account, returnTo) {
|
|
|
10226
10241
|
if (!ACCOUNT_HEX.test(account)) {
|
|
10227
10242
|
throw new Error("accountId must be 64 lowercase hex characters");
|
|
10228
10243
|
}
|
|
10229
|
-
const
|
|
10244
|
+
const url2 = new URL(returnTo);
|
|
10230
10245
|
const now = Date.now();
|
|
10231
10246
|
const pending = readPending(now);
|
|
10232
10247
|
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
@@ -10235,8 +10250,8 @@ function beginLinkState(account, returnTo) {
|
|
|
10235
10250
|
);
|
|
10236
10251
|
pending[state] = { account, expiresAt: now + LIFETIME_MS };
|
|
10237
10252
|
writePending(Object.fromEntries(Object.entries(pending).slice(-MAX_PENDING)));
|
|
10238
|
-
|
|
10239
|
-
return
|
|
10253
|
+
url2.searchParams.set(STATE_PARAM, state);
|
|
10254
|
+
return url2.toString();
|
|
10240
10255
|
}
|
|
10241
10256
|
function takeLinkState(search) {
|
|
10242
10257
|
const state = new URLSearchParams(search).get(STATE_PARAM);
|
|
@@ -10258,10 +10273,10 @@ function withoutLinkState(search) {
|
|
|
10258
10273
|
// src/cloud/link-redirect.ts
|
|
10259
10274
|
var DEFAULT_CLOUD_WEB_URL = "https://cloud.calimero.network";
|
|
10260
10275
|
function cloudLinkUrl(options) {
|
|
10261
|
-
const
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
return
|
|
10276
|
+
const url2 = new URL(options.cloudWebUrl ?? DEFAULT_CLOUD_WEB_URL);
|
|
10277
|
+
url2.searchParams.set("link-account", options.accountId);
|
|
10278
|
+
url2.searchParams.set("callback-url", beginLinkState(options.accountId, options.returnTo));
|
|
10279
|
+
return url2.toString();
|
|
10265
10280
|
}
|
|
10266
10281
|
function beginCloudLink(options) {
|
|
10267
10282
|
window.location.assign(cloudLinkUrl(options));
|
|
@@ -10317,12 +10332,12 @@ function deviceEnrolmentUrl(options) {
|
|
|
10317
10332
|
assertHex(options.kemPublicKey, "kemPublicKey");
|
|
10318
10333
|
assertSafeReturnTo(options.returnTo);
|
|
10319
10334
|
warnOnForeignCallback(options.returnTo);
|
|
10320
|
-
const
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
if (options.state)
|
|
10325
|
-
return
|
|
10335
|
+
const url2 = new URL(options.walletUrl);
|
|
10336
|
+
url2.searchParams.set(DEVICE_PARAM, options.devicePublicKey);
|
|
10337
|
+
url2.searchParams.set(KEM_PARAM, options.kemPublicKey);
|
|
10338
|
+
url2.searchParams.set(CALLBACK_PARAM, options.returnTo);
|
|
10339
|
+
if (options.state) url2.searchParams.set(STATE_PARAM2, options.state);
|
|
10340
|
+
return url2.toString();
|
|
10326
10341
|
}
|
|
10327
10342
|
function beginDeviceEnrolment(options) {
|
|
10328
10343
|
window.location.assign(deviceEnrolmentUrl(options));
|
|
@@ -10407,17 +10422,17 @@ function warnOnForeignCallback(returnTo) {
|
|
|
10407
10422
|
);
|
|
10408
10423
|
}
|
|
10409
10424
|
function assertSafeReturnTo(returnTo) {
|
|
10410
|
-
let
|
|
10425
|
+
let url2;
|
|
10411
10426
|
try {
|
|
10412
|
-
|
|
10427
|
+
url2 = new URL(returnTo);
|
|
10413
10428
|
} catch {
|
|
10414
10429
|
throw new Error(`returnTo must be an absolute URL, got ${returnTo}`);
|
|
10415
10430
|
}
|
|
10416
|
-
const loopback =
|
|
10417
|
-
if (
|
|
10418
|
-
if (
|
|
10431
|
+
const loopback = url2.hostname === "localhost" || url2.hostname === "127.0.0.1" || url2.hostname === "[::1]" || url2.hostname === "::1";
|
|
10432
|
+
if (url2.protocol === "https:") return;
|
|
10433
|
+
if (url2.protocol === "http:" && loopback) return;
|
|
10419
10434
|
throw new Error(
|
|
10420
|
-
`returnTo must be https:, or http: on localhost \u2014 got ${
|
|
10435
|
+
`returnTo must be https:, or http: on localhost \u2014 got ${url2.protocol}//${url2.hostname}`
|
|
10421
10436
|
);
|
|
10422
10437
|
}
|
|
10423
10438
|
|
|
@@ -10704,8 +10719,8 @@ function joinNonce(account) {
|
|
|
10704
10719
|
const source = createLocalStorageNonceSource(`calimero.delegated.joinnonce.${account}`);
|
|
10705
10720
|
return () => source.next();
|
|
10706
10721
|
}
|
|
10707
|
-
function origin(
|
|
10708
|
-
return
|
|
10722
|
+
function origin(url2) {
|
|
10723
|
+
return url2.replace(/\/+$/, "");
|
|
10709
10724
|
}
|
|
10710
10725
|
async function joinWithNode(input) {
|
|
10711
10726
|
const { account, credential, deviceSecret } = input.credential;
|
|
@@ -10727,11 +10742,11 @@ async function joinWithNode(input) {
|
|
|
10727
10742
|
};
|
|
10728
10743
|
}
|
|
10729
10744
|
const body = { invitation: input.invitation, signedOp };
|
|
10730
|
-
const
|
|
10745
|
+
const url2 = input.admitUrl ?? `${origin(input.nodeUrl)}/admin-api/namespaces/${pathSegment(input.namespaceId)}/admit`;
|
|
10731
10746
|
const doFetch = input.deps?.fetch ?? fetch;
|
|
10732
10747
|
let response;
|
|
10733
10748
|
try {
|
|
10734
|
-
response = await doFetch(
|
|
10749
|
+
response = await doFetch(url2, {
|
|
10735
10750
|
method: "POST",
|
|
10736
10751
|
// No Authorization header and no request proof, deliberately: the route is
|
|
10737
10752
|
// unauthenticated because the joiner's signature is the authorization.
|
|
@@ -10854,8 +10869,8 @@ function selectLatestBundle(bundles) {
|
|
|
10854
10869
|
);
|
|
10855
10870
|
}
|
|
10856
10871
|
async function fetchRegistryBundles(registryUrl, pkg, fetchFn = globalThis.fetch) {
|
|
10857
|
-
const
|
|
10858
|
-
const response = await fetchFn(
|
|
10872
|
+
const url2 = `${registryUrl.replace(/\/+$/, "")}/api/v2/bundles?package=${encodeURIComponent(pkg)}`;
|
|
10873
|
+
const response = await fetchFn(url2, { headers: { Accept: "application/json" } });
|
|
10859
10874
|
if (!response.ok) throw new Error(`the registry has no ${pkg} (HTTP ${response.status})`);
|
|
10860
10875
|
const body = await response.json();
|
|
10861
10876
|
return Array.isArray(body) ? body : [];
|
|
@@ -10895,9 +10910,9 @@ function nextGovernanceNonce(relay, group) {
|
|
|
10895
10910
|
return next;
|
|
10896
10911
|
}
|
|
10897
10912
|
function relayFor(s, namespaceId) {
|
|
10898
|
-
const
|
|
10899
|
-
if (!
|
|
10900
|
-
return
|
|
10913
|
+
const url2 = readRelayMap(s.account).namespaces[namespaceId] ?? s.relayUrl;
|
|
10914
|
+
if (!url2) throw new Error("no relay is known for this namespace, so there is nowhere to send this");
|
|
10915
|
+
return url2.replace(/\/+$/, "");
|
|
10901
10916
|
}
|
|
10902
10917
|
function initArgsOf(params) {
|
|
10903
10918
|
if (!params || params.length === 0) return {};
|
|
@@ -10980,7 +10995,7 @@ async function foundingExecutor(s, relay, fetch2) {
|
|
|
10980
10995
|
const named = s.executorAccount && s.relayUrl?.replace(/\/+$/, "") === relay ? s.executorAccount : null;
|
|
10981
10996
|
if (named) return { executorAccount: named, executorKey: await attestedNodeKey(relay) };
|
|
10982
10997
|
const known = Object.entries(readRelayMap(s.account).namespaces).find(
|
|
10983
|
-
([,
|
|
10998
|
+
([, url2]) => url2.replace(/\/+$/, "") === relay
|
|
10984
10999
|
)?.[0];
|
|
10985
11000
|
if (!known) {
|
|
10986
11001
|
throw new Error(
|
|
@@ -11427,8 +11442,8 @@ function accountHexOrNull(value) {
|
|
|
11427
11442
|
return typeof value === "string" && ACCOUNT_HEX.test(value) ? value : null;
|
|
11428
11443
|
}
|
|
11429
11444
|
var AccountHaRefusedError = class extends HTTPError {
|
|
11430
|
-
constructor(code, status, statusText,
|
|
11431
|
-
super(status, statusText,
|
|
11445
|
+
constructor(code, status, statusText, url2, headers, bodyText) {
|
|
11446
|
+
super(status, statusText, url2, headers, bodyText);
|
|
11432
11447
|
this.code = code;
|
|
11433
11448
|
this.name = "AccountHaRefusedError";
|
|
11434
11449
|
}
|
|
@@ -12745,8 +12760,8 @@ var MeroJs = class {
|
|
|
12745
12760
|
/**
|
|
12746
12761
|
* Parse an auth callback URL hash fragment (static utility)
|
|
12747
12762
|
*/
|
|
12748
|
-
static parseAuthCallback(
|
|
12749
|
-
return parseAuthCallback(
|
|
12763
|
+
static parseAuthCallback(url2) {
|
|
12764
|
+
return parseAuthCallback(url2);
|
|
12750
12765
|
}
|
|
12751
12766
|
/**
|
|
12752
12767
|
* Build an auth login URL (static utility)
|
|
@@ -13011,8 +13026,8 @@ async function probeNodeHealth(baseUrl, options = {}) {
|
|
|
13011
13026
|
if (abortSignal) abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
13012
13027
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
13013
13028
|
try {
|
|
13014
|
-
const
|
|
13015
|
-
const res = await fetch(
|
|
13029
|
+
const url2 = nodeEndpoint(baseUrl, "admin-api/health");
|
|
13030
|
+
const res = await fetch(url2, {
|
|
13016
13031
|
method: "GET",
|
|
13017
13032
|
signal: controller.signal
|
|
13018
13033
|
});
|
|
@@ -13036,11 +13051,445 @@ async function discoverLocalNodes(options = {}) {
|
|
|
13036
13051
|
const { ports = DEFAULT_LOCAL_NODE_PORTS, timeoutMs, signal } = options;
|
|
13037
13052
|
const results = await Promise.all(
|
|
13038
13053
|
ports.map(async (port) => {
|
|
13039
|
-
const
|
|
13040
|
-
const ok = await probeNodeHealth(
|
|
13041
|
-
return ok ?
|
|
13054
|
+
const url2 = localNodeUrl(port);
|
|
13055
|
+
const ok = await probeNodeHealth(url2, { timeoutMs, signal });
|
|
13056
|
+
return ok ? url2 : null;
|
|
13042
13057
|
})
|
|
13043
13058
|
);
|
|
13044
|
-
return results.filter((
|
|
13059
|
+
return results.filter((url2) => url2 !== null);
|
|
13060
|
+
}
|
|
13061
|
+
|
|
13062
|
+
// src/agent-gate/chacha20poly1305.ts
|
|
13063
|
+
var KEY_LEN = 32;
|
|
13064
|
+
var NONCE_LEN = 12;
|
|
13065
|
+
var TAG_LEN2 = 16;
|
|
13066
|
+
function rotl(value, shift) {
|
|
13067
|
+
return (value << shift | value >>> 32 - shift) >>> 0;
|
|
13068
|
+
}
|
|
13069
|
+
function quarterRound(s, a, b, c, d) {
|
|
13070
|
+
s[a] = s[a] + s[b] >>> 0;
|
|
13071
|
+
s[d] = rotl(s[d] ^ s[a], 16);
|
|
13072
|
+
s[c] = s[c] + s[d] >>> 0;
|
|
13073
|
+
s[b] = rotl(s[b] ^ s[c], 12);
|
|
13074
|
+
s[a] = s[a] + s[b] >>> 0;
|
|
13075
|
+
s[d] = rotl(s[d] ^ s[a], 8);
|
|
13076
|
+
s[c] = s[c] + s[d] >>> 0;
|
|
13077
|
+
s[b] = rotl(s[b] ^ s[c], 7);
|
|
13078
|
+
}
|
|
13079
|
+
function u32le2(bytes, offset) {
|
|
13080
|
+
return (bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24) >>> 0;
|
|
13081
|
+
}
|
|
13082
|
+
function chacha20Block(key, counter, nonce2) {
|
|
13083
|
+
const state = new Uint32Array(16);
|
|
13084
|
+
state[0] = 1634760805;
|
|
13085
|
+
state[1] = 857760878;
|
|
13086
|
+
state[2] = 2036477234;
|
|
13087
|
+
state[3] = 1797285236;
|
|
13088
|
+
for (let i = 0; i < 8; i += 1) state[4 + i] = u32le2(key, i * 4);
|
|
13089
|
+
state[12] = counter >>> 0;
|
|
13090
|
+
for (let i = 0; i < 3; i += 1) state[13 + i] = u32le2(nonce2, i * 4);
|
|
13091
|
+
const working = state.slice();
|
|
13092
|
+
for (let round = 0; round < 10; round += 1) {
|
|
13093
|
+
quarterRound(working, 0, 4, 8, 12);
|
|
13094
|
+
quarterRound(working, 1, 5, 9, 13);
|
|
13095
|
+
quarterRound(working, 2, 6, 10, 14);
|
|
13096
|
+
quarterRound(working, 3, 7, 11, 15);
|
|
13097
|
+
quarterRound(working, 0, 5, 10, 15);
|
|
13098
|
+
quarterRound(working, 1, 6, 11, 12);
|
|
13099
|
+
quarterRound(working, 2, 7, 8, 13);
|
|
13100
|
+
quarterRound(working, 3, 4, 9, 14);
|
|
13101
|
+
}
|
|
13102
|
+
const out = new Uint8Array(64);
|
|
13103
|
+
for (let i = 0; i < 16; i += 1) {
|
|
13104
|
+
const word = working[i] + state[i] >>> 0;
|
|
13105
|
+
out[i * 4] = word & 255;
|
|
13106
|
+
out[i * 4 + 1] = word >>> 8 & 255;
|
|
13107
|
+
out[i * 4 + 2] = word >>> 16 & 255;
|
|
13108
|
+
out[i * 4 + 3] = word >>> 24 & 255;
|
|
13109
|
+
}
|
|
13110
|
+
return out;
|
|
13111
|
+
}
|
|
13112
|
+
function chacha20(key, counter, nonce2, data) {
|
|
13113
|
+
const out = new Uint8Array(data.length);
|
|
13114
|
+
for (let offset = 0, block = counter; offset < data.length; offset += 64, block += 1) {
|
|
13115
|
+
const stream = chacha20Block(key, block, nonce2);
|
|
13116
|
+
const end = Math.min(offset + 64, data.length);
|
|
13117
|
+
for (let i = offset; i < end; i += 1) out[i] = data[i] ^ stream[i - offset];
|
|
13118
|
+
}
|
|
13119
|
+
return out;
|
|
13120
|
+
}
|
|
13121
|
+
function leToBigInt(bytes) {
|
|
13122
|
+
let value = 0n;
|
|
13123
|
+
for (let i = bytes.length - 1; i >= 0; i -= 1) value = value << 8n | BigInt(bytes[i]);
|
|
13124
|
+
return value;
|
|
13125
|
+
}
|
|
13126
|
+
var P1305 = (1n << 130n) - 5n;
|
|
13127
|
+
function poly1305(key, message) {
|
|
13128
|
+
const r = leToBigInt(key.subarray(0, 16)) & 0x0ffffffc0ffffffc0ffffffc0fffffffn;
|
|
13129
|
+
const s = leToBigInt(key.subarray(16, 32));
|
|
13130
|
+
let acc = 0n;
|
|
13131
|
+
for (let offset = 0; offset < message.length; offset += 16) {
|
|
13132
|
+
const block = message.subarray(offset, Math.min(offset + 16, message.length));
|
|
13133
|
+
const n = leToBigInt(block) + (1n << BigInt(8 * block.length));
|
|
13134
|
+
acc = (acc + n) * r % P1305;
|
|
13135
|
+
}
|
|
13136
|
+
let tag3 = acc + s & (1n << 128n) - 1n;
|
|
13137
|
+
const out = new Uint8Array(TAG_LEN2);
|
|
13138
|
+
for (let i = 0; i < TAG_LEN2; i += 1) {
|
|
13139
|
+
out[i] = Number(tag3 & 0xffn);
|
|
13140
|
+
tag3 >>= 8n;
|
|
13141
|
+
}
|
|
13142
|
+
return out;
|
|
13143
|
+
}
|
|
13144
|
+
function pad16(length) {
|
|
13145
|
+
return new Uint8Array((16 - length % 16) % 16);
|
|
13146
|
+
}
|
|
13147
|
+
function u64le2(value) {
|
|
13148
|
+
const out = new Uint8Array(8);
|
|
13149
|
+
new DataView(out.buffer).setBigUint64(0, BigInt(value), true);
|
|
13150
|
+
return out;
|
|
13151
|
+
}
|
|
13152
|
+
function macData(aad, ciphertext) {
|
|
13153
|
+
const parts = [aad, pad16(aad.length), ciphertext, pad16(ciphertext.length), u64le2(aad.length), u64le2(ciphertext.length)];
|
|
13154
|
+
const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));
|
|
13155
|
+
let offset = 0;
|
|
13156
|
+
for (const part of parts) {
|
|
13157
|
+
out.set(part, offset);
|
|
13158
|
+
offset += part.length;
|
|
13159
|
+
}
|
|
13160
|
+
return out;
|
|
13161
|
+
}
|
|
13162
|
+
function check(key, nonce2) {
|
|
13163
|
+
if (key.length !== KEY_LEN) throw new Error("ChaCha20-Poly1305 needs a 32-byte key");
|
|
13164
|
+
if (nonce2.length !== NONCE_LEN) throw new Error("ChaCha20-Poly1305 needs a 12-byte nonce");
|
|
13165
|
+
}
|
|
13166
|
+
function chacha20Poly1305Seal(key, nonce2, plaintext, aad = new Uint8Array(0)) {
|
|
13167
|
+
check(key, nonce2);
|
|
13168
|
+
const otk = chacha20Block(key, 0, nonce2).subarray(0, 32);
|
|
13169
|
+
const ciphertext = chacha20(key, 1, nonce2, plaintext);
|
|
13170
|
+
const tag3 = poly1305(otk, macData(aad, ciphertext));
|
|
13171
|
+
const out = new Uint8Array(ciphertext.length + TAG_LEN2);
|
|
13172
|
+
out.set(ciphertext);
|
|
13173
|
+
out.set(tag3, ciphertext.length);
|
|
13174
|
+
return out;
|
|
13175
|
+
}
|
|
13176
|
+
|
|
13177
|
+
// src/agent-gate/hpke.ts
|
|
13178
|
+
var KEM_ID = 32;
|
|
13179
|
+
var KDF_ID = 1;
|
|
13180
|
+
var AEAD_ID = 3;
|
|
13181
|
+
var MODE_AUTH = 2;
|
|
13182
|
+
var N_SECRET = 32;
|
|
13183
|
+
var N_KEY = 32;
|
|
13184
|
+
var N_NONCE = 12;
|
|
13185
|
+
var utf84 = (s) => new TextEncoder().encode(s);
|
|
13186
|
+
var i2osp2 = (n) => new Uint8Array([n >> 8 & 255, n & 255]);
|
|
13187
|
+
var KEM_SUITE = concat(utf84("KEM"), i2osp2(KEM_ID));
|
|
13188
|
+
var HPKE_SUITE = concat(utf84("HPKE"), i2osp2(KEM_ID), i2osp2(KDF_ID), i2osp2(AEAD_ID));
|
|
13189
|
+
async function hmac(key, data) {
|
|
13190
|
+
const raw = key.length === 0 ? new Uint8Array(32) : key;
|
|
13191
|
+
const k = await crypto.subtle.importKey("raw", raw, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
13192
|
+
return new Uint8Array(await crypto.subtle.sign("HMAC", k, data));
|
|
13193
|
+
}
|
|
13194
|
+
async function expand(prk, info, length) {
|
|
13195
|
+
const out = new Uint8Array(length);
|
|
13196
|
+
let previous = new Uint8Array(0);
|
|
13197
|
+
for (let i = 1, offset = 0; offset < length; i += 1) {
|
|
13198
|
+
previous = await hmac(prk, concat(previous, info, new Uint8Array([i])));
|
|
13199
|
+
out.set(previous.subarray(0, Math.min(previous.length, length - offset)), offset);
|
|
13200
|
+
offset += previous.length;
|
|
13201
|
+
}
|
|
13202
|
+
return out;
|
|
13203
|
+
}
|
|
13204
|
+
function labeledExtract(suite, salt, label2, ikm) {
|
|
13205
|
+
return hmac(salt, concat(utf84("HPKE-v1"), suite, utf84(label2), ikm));
|
|
13206
|
+
}
|
|
13207
|
+
function labeledExpand(suite, prk, label2, info, length) {
|
|
13208
|
+
return expand(prk, concat(i2osp2(length), utf84("HPKE-v1"), suite, utf84(label2), info), length);
|
|
13209
|
+
}
|
|
13210
|
+
async function extractAndExpand(dhValue, kemContext) {
|
|
13211
|
+
const prk = await labeledExtract(KEM_SUITE, new Uint8Array(0), "eae_prk", dhValue);
|
|
13212
|
+
return labeledExpand(KEM_SUITE, prk, "shared_secret", kemContext, N_SECRET);
|
|
13213
|
+
}
|
|
13214
|
+
async function keySchedule(sharedSecret, info) {
|
|
13215
|
+
const empty = new Uint8Array(0);
|
|
13216
|
+
const pskIdHash = await labeledExtract(HPKE_SUITE, empty, "psk_id_hash", empty);
|
|
13217
|
+
const infoHash = await labeledExtract(HPKE_SUITE, empty, "info_hash", info);
|
|
13218
|
+
const context = concat(new Uint8Array([MODE_AUTH]), pskIdHash, infoHash);
|
|
13219
|
+
const secret = await labeledExtract(HPKE_SUITE, sharedSecret, "secret", empty);
|
|
13220
|
+
return {
|
|
13221
|
+
key: await labeledExpand(HPKE_SUITE, secret, "key", context, N_KEY),
|
|
13222
|
+
nonce: await labeledExpand(HPKE_SUITE, secret, "base_nonce", context, N_NONCE)
|
|
13223
|
+
};
|
|
13224
|
+
}
|
|
13225
|
+
async function hpkeSealAuth(recipientPublic, senderSecret, info, plaintext, aad = new Uint8Array(0), ephemeralSecret) {
|
|
13226
|
+
if (recipientPublic.length !== 32) throw new Error("The recipient key is not 32 bytes of X25519");
|
|
13227
|
+
const ephemeral = await x25519KeyPair(ephemeralSecret);
|
|
13228
|
+
const sender = await x25519KeyPair(senderSecret);
|
|
13229
|
+
const dhValue = concat(await dh(ephemeral.privateKey, recipientPublic), await dh(sender.privateKey, recipientPublic));
|
|
13230
|
+
const shared = await extractAndExpand(dhValue, concat(ephemeral.publicKey, recipientPublic, sender.publicKey));
|
|
13231
|
+
const { key, nonce: nonce2 } = await keySchedule(shared, info);
|
|
13232
|
+
return { enc: ephemeral.publicKey, ciphertext: chacha20Poly1305Seal(key, nonce2, plaintext, aad) };
|
|
13233
|
+
}
|
|
13234
|
+
|
|
13235
|
+
// src/agent-gate/gate.ts
|
|
13236
|
+
var AGENT_ATTEST_DOMAIN = "mero-agent-gate/attest/v3";
|
|
13237
|
+
var AGENT_PROVISION_INFO_DOMAIN = "mero-agent-gate/provision/v2";
|
|
13238
|
+
var AGENT_ID = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
13239
|
+
var SECRET_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
13240
|
+
var MAX_SECRETS = 64;
|
|
13241
|
+
var MAX_SECRET_LEN = 64 * 1024;
|
|
13242
|
+
var AgentGateError = class extends Error {
|
|
13243
|
+
constructor(message, status, code) {
|
|
13244
|
+
super(message);
|
|
13245
|
+
this.status = status;
|
|
13246
|
+
this.code = code;
|
|
13247
|
+
this.name = "AgentGateError";
|
|
13248
|
+
}
|
|
13249
|
+
};
|
|
13250
|
+
function validateAgentId(agentId) {
|
|
13251
|
+
if (!AGENT_ID.test(agentId)) {
|
|
13252
|
+
throw new Error(`Agent id ${JSON.stringify(agentId)} must match [a-z0-9][a-z0-9-]{0,62}`);
|
|
13253
|
+
}
|
|
13254
|
+
}
|
|
13255
|
+
function utf85(value) {
|
|
13256
|
+
return new TextEncoder().encode(value);
|
|
13257
|
+
}
|
|
13258
|
+
function lengthPrefixed(agentId) {
|
|
13259
|
+
const id = utf85(agentId);
|
|
13260
|
+
return concat(new Uint8Array([id.length]), id);
|
|
13261
|
+
}
|
|
13262
|
+
function toBase64(bytes) {
|
|
13263
|
+
let binary = "";
|
|
13264
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
13265
|
+
return btoa(binary);
|
|
13266
|
+
}
|
|
13267
|
+
function fromBase644(value, label2, length) {
|
|
13268
|
+
let bytes;
|
|
13269
|
+
try {
|
|
13270
|
+
bytes = Uint8Array.from(atob(value.trim()), (c) => c.charCodeAt(0));
|
|
13271
|
+
} catch {
|
|
13272
|
+
throw new Error(`${label2} is not base64`);
|
|
13273
|
+
}
|
|
13274
|
+
if (length !== void 0 && bytes.length !== length) throw new Error(`${label2} is not ${length} bytes`);
|
|
13275
|
+
return bytes;
|
|
13276
|
+
}
|
|
13277
|
+
async function agentKeyBinding(provisioningPublic, agentId, signingPublic, ownerPublic) {
|
|
13278
|
+
const zero = new Uint8Array(32);
|
|
13279
|
+
const data = concat(
|
|
13280
|
+
utf85(AGENT_ATTEST_DOMAIN),
|
|
13281
|
+
provisioningPublic,
|
|
13282
|
+
lengthPrefixed(agentId),
|
|
13283
|
+
signingPublic ?? zero,
|
|
13284
|
+
ownerPublic ?? zero
|
|
13285
|
+
);
|
|
13286
|
+
return new Uint8Array(await crypto.subtle.digest("SHA-256", data));
|
|
13287
|
+
}
|
|
13288
|
+
function provisionInfo(recipientPublic, agentId) {
|
|
13289
|
+
return concat(utf85(AGENT_PROVISION_INFO_DOMAIN), recipientPublic, lengthPrefixed(agentId));
|
|
13290
|
+
}
|
|
13291
|
+
async function generateOwnerKey() {
|
|
13292
|
+
const secret = crypto.getRandomValues(new Uint8Array(32));
|
|
13293
|
+
return { secret, publicKey: await ownerPublicKey(secret) };
|
|
13294
|
+
}
|
|
13295
|
+
async function ownerPublicKey(secret) {
|
|
13296
|
+
if (secret.length !== 32) throw new Error("An owner key is 32 bytes");
|
|
13297
|
+
return toBase64((await x25519KeyPair(secret)).publicKey);
|
|
13298
|
+
}
|
|
13299
|
+
function url(gateUrl, path) {
|
|
13300
|
+
return `${gateUrl.replace(/\/+$/, "")}${path}`;
|
|
13301
|
+
}
|
|
13302
|
+
async function postJson(fetchImpl, target, body) {
|
|
13303
|
+
const response = await fetchImpl(target, {
|
|
13304
|
+
method: "POST",
|
|
13305
|
+
headers: { "content-type": "application/json" },
|
|
13306
|
+
body: JSON.stringify(body)
|
|
13307
|
+
});
|
|
13308
|
+
const text = await response.text();
|
|
13309
|
+
let parsed = void 0;
|
|
13310
|
+
try {
|
|
13311
|
+
parsed = text ? JSON.parse(text) : void 0;
|
|
13312
|
+
} catch {
|
|
13313
|
+
}
|
|
13314
|
+
if (!response.ok) {
|
|
13315
|
+
const error = parsed;
|
|
13316
|
+
throw new AgentGateError(
|
|
13317
|
+
`The gate answered ${response.status}${error?.error ? ` ${error.error}` : ""}: ${error?.details ?? text.slice(0, 200)}`,
|
|
13318
|
+
response.status,
|
|
13319
|
+
error?.error
|
|
13320
|
+
);
|
|
13321
|
+
}
|
|
13322
|
+
return parsed;
|
|
13323
|
+
}
|
|
13324
|
+
async function attestAgent(options) {
|
|
13325
|
+
const agentId = options.agentId ?? "";
|
|
13326
|
+
if (agentId) validateAgentId(agentId);
|
|
13327
|
+
const nonce2 = crypto.getRandomValues(new Uint8Array(32));
|
|
13328
|
+
const body = await postJson(options.fetch ?? fetch, url(options.gateUrl, "/attest"), {
|
|
13329
|
+
nonceB64: toBase64(nonce2),
|
|
13330
|
+
...agentId ? { agentId } : {}
|
|
13331
|
+
});
|
|
13332
|
+
if ((body?.agentId ?? "") !== agentId) {
|
|
13333
|
+
throw new Error(`Asked about agent ${JSON.stringify(agentId)}, the gate answered for ${JSON.stringify(body?.agentId)}`);
|
|
13334
|
+
}
|
|
13335
|
+
const provisioning = fromBase644(body.provisioningPublicKeyB64 ?? "", "provisioningPublicKeyB64", 32);
|
|
13336
|
+
const signing = body.signingPublicKeyB64 ? fromBase644(body.signingPublicKeyB64, "signingPublicKeyB64", 32) : void 0;
|
|
13337
|
+
const owner = body.ownerPublicKeyB64 ? fromBase644(body.ownerPublicKeyB64, "ownerPublicKeyB64", 32) : void 0;
|
|
13338
|
+
if (!signing !== !owner) {
|
|
13339
|
+
throw new Error("A claimed agent has both a signing key and an owner; the gate named one");
|
|
13340
|
+
}
|
|
13341
|
+
const binding = await agentKeyBinding(provisioning, agentId, signing, owner);
|
|
13342
|
+
await options.verifier({ quoteB64: body.quoteB64, nonce: hex(nonce2), reportDataSuffix: hex(binding) });
|
|
13343
|
+
return {
|
|
13344
|
+
agentId,
|
|
13345
|
+
provisioningPublicKey: toBase64(provisioning),
|
|
13346
|
+
...signing ? { signingPublicKey: toBase64(signing) } : {},
|
|
13347
|
+
...owner ? { ownerPublicKey: toBase64(owner) } : {}
|
|
13348
|
+
};
|
|
13349
|
+
}
|
|
13350
|
+
async function checkOwner(agent, ownerSecret) {
|
|
13351
|
+
const mine = await ownerPublicKey(ownerSecret);
|
|
13352
|
+
if (agent.ownerPublicKey && agent.ownerPublicKey !== mine) {
|
|
13353
|
+
throw new AgentGateError(
|
|
13354
|
+
`This agent is claimed by another key (${agent.ownerPublicKey}); it is not yours. Send it nothing and do not authorize its signing key`,
|
|
13355
|
+
void 0,
|
|
13356
|
+
"not_yours"
|
|
13357
|
+
);
|
|
13358
|
+
}
|
|
13359
|
+
return mine;
|
|
13360
|
+
}
|
|
13361
|
+
function validateSecrets(secrets) {
|
|
13362
|
+
const names = Object.keys(secrets);
|
|
13363
|
+
if (names.length === 0) throw new Error("There are no secrets to provision");
|
|
13364
|
+
if (names.length > MAX_SECRETS) throw new Error(`At most ${MAX_SECRETS} secrets at once`);
|
|
13365
|
+
for (const name of names) {
|
|
13366
|
+
if (!SECRET_NAME.test(name)) throw new Error(`Secret name ${JSON.stringify(name)} must match [A-Za-z0-9][A-Za-z0-9_.-]{0,63}`);
|
|
13367
|
+
if (typeof secrets[name] !== "string") throw new Error(`Secret ${name} is not a string`);
|
|
13368
|
+
if (utf85(secrets[name]).length > MAX_SECRET_LEN) throw new Error(`Secret ${name} is over ${MAX_SECRET_LEN} bytes`);
|
|
13369
|
+
}
|
|
13370
|
+
}
|
|
13371
|
+
async function sendSealed(fetchImpl, gateUrl, path, agent, ownerSecret, message) {
|
|
13372
|
+
if (!agent.agentId) throw new Error("This quote names no agent; attest with the agent id");
|
|
13373
|
+
const mine = await checkOwner(agent, ownerSecret);
|
|
13374
|
+
const recipient = fromBase644(agent.provisioningPublicKey, "provisioningPublicKey", 32);
|
|
13375
|
+
const sealed = await hpkeSealAuth(
|
|
13376
|
+
recipient,
|
|
13377
|
+
ownerSecret,
|
|
13378
|
+
provisionInfo(recipient, agent.agentId),
|
|
13379
|
+
utf85(JSON.stringify(message))
|
|
13380
|
+
);
|
|
13381
|
+
return postJson(fetchImpl, url(gateUrl, path), {
|
|
13382
|
+
agentId: agent.agentId,
|
|
13383
|
+
provisioningPublicKeyB64: agent.provisioningPublicKey,
|
|
13384
|
+
senderPublicKeyB64: mine,
|
|
13385
|
+
encappedKeyB64: toBase64(sealed.enc),
|
|
13386
|
+
ciphertextB64: toBase64(sealed.ciphertext)
|
|
13387
|
+
});
|
|
13388
|
+
}
|
|
13389
|
+
async function provisionAgent(options) {
|
|
13390
|
+
validateSecrets(options.secrets);
|
|
13391
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
13392
|
+
const answer = await sendSealed(fetchImpl, options.gateUrl, "/provision", options.agent, options.ownerSecret, {
|
|
13393
|
+
secrets: options.secrets
|
|
13394
|
+
});
|
|
13395
|
+
const after = await attestAgent({ gateUrl: options.gateUrl, agentId: options.agent.agentId, verifier: options.verifier, fetch: fetchImpl });
|
|
13396
|
+
const mine = await ownerPublicKey(options.ownerSecret);
|
|
13397
|
+
if (after.ownerPublicKey !== mine || !after.signingPublicKey) {
|
|
13398
|
+
throw new AgentGateError("The gate accepted the secrets, but its quote does not name your key as owner");
|
|
13399
|
+
}
|
|
13400
|
+
if (options.agent.signingPublicKey && options.agent.signingPublicKey !== after.signingPublicKey) {
|
|
13401
|
+
throw new AgentGateError("The agent's signing key changed while provisioning");
|
|
13402
|
+
}
|
|
13403
|
+
return {
|
|
13404
|
+
agentId: after.agentId,
|
|
13405
|
+
provisioningPublicKey: after.provisioningPublicKey,
|
|
13406
|
+
signingPublicKey: after.signingPublicKey,
|
|
13407
|
+
ownerPublicKey: mine,
|
|
13408
|
+
written: answer?.written ?? [],
|
|
13409
|
+
claimed: answer?.claimed === true
|
|
13410
|
+
};
|
|
13411
|
+
}
|
|
13412
|
+
async function releaseAgent(options) {
|
|
13413
|
+
if (!options.agent.ownerPublicKey) throw new Error("This agent is not claimed; there is nothing to release");
|
|
13414
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
13415
|
+
await sendSealed(fetchImpl, options.gateUrl, "/release", options.agent, options.ownerSecret, { release: true });
|
|
13416
|
+
const after = await attestAgent({ gateUrl: options.gateUrl, agentId: options.agent.agentId, verifier: options.verifier, fetch: fetchImpl });
|
|
13417
|
+
if (after.ownerPublicKey) {
|
|
13418
|
+
throw new AgentGateError("The gate says it released the agent, but its quote still names an owner");
|
|
13419
|
+
}
|
|
13420
|
+
}
|
|
13421
|
+
|
|
13422
|
+
// src/agent-gate/policy.ts
|
|
13423
|
+
var KMS_RELEASE_SIGNER = Object.freeze({
|
|
13424
|
+
identity: "https://github.com/calimero-network/mero-tee/.github/workflows/release-kms.yaml@refs/heads/master",
|
|
13425
|
+
issuer: "https://token.actions.githubusercontent.com"
|
|
13426
|
+
});
|
|
13427
|
+
var LISTS = [
|
|
13428
|
+
"allowed_tcb_statuses",
|
|
13429
|
+
"allowed_mrtd",
|
|
13430
|
+
"allowed_rtmr0",
|
|
13431
|
+
"allowed_rtmr1",
|
|
13432
|
+
"allowed_rtmr2",
|
|
13433
|
+
"allowed_rtmr3"
|
|
13434
|
+
];
|
|
13435
|
+
async function verifySignedAgentPolicy(policy, bundle, options = {}) {
|
|
13436
|
+
const body = typeof policy === "string" ? new TextEncoder().encode(policy) : policy;
|
|
13437
|
+
await verifyCosignBundle(body, bundle, {
|
|
13438
|
+
identity: options.identity ?? KMS_RELEASE_SIGNER.identity,
|
|
13439
|
+
issuer: options.issuer ?? KMS_RELEASE_SIGNER.issuer
|
|
13440
|
+
});
|
|
13441
|
+
let parsed;
|
|
13442
|
+
try {
|
|
13443
|
+
parsed = JSON.parse(new TextDecoder().decode(body));
|
|
13444
|
+
} catch {
|
|
13445
|
+
throw new Error("The signed agent policy is not JSON");
|
|
13446
|
+
}
|
|
13447
|
+
if (parsed?.role !== "agent") {
|
|
13448
|
+
throw new Error(`The signed file is a ${JSON.stringify(parsed?.role)} policy, not an agent one`);
|
|
13449
|
+
}
|
|
13450
|
+
const profile = options.profile ?? PRODUCTION_PROFILE;
|
|
13451
|
+
if (parsed.profile !== profile) {
|
|
13452
|
+
throw new Error(`The signed agent policy is for the ${JSON.stringify(parsed.profile)} profile, not ${profile}`);
|
|
13453
|
+
}
|
|
13454
|
+
if (options.expectedVersion !== void 0 && parsed.version !== options.expectedVersion) {
|
|
13455
|
+
throw new Error(`The signed agent policy is release ${JSON.stringify(parsed.version)}, not ${options.expectedVersion}`);
|
|
13456
|
+
}
|
|
13457
|
+
checkLists(parsed);
|
|
13458
|
+
return parsed;
|
|
13459
|
+
}
|
|
13460
|
+
function checkLists(policy) {
|
|
13461
|
+
for (const list of LISTS) {
|
|
13462
|
+
if (!Array.isArray(policy?.[list]) || policy[list].length === 0) {
|
|
13463
|
+
throw new Error(`The agent policy's ${list} is empty, so no agent would be accepted`);
|
|
13464
|
+
}
|
|
13465
|
+
}
|
|
13466
|
+
}
|
|
13467
|
+
var TCB_STATUSES2 = [
|
|
13468
|
+
"UpToDate",
|
|
13469
|
+
"SWHardeningNeeded",
|
|
13470
|
+
"ConfigurationNeeded",
|
|
13471
|
+
"ConfigurationAndSWHardeningNeeded",
|
|
13472
|
+
"OutOfDate",
|
|
13473
|
+
"OutOfDateConfigurationNeeded"
|
|
13474
|
+
];
|
|
13475
|
+
function tcbStatus2(value) {
|
|
13476
|
+
const found = TCB_STATUSES2.find((status) => status.toLowerCase() === value.trim().toLowerCase());
|
|
13477
|
+
if (!found) throw new Error(`The agent policy allows an unknown TCB status ${JSON.stringify(value)}`);
|
|
13478
|
+
return found;
|
|
13479
|
+
}
|
|
13480
|
+
var register = (value) => value.trim().replace(/^0x/i, "");
|
|
13481
|
+
function agentQuoteVerifier(policy, options) {
|
|
13482
|
+
checkLists(policy);
|
|
13483
|
+
return createQuoteVerifier({
|
|
13484
|
+
dcapVerify: options.dcapVerify,
|
|
13485
|
+
fetchCollateral: options.fetchCollateral,
|
|
13486
|
+
now: options.now,
|
|
13487
|
+
allowedTcbStatuses: policy.allowed_tcb_statuses.map(tcbStatus2),
|
|
13488
|
+
allowedMrtd: policy.allowed_mrtd.map(register),
|
|
13489
|
+
allowedRtmr0: policy.allowed_rtmr0.map(register),
|
|
13490
|
+
allowedRtmr1: policy.allowed_rtmr1.map(register),
|
|
13491
|
+
allowedRtmr2: policy.allowed_rtmr2.map(register),
|
|
13492
|
+
allowedRtmr3: policy.allowed_rtmr3.map(register)
|
|
13493
|
+
});
|
|
13045
13494
|
}
|
|
13046
13495
|
//# sourceMappingURL=index.cjs.map
|