@antseed/antseed-verifier 0.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.
Files changed (83) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +86 -0
  3. package/dist/adapters/aci.d.ts +4 -0
  4. package/dist/adapters/aci.d.ts.map +1 -0
  5. package/dist/adapters/aci.js +42 -0
  6. package/dist/adapters/aci.js.map +1 -0
  7. package/dist/adapters/chutes.d.ts +4 -0
  8. package/dist/adapters/chutes.d.ts.map +1 -0
  9. package/dist/adapters/chutes.js +72 -0
  10. package/dist/adapters/chutes.js.map +1 -0
  11. package/dist/adapters/index.d.ts +26 -0
  12. package/dist/adapters/index.d.ts.map +1 -0
  13. package/dist/adapters/index.js +19 -0
  14. package/dist/adapters/index.js.map +1 -0
  15. package/dist/antseed-node-types.d.ts +55 -0
  16. package/dist/antseed-node-types.d.ts.map +1 -0
  17. package/dist/antseed-node-types.js +8 -0
  18. package/dist/antseed-node-types.js.map +1 -0
  19. package/dist/capability.d.ts +50 -0
  20. package/dist/capability.d.ts.map +1 -0
  21. package/dist/capability.js +15 -0
  22. package/dist/capability.js.map +1 -0
  23. package/dist/caps/gpu-nvidia.d.ts +66 -0
  24. package/dist/caps/gpu-nvidia.d.ts.map +1 -0
  25. package/dist/caps/gpu-nvidia.js +142 -0
  26. package/dist/caps/gpu-nvidia.js.map +1 -0
  27. package/dist/caps/index.d.ts +7 -0
  28. package/dist/caps/index.d.ts.map +1 -0
  29. package/dist/caps/index.js +21 -0
  30. package/dist/caps/index.js.map +1 -0
  31. package/dist/caps/measured-image.d.ts +14 -0
  32. package/dist/caps/measured-image.d.ts.map +1 -0
  33. package/dist/caps/measured-image.js +46 -0
  34. package/dist/caps/measured-image.js.map +1 -0
  35. package/dist/caps/provider-claims.d.ts +52 -0
  36. package/dist/caps/provider-claims.d.ts.map +1 -0
  37. package/dist/caps/provider-claims.js +195 -0
  38. package/dist/caps/provider-claims.js.map +1 -0
  39. package/dist/caps/seller-bound.d.ts +9 -0
  40. package/dist/caps/seller-bound.d.ts.map +1 -0
  41. package/dist/caps/seller-bound.js +104 -0
  42. package/dist/caps/seller-bound.js.map +1 -0
  43. package/dist/caps/tee-tdx.d.ts +107 -0
  44. package/dist/caps/tee-tdx.d.ts.map +1 -0
  45. package/dist/caps/tee-tdx.js +210 -0
  46. package/dist/caps/tee-tdx.js.map +1 -0
  47. package/dist/collect/configfs.d.ts +6 -0
  48. package/dist/collect/configfs.d.ts.map +1 -0
  49. package/dist/collect/configfs.js +38 -0
  50. package/dist/collect/configfs.js.map +1 -0
  51. package/dist/collect/dstack.d.ts +8 -0
  52. package/dist/collect/dstack.d.ts.map +1 -0
  53. package/dist/collect/dstack.js +79 -0
  54. package/dist/collect/dstack.js.map +1 -0
  55. package/dist/collect/http.d.ts +25 -0
  56. package/dist/collect/http.d.ts.map +1 -0
  57. package/dist/collect/http.js +83 -0
  58. package/dist/collect/http.js.map +1 -0
  59. package/dist/index.d.ts +33 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +40 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/nras.d.ts +81 -0
  64. package/dist/nras.d.ts.map +1 -0
  65. package/dist/nras.js +190 -0
  66. package/dist/nras.js.map +1 -0
  67. package/dist/prover.d.ts +5 -0
  68. package/dist/prover.d.ts.map +1 -0
  69. package/dist/prover.js +204 -0
  70. package/dist/prover.js.map +1 -0
  71. package/dist/report-data.d.ts +47 -0
  72. package/dist/report-data.d.ts.map +1 -0
  73. package/dist/report-data.js +111 -0
  74. package/dist/report-data.js.map +1 -0
  75. package/dist/shared.d.ts +89 -0
  76. package/dist/shared.d.ts.map +1 -0
  77. package/dist/shared.js +158 -0
  78. package/dist/shared.js.map +1 -0
  79. package/dist/verifier.d.ts +21 -0
  80. package/dist/verifier.d.ts.map +1 -0
  81. package/dist/verifier.js +149 -0
  82. package/dist/verifier.js.map +1 -0
  83. package/package.json +42 -0
@@ -0,0 +1,104 @@
1
+ import { secp256k1 } from '@noble/curves/secp256k1.js';
2
+ import { keccak_256 } from '@noble/hashes/sha3.js';
3
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils.js';
4
+ import { bundleDigest, claimId, normalizePeerId, parseEvidenceConfigKey, sellerBoundPreimage } from '../shared.js';
5
+ /**
6
+ * Capability 'seller-bound': turns provider verification into seller verification. The
7
+ * seller signs the seller-bound preimage (keccak256 over nonce ‖ bundleDigest ‖ peerId)
8
+ * with its AntSeed identity key, where bundleDigest covers every other cap's evidence
9
+ * (the node quote and the provider quote together). The buyer recovers the signer's EVM
10
+ * address and requires it to equal the peer id. Freshness (nonce) and identity (peerId)
11
+ * live here, independent of what any quote's own report_data binds. One seller signature
12
+ * therefore ties the whole bundle to this seller and this round.
13
+ */
14
+ const CAP_ID = 'seller-bound';
15
+ /** Recover the 40-hex (lowercase, no 0x) EVM address that produced an r‖s‖v signature. */
16
+ export function recoverEvmAddress(digest, sig) {
17
+ if (sig.length !== 65)
18
+ throw new Error(`signature must be 65 bytes, got ${sig.length}`);
19
+ const recovery = sig[64] >= 27 ? sig[64] - 27 : sig[64];
20
+ if (recovery !== 0 && recovery !== 1)
21
+ throw new Error(`invalid recovery byte: ${sig[64]}`);
22
+ // noble's recovered format is v(1) ‖ r(32) ‖ s(32); repack our r‖s‖v into it.
23
+ const noble = new Uint8Array(65);
24
+ noble[0] = recovery;
25
+ noble.set(sig.subarray(0, 64), 1);
26
+ const compressed = secp256k1.recoverPublicKey(noble, digest, { prehash: false });
27
+ const uncompressed = secp256k1.Point.fromBytes(compressed).toBytes(false); // 0x04 ‖ X ‖ Y
28
+ return bytesToHex(keccak_256(uncompressed.subarray(1)).subarray(-20));
29
+ }
30
+ /** Build a signer over 32-byte digests from a hex private key; it emits r‖s‖v (v = 27/28). */
31
+ export function signerFromPrivateKey(privHex) {
32
+ const priv = hexToBytes(privHex.replace(/^0x/i, ''));
33
+ if (priv.length !== 32)
34
+ throw new Error(`private key must be 32 bytes, got ${priv.length}`);
35
+ return async (msg) => {
36
+ // prehash:false — msg is already the 32-byte keccak preimage digest, sign it directly.
37
+ const recovered = secp256k1.sign(msg, priv, { prehash: false, format: 'recovered' });
38
+ const out = new Uint8Array(65);
39
+ out.set(recovered.subarray(1), 0); // r ‖ s
40
+ out[64] = recovered[0] + 27; // v
41
+ return out;
42
+ };
43
+ }
44
+ /** The 40-hex EVM address a private key corresponds to (for seller-side consistency checks). */
45
+ export function evmAddressFromPrivateKey(privHex) {
46
+ const priv = hexToBytes(privHex.replace(/^0x/i, ''));
47
+ const uncompressed = secp256k1.getPublicKey(priv, false);
48
+ return bytesToHex(keccak_256(uncompressed.subarray(1)).subarray(-20));
49
+ }
50
+ export const sellerBoundCapability = {
51
+ id: CAP_ID,
52
+ verify(input) {
53
+ const claim = claimId(CAP_ID);
54
+ if (!input.evidence)
55
+ return { claim, ok: false, detail: 'seller returned no identity signature' };
56
+ const bundle = input.evidenceBundle;
57
+ if (!bundle)
58
+ return { claim, ok: false, detail: 'seller-bound requires the evidence bundle to bind to' };
59
+ // bundleDigest excludes seller-bound's own entry; require at least one other cap to cover.
60
+ if (Object.keys(bundle).filter((id) => id !== CAP_ID).length === 0) {
61
+ return { claim, ok: false, detail: 'seller-bound has no other evidence to bind to' };
62
+ }
63
+ let peerId;
64
+ try {
65
+ peerId = normalizePeerId(input.peerId);
66
+ }
67
+ catch (err) {
68
+ return { claim, ok: false, detail: err instanceof Error ? err.message : String(err) };
69
+ }
70
+ const preimage = sellerBoundPreimage(input.nonce, bundleDigest(bundle), peerId);
71
+ let signer;
72
+ try {
73
+ signer = recoverEvmAddress(preimage, input.evidence);
74
+ }
75
+ catch (err) {
76
+ return { claim, ok: false, detail: `signature recovery failed: ${err instanceof Error ? err.message : String(err)}` };
77
+ }
78
+ if (signer !== peerId) {
79
+ return { claim, ok: false, detail: `signer ${signer.slice(0, 10)}… does not match peer ${peerId.slice(0, 10)}…` };
80
+ }
81
+ return { claim, ok: true, detail: `seller identity ${peerId.slice(0, 10)}… signed this bundle (fresh nonce bound)` };
82
+ },
83
+ async collect(input) {
84
+ if (!input.sign)
85
+ throw new Error('seller-bound requires a signer (seller identity key); not offered');
86
+ // Rebuild the bundle from every other cap's evidence the prover already collected this
87
+ // round (exposed as "evidence:<capId>" config entries). Collect it last, so the node and
88
+ // provider quotes are already present.
89
+ const bundle = {};
90
+ for (const [key, b64] of Object.entries(input.config)) {
91
+ const capId = parseEvidenceConfigKey(key);
92
+ if (capId && capId !== CAP_ID)
93
+ bundle[capId] = new Uint8Array(Buffer.from(b64, 'base64'));
94
+ }
95
+ if (Object.keys(bundle).length === 0)
96
+ throw new Error('seller-bound requires other cap evidence to bind to; collect a TEE cap first');
97
+ const preimage = sellerBoundPreimage(input.nonce, bundleDigest(bundle), input.peerId);
98
+ const sig = await input.sign(preimage);
99
+ if (sig.length !== 65)
100
+ throw new Error(`signer returned ${sig.length}-byte signature, expected 65 (r‖s‖v)`);
101
+ return sig;
102
+ },
103
+ };
104
+ //# sourceMappingURL=seller-bound.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seller-bound.js","sourceRoot":"","sources":["../../src/caps/seller-bound.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import type { Capability } from '../capability.js';
2
+ import { type BindingIngredients } from '../report-data.js';
3
+ /** A provider quote's declared report_data binding: a frozen scheme id + its string ingredients. */
4
+ export interface ReportDataBinding {
5
+ scheme: string;
6
+ ingredients: Pick<BindingIngredients, 'peerId' | 'e2ePubkey' | 'keysetDigest'>;
7
+ }
8
+ /**
9
+ * A genuine-Intel-TDX capability: proves a party runs in a genuine Intel TDX enclave.
10
+ * It DCAP-verifies the quote (ECDSA sig + PCK chain to Intel's root + TCB), requires an
11
+ * acceptable TCB, requires a TDX (TD10) quote, and requires TDX debug off. It also parses
12
+ * the authenticated measurements (MRTD, RTMR0-3, report_data) into a shared ParsedTdxQuote,
13
+ * so dependent caps (measured-image) reuse the same verified quote instead of re-parsing
14
+ * untrusted bytes.
15
+ *
16
+ * The one factory below (makeTdxCap) mints two instances. They differ only by id, collector
17
+ * source, and evidence key: the AntSeed seller node's own TEE (configfs), and the downstream
18
+ * inference provider's TEE (http). Same verify logic; independent evidence.
19
+ */
20
+ /** The AntSeed seller node's own TEE (mints its quote locally via configfs). */
21
+ export declare const NODE_TEE_CAP_ID = "seller-node-tee-genuine";
22
+ /** The downstream inference provider's TEE (quote fetched from the provider's evidence route). */
23
+ export declare const PROVIDER_TEE_CAP_ID = "seller-provider-tee-genuine";
24
+ /**
25
+ * Config-key convention: each TDX cap reads its own collector settings from `<capId>.<key>`
26
+ * in the shared config map, so the node cap and the provider cap never collide. It lives in
27
+ * one place, so the prover writes the same keys the factory reads.
28
+ */
29
+ export declare function tdxConfigKey(id: string, key: string): string;
30
+ /**
31
+ * TCB acceptance. UpToDate is always genuine hardware. SWHardeningNeeded flags guest-side
32
+ * software mitigations only — not a hardware compromise — and is accepted by default (real
33
+ * GCP TDX quotes often report it). Set ANTSEED_VERIFIER_STRICT_TCB=true to require UpToDate
34
+ * exactly. Anything else (OutOfDate, Revoked, Unknown, ...) is rejected.
35
+ */
36
+ export declare function isTcbAcceptable(status: string): boolean;
37
+ /** Authenticated TD10 measurements, extracted from a verified quote. */
38
+ export interface TdMeasurements {
39
+ mrTd: Uint8Array;
40
+ rtMr0: Uint8Array;
41
+ rtMr1: Uint8Array;
42
+ rtMr2: Uint8Array;
43
+ rtMr3: Uint8Array;
44
+ reportData: Uint8Array;
45
+ /** TUD.DEBUG (tdAttributes bit 0); null if not determinable. */
46
+ debug: boolean | null;
47
+ }
48
+ /** Raw output of a DCAP check — status + measurements (td null when not a TDX quote). */
49
+ export interface RawTdxVerification {
50
+ status: string;
51
+ td: TdMeasurements | null;
52
+ }
53
+ /** Injectable DCAP check — the default verifies for real; tests inject a stub. */
54
+ export type VerifyQuoteFn = (quote: Uint8Array, collateral: unknown | undefined, nowSecs: number) => Promise<RawTdxVerification>;
55
+ /**
56
+ * The shared, verified quote given to every capability for this attestation round.
57
+ * `quoteEvidence` is always the exact tee-tdx evidence bytes the seller returned (so
58
+ * seller-bound can hash the same bytes). `td` is present only when DCAP parsing yields
59
+ * a TDX report.
60
+ */
61
+ export interface ParsedTdxQuote {
62
+ quoteEvidence: Uint8Array;
63
+ status: string;
64
+ td: TdMeasurements | null;
65
+ /** The provider-declared report_data binding, if the evidence carried one. */
66
+ binding?: ReportDataBinding;
67
+ /** Set when DCAP verification or evidence decoding threw. */
68
+ error?: string;
69
+ }
70
+ export declare function encodeTeeTdxEvidence(quote: Uint8Array, collateral?: unknown, binding?: ReportDataBinding): Uint8Array;
71
+ export declare function decodeTeeTdxEvidence(bytes: Uint8Array): {
72
+ quote: Uint8Array;
73
+ collateral?: unknown;
74
+ binding?: ReportDataBinding;
75
+ };
76
+ /**
77
+ * Default DCAP verifier: it validates the quote's ECDSA signature + PCK cert chain to
78
+ * Intel's production root CA + TCB, and reads the TD10 measurements. It uses the seller's
79
+ * collateral when supplied; otherwise it fetches collateral from a public PCCS. @phala/dcap-qvl
80
+ * is imported lazily so the seller/prover half never loads it.
81
+ */
82
+ export declare const defaultVerifyQuote: VerifyQuoteFn;
83
+ /**
84
+ * DCAP-verify the tee-tdx evidence and build the shared ParsedTdxQuote. It never throws:
85
+ * decode or verify errors are captured in `error`, so dependent caps still see the raw
86
+ * `quoteEvidence` bytes (seller-bound only needs those to bind identity to the quote).
87
+ */
88
+ export declare function verifyTdxEvidence(evidence: Uint8Array, verifyQuote: VerifyQuoteFn, nowSecs: number): Promise<ParsedTdxQuote>;
89
+ /**
90
+ * Mint one TDX capability. `id` names the target (node or provider); `defaultSource`
91
+ * is the collector used when config supplies no `<id>.source` override:
92
+ * 'configfs': self-hosted TDX minted locally via configfs-tsm; report_data = antseed-rd-v1 {peerId}
93
+ * 'dstack' : self-hosted TDX minted via the dstack guest-agent socket (Phala CVMs, where
94
+ * configfs-tsm is absent); same antseed-rd-v1 {peerId} report_data as configfs
95
+ * 'http' : a pre-made quote fetched from a config-supplied evidence route ({nonce} hex)
96
+ * verify reads this cap's own parsed quote (the orchestrator DCAP-verifies each cap's
97
+ * own evidence entry independently). collect throws when its source is unavailable
98
+ * (off-TEE for configfs, or no url for http), so the prover omits the cap.
99
+ */
100
+ export declare function makeTdxCap(id: string, defaultSource: 'configfs' | 'http', opts?: {
101
+ bindNoncePeerId?: boolean;
102
+ }): Capability;
103
+ /** The AntSeed seller node's own TEE — mints its quote locally via configfs; report_data bound to nonce+peerId. */
104
+ export declare const nodeTeeCapability: Capability;
105
+ /** The downstream inference provider's TEE — quote fetched from the provider's evidence route. */
106
+ export declare const providerTeeCapability: Capability;
107
+ //# sourceMappingURL=tee-tdx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tee-tdx.d.ts","sourceRoot":"","sources":["../../src/caps/tee-tdx.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAiD,MAAM,kBAAkB,CAAA;AAKjG,OAAO,EAAiC,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE1F,oGAAoG;AACpG,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,WAAW,GAAG,cAAc,CAAC,CAAA;CAC/E;AAED;;;;;;;;;;;GAWG;AAEH,gFAAgF;AAChF,eAAO,MAAM,eAAe,4BAA4B,CAAA;AACxD,kGAAkG;AAClG,eAAO,MAAM,mBAAmB,gCAAgC,CAAA;AAEhE;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,EAAE,UAAU,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;IACtB,gEAAgE;IAChE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACtB;AAED,yFAAyF;AACzF,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,EAAE,cAAc,GAAG,IAAI,CAAA;CAC1B;AAED,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,CAC1B,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,OAAO,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEhC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,UAAU,CAAA;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,EAAE,cAAc,GAAG,IAAI,CAAA;IACzB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AASD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAOrH;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAAE,CAchI;AAED;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAqBhC,CAAA;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,UAAU,EACpB,WAAW,EAAE,aAAa,EAC1B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,CAezB;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,MAAM,EACV,aAAa,EAAE,UAAU,GAAG,MAAM,EAClC,IAAI,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACnC,UAAU,CAgEZ;AAED,mHAAmH;AACnH,eAAO,MAAM,iBAAiB,YAAqE,CAAA;AACnG,kGAAkG;AAClG,eAAO,MAAM,qBAAqB,YAA0C,CAAA"}
@@ -0,0 +1,210 @@
1
+ import { claimId, computeReportData } from '../shared.js';
2
+ import { generateTdxQuote } from '../collect/configfs.js';
3
+ import { generateDstackQuote } from '../collect/dstack.js';
4
+ import { collectViaHttp, collectTdxAndPubkey } from '../collect/http.js';
5
+ import { antseedRdV1, verifyReportData } from '../report-data.js';
6
+ /**
7
+ * A genuine-Intel-TDX capability: proves a party runs in a genuine Intel TDX enclave.
8
+ * It DCAP-verifies the quote (ECDSA sig + PCK chain to Intel's root + TCB), requires an
9
+ * acceptable TCB, requires a TDX (TD10) quote, and requires TDX debug off. It also parses
10
+ * the authenticated measurements (MRTD, RTMR0-3, report_data) into a shared ParsedTdxQuote,
11
+ * so dependent caps (measured-image) reuse the same verified quote instead of re-parsing
12
+ * untrusted bytes.
13
+ *
14
+ * The one factory below (makeTdxCap) mints two instances. They differ only by id, collector
15
+ * source, and evidence key: the AntSeed seller node's own TEE (configfs), and the downstream
16
+ * inference provider's TEE (http). Same verify logic; independent evidence.
17
+ */
18
+ /** The AntSeed seller node's own TEE (mints its quote locally via configfs). */
19
+ export const NODE_TEE_CAP_ID = 'seller-node-tee-genuine';
20
+ /** The downstream inference provider's TEE (quote fetched from the provider's evidence route). */
21
+ export const PROVIDER_TEE_CAP_ID = 'seller-provider-tee-genuine';
22
+ /**
23
+ * Config-key convention: each TDX cap reads its own collector settings from `<capId>.<key>`
24
+ * in the shared config map, so the node cap and the provider cap never collide. It lives in
25
+ * one place, so the prover writes the same keys the factory reads.
26
+ */
27
+ export function tdxConfigKey(id, key) {
28
+ return `${id}.${key}`;
29
+ }
30
+ /**
31
+ * TCB acceptance. UpToDate is always genuine hardware. SWHardeningNeeded flags guest-side
32
+ * software mitigations only — not a hardware compromise — and is accepted by default (real
33
+ * GCP TDX quotes often report it). Set ANTSEED_VERIFIER_STRICT_TCB=true to require UpToDate
34
+ * exactly. Anything else (OutOfDate, Revoked, Unknown, ...) is rejected.
35
+ */
36
+ export function isTcbAcceptable(status) {
37
+ if (status === 'UpToDate')
38
+ return true;
39
+ if (status === 'SWHardeningNeeded')
40
+ return process.env['ANTSEED_VERIFIER_STRICT_TCB'] !== 'true';
41
+ return false;
42
+ }
43
+ export function encodeTeeTdxEvidence(quote, collateral, binding) {
44
+ const blob = {
45
+ quote: Buffer.from(quote).toString('base64'),
46
+ ...(collateral !== undefined ? { collateral } : {}),
47
+ ...(binding !== undefined ? { binding } : {}),
48
+ };
49
+ return new TextEncoder().encode(JSON.stringify(blob));
50
+ }
51
+ export function decodeTeeTdxEvidence(bytes) {
52
+ const parsed = JSON.parse(new TextDecoder().decode(bytes));
53
+ if (typeof parsed.quote !== 'string' || parsed.quote.length === 0) {
54
+ throw new Error('tee-tdx evidence missing "quote"');
55
+ }
56
+ const quote = new Uint8Array(Buffer.from(parsed.quote, 'base64'));
57
+ if (quote.length === 0) {
58
+ throw new Error('tee-tdx evidence "quote" is not valid base64');
59
+ }
60
+ return {
61
+ quote,
62
+ ...(parsed.collateral !== undefined ? { collateral: parsed.collateral } : {}),
63
+ ...(parsed.binding !== undefined ? { binding: parsed.binding } : {}),
64
+ };
65
+ }
66
+ /**
67
+ * Default DCAP verifier: it validates the quote's ECDSA signature + PCK cert chain to
68
+ * Intel's production root CA + TCB, and reads the TD10 measurements. It uses the seller's
69
+ * collateral when supplied; otherwise it fetches collateral from a public PCCS. @phala/dcap-qvl
70
+ * is imported lazily so the seller/prover half never loads it.
71
+ */
72
+ export const defaultVerifyQuote = async (quote, collateral, nowSecs) => {
73
+ const mod = (await import('@phala/dcap-qvl'));
74
+ const dcap = mod.default ?? mod;
75
+ const verified = collateral !== undefined
76
+ ? dcap.verify(Buffer.from(quote), collateral, nowSecs)
77
+ : await dcap.getCollateralAndVerify(Buffer.from(quote));
78
+ const td = verified.report.asTd10();
79
+ if (!td)
80
+ return { status: verified.status, td: null };
81
+ return {
82
+ status: verified.status,
83
+ td: {
84
+ mrTd: td.mrTd,
85
+ rtMr0: td.rtMr0,
86
+ rtMr1: td.rtMr1,
87
+ rtMr2: td.rtMr2,
88
+ rtMr3: td.rtMr3,
89
+ reportData: td.reportData,
90
+ debug: td.tdAttributes.length > 0 ? (td.tdAttributes[0] & 0x01) === 1 : null,
91
+ },
92
+ };
93
+ };
94
+ /**
95
+ * DCAP-verify the tee-tdx evidence and build the shared ParsedTdxQuote. It never throws:
96
+ * decode or verify errors are captured in `error`, so dependent caps still see the raw
97
+ * `quoteEvidence` bytes (seller-bound only needs those to bind identity to the quote).
98
+ */
99
+ export async function verifyTdxEvidence(evidence, verifyQuote, nowSecs) {
100
+ let quote;
101
+ let collateral;
102
+ let binding;
103
+ try {
104
+ ;
105
+ ({ quote, collateral, binding } = decodeTeeTdxEvidence(evidence));
106
+ }
107
+ catch (err) {
108
+ return { quoteEvidence: evidence, status: '', td: null, error: `malformed tee-tdx evidence: ${msg(err)}` };
109
+ }
110
+ try {
111
+ const raw = await verifyQuote(quote, collateral, nowSecs);
112
+ return { quoteEvidence: evidence, status: raw.status, td: raw.td, ...(binding ? { binding } : {}) };
113
+ }
114
+ catch (err) {
115
+ return { quoteEvidence: evidence, status: '', td: null, ...(binding ? { binding } : {}), error: `quote verification failed: ${msg(err)}` };
116
+ }
117
+ }
118
+ function msg(err) {
119
+ return err instanceof Error ? err.message : String(err);
120
+ }
121
+ function hex(b) {
122
+ return Buffer.from(b).toString('hex');
123
+ }
124
+ /**
125
+ * Mint one TDX capability. `id` names the target (node or provider); `defaultSource`
126
+ * is the collector used when config supplies no `<id>.source` override:
127
+ * 'configfs': self-hosted TDX minted locally via configfs-tsm; report_data = antseed-rd-v1 {peerId}
128
+ * 'dstack' : self-hosted TDX minted via the dstack guest-agent socket (Phala CVMs, where
129
+ * configfs-tsm is absent); same antseed-rd-v1 {peerId} report_data as configfs
130
+ * 'http' : a pre-made quote fetched from a config-supplied evidence route ({nonce} hex)
131
+ * verify reads this cap's own parsed quote (the orchestrator DCAP-verifies each cap's
132
+ * own evidence entry independently). collect throws when its source is unavailable
133
+ * (off-TEE for configfs, or no url for http), so the prover omits the cap.
134
+ */
135
+ export function makeTdxCap(id, defaultSource, opts) {
136
+ return {
137
+ id,
138
+ verify(input) {
139
+ const claim = claimId(id);
140
+ if (!input.evidence)
141
+ return { claim, ok: false, detail: 'seller returned no TDX quote' };
142
+ const p = input.parsedQuote;
143
+ if (!p)
144
+ return { claim, ok: false, detail: 'TDX quote was not verified' };
145
+ if (p.error)
146
+ return { claim, ok: false, detail: p.error };
147
+ if (!isTcbAcceptable(p.status))
148
+ return { claim, ok: false, detail: `TCB status not acceptable: ${p.status || 'unknown'}` };
149
+ if (!p.td)
150
+ return { claim, ok: false, detail: 'quote is not an Intel TDX quote' };
151
+ if (p.td.debug === true)
152
+ return { claim, ok: false, detail: 'TDX debug mode is enabled' };
153
+ // Bind report_data to this round: the node cap to its {peerId} identity, a provider cap
154
+ // to whatever frozen scheme its evidence declares. Fail-closed — a borrowed, relayed, or
155
+ // stale quote cannot match a fresh-nonce commitment. A provider quote with no declared
156
+ // scheme still passes on genuineness, but its detail must disclose that freshness was not proven.
157
+ const binding = opts?.bindNoncePeerId
158
+ ? { scheme: antseedRdV1.id, ingredients: { peerId: input.peerId } }
159
+ : p.binding;
160
+ if (binding) {
161
+ const bad = verifyReportData(binding.scheme, p.td.reportData, input.nonce, binding.ingredients);
162
+ if (bad)
163
+ return { claim, ok: false, detail: bad };
164
+ }
165
+ const freshness = binding
166
+ ? `bound to this round (${binding.scheme})`
167
+ : 'freshness/instance binding NOT verified (no report_data scheme declared)';
168
+ return {
169
+ claim,
170
+ ok: true,
171
+ detail: `genuine Intel TDX quote (TCB ${p.status}); MRTD ${hex(p.td.mrTd).slice(0, 16)}…; ${freshness}`,
172
+ };
173
+ },
174
+ async collect(input) {
175
+ const source = input.config[tdxConfigKey(id, 'source')] ?? defaultSource;
176
+ if (source === 'configfs') {
177
+ const quote = generateTdxQuote(computeReportData(input.nonce, input.peerId));
178
+ return encodeTeeTdxEvidence(quote);
179
+ }
180
+ if (source === 'dstack') {
181
+ const socket = input.config[tdxConfigKey(id, 'dstack.socket')] || undefined;
182
+ const quote = await generateDstackQuote(computeReportData(input.nonce, input.peerId), socket);
183
+ return encodeTeeTdxEvidence(quote);
184
+ }
185
+ if (source === 'http') {
186
+ const url = input.config[tdxConfigKey(id, 'url')];
187
+ if (!url)
188
+ throw new Error(`${id} http source requires an evidence url; not offered`);
189
+ const field = input.config[tdxConfigKey(id, 'field')] ?? 'quote';
190
+ const scheme = input.config[tdxConfigKey(id, 'binding.scheme')];
191
+ if (!scheme) {
192
+ return encodeTeeTdxEvidence(await collectViaHttp(url, input.nonce, field));
193
+ }
194
+ // Declare the provider's frozen report_data scheme and its ingredients (e.g. the E2E
195
+ // pubkey) so the buyer can verify the quote is bound to this round. Both come from one
196
+ // fetch, so the quote and the pubkey are from the same response (no cross-fetch skew).
197
+ const pubkeyField = input.config[tdxConfigKey(id, 'binding.pubkeyField')];
198
+ const { quote, pubkey } = await collectTdxAndPubkey(url, input.nonce, field, pubkeyField);
199
+ const ingredients = pubkey ? { e2ePubkey: pubkey } : {};
200
+ return encodeTeeTdxEvidence(quote, undefined, { scheme, ingredients });
201
+ }
202
+ throw new Error(`unknown ${id} source "${source}" (expected "configfs", "dstack", or "http")`);
203
+ },
204
+ };
205
+ }
206
+ /** The AntSeed seller node's own TEE — mints its quote locally via configfs; report_data bound to nonce+peerId. */
207
+ export const nodeTeeCapability = makeTdxCap(NODE_TEE_CAP_ID, 'configfs', { bindNoncePeerId: true });
208
+ /** The downstream inference provider's TEE — quote fetched from the provider's evidence route. */
209
+ export const providerTeeCapability = makeTdxCap(PROVIDER_TEE_CAP_ID, 'http');
210
+ //# sourceMappingURL=tee-tdx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tee-tdx.js","sourceRoot":"","sources":["../../src/caps/tee-tdx.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAA2B,MAAM,mBAAmB,CAAA;AAQ1F;;;;;;;;;;;GAWG;AAEH,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAA;AACxD,kGAAkG;AAClG,MAAM,CAAC,MAAM,mBAAmB,GAAG,6BAA6B,CAAA;AAEhE;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,GAAW;IAClD,OAAO,GAAG,EAAE,IAAI,GAAG,EAAE,CAAA;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,IAAI,CAAA;IACtC,IAAI,MAAM,KAAK,mBAAmB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,KAAK,MAAM,CAAA;IAChG,OAAO,KAAK,CAAA;AACd,CAAC;AAkDD,MAAM,UAAU,oBAAoB,CAAC,KAAiB,EAAE,UAAoB,EAAE,OAA2B;IACvG,MAAM,IAAI,GAAmB;QAC3B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC5C,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9C,CAAA;IACD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;AACvD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAiB;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAA4B,CAAA;IACrF,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACrD,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IACjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAA;IACjE,CAAC;IACD,OAAO;QACL,KAAK;QACL,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAkB,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;IAEpF,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAA8B,CAAA;IAC1E,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAA;IAC/B,MAAM,QAAQ,GAAG,UAAU,KAAK,SAAS;QACvC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,UAAmB,EAAE,OAAO,CAAC;QAC/D,CAAC,CAAC,MAAM,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACzD,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAA;IACnC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA;IACrD,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,EAAE,EAAE;YACF,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,UAAU,EAAE,EAAE,CAAC,UAAU;YACzB,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;SAC9E;KACF,CAAA;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAoB,EACpB,WAA0B,EAC1B,OAAe;IAEf,IAAI,KAAiB,CAAA;IACrB,IAAI,UAAmB,CAAA;IACvB,IAAI,OAAsC,CAAA;IAC1C,IAAI,CAAC;QACH,CAAC;QAAA,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAA;IACpE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,+BAA+B,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAA;IAC5G,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;QACzD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IACrG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,8BAA8B,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAA;IAC5I,CAAC;AACH,CAAC;AAED,SAAS,GAAG,CAAC,GAAY;IACvB,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,SAAS,GAAG,CAAC,CAAa;IACxB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACvC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CACxB,EAAU,EACV,aAAkC,EAClC,IAAoC;IAEpC,OAAO;QACL,EAAE;QAEF,MAAM,CAAC,KAA4B;YACjC,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,CAAA;YACzB,IAAI,CAAC,KAAK,CAAC,QAAQ;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAA;YACxF,MAAM,CAAC,GAAG,KAAK,CAAC,WAAyC,CAAA;YACzD,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,4BAA4B,EAAE,CAAA;YACzE,IAAI,CAAC,CAAC,KAAK;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;YACzD,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,CAAC,CAAC,MAAM,IAAI,SAAS,EAAE,EAAE,CAAA;YAC1H,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAA;YACjF,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI;gBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAA;YACzF,wFAAwF;YACxF,yFAAyF;YACzF,uFAAuF;YACvF,kGAAkG;YAClG,MAAM,OAAO,GAAkC,IAAI,EAAE,eAAe;gBAClE,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE;gBACnE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YACb,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;gBAC/F,IAAI,GAAG;oBAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;YACnD,CAAC;YACD,MAAM,SAAS,GAAG,OAAO;gBACvB,CAAC,CAAC,wBAAwB,OAAO,CAAC,MAAM,GAAG;gBAC3C,CAAC,CAAC,0EAA0E,CAAA;YAC9E,OAAO;gBACL,KAAK;gBACL,EAAE,EAAE,IAAI;gBACR,MAAM,EAAE,gCAAgC,CAAC,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,SAAS,EAAE;aACxG,CAAA;QACH,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,KAA6B;YACzC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,IAAI,aAAa,CAAA;YACxE,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAG,gBAAgB,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;gBAC5E,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAA;YACpC,CAAC;YACD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACxB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC,IAAI,SAAS,CAAA;gBAC3E,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;gBAC7F,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAA;YACpC,CAAC;YACD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;gBACjD,IAAI,CAAC,GAAG;oBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,oDAAoD,CAAC,CAAA;gBACpF,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,IAAI,OAAO,CAAA;gBAChE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAA;gBAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,OAAO,oBAAoB,CAAC,MAAM,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;gBAC5E,CAAC;gBACD,qFAAqF;gBACrF,uFAAuF;gBACvF,uFAAuF;gBACvF,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAA;gBACzE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBACzF,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;gBACvD,OAAO,oBAAoB,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAA;YACxE,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,WAAW,EAAE,YAAY,MAAM,8CAA8C,CAAC,CAAA;QAChG,CAAC;KACF,CAAA;AACH,CAAC;AAED,mHAAmH;AACnH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC,eAAe,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAA;AACnG,kGAAkG;AAClG,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Generate a raw Intel TDX quote bound to `reportData` (64 bytes) via configfs-tsm: mkdir a
3
+ * report entry, write REPORTDATA to `inblob`, read the assembled quote from `outblob`, rmdir.
4
+ */
5
+ export declare function generateTdxQuote(reportData: Uint8Array): Uint8Array;
6
+ //# sourceMappingURL=configfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configfs.d.ts","sourceRoot":"","sources":["../../src/collect/configfs.ts"],"names":[],"mappings":"AAYA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAoBnE"}
@@ -0,0 +1,38 @@
1
+ import { mkdirSync, writeFileSync, readFileSync, rmdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { randomBytes } from 'node:crypto';
4
+ /**
5
+ * Self-hosted TDX collector: it mints a quote locally via the Linux configfs-TSM report
6
+ * interface (kernel >= 6.7). The interface is present inside a real Intel TDX guest (e.g. a
7
+ * GCP confidential VM) and absent elsewhere, so this throws off-TEE. The prover uses that to
8
+ * detect it cannot offer the tee-tdx capability via this source.
9
+ */
10
+ const TSM_REPORT_DIR = '/sys/kernel/config/tsm/report';
11
+ /**
12
+ * Generate a raw Intel TDX quote bound to `reportData` (64 bytes) via configfs-tsm: mkdir a
13
+ * report entry, write REPORTDATA to `inblob`, read the assembled quote from `outblob`, rmdir.
14
+ */
15
+ export function generateTdxQuote(reportData) {
16
+ if (reportData.length !== 64) {
17
+ throw new Error(`reportData must be 64 bytes, got ${reportData.length}`);
18
+ }
19
+ const entry = join(TSM_REPORT_DIR, `antseed-${randomBytes(8).toString('hex')}`);
20
+ mkdirSync(entry);
21
+ try {
22
+ writeFileSync(join(entry, 'inblob'), Buffer.from(reportData));
23
+ const quote = readFileSync(join(entry, 'outblob'));
24
+ if (quote.length === 0) {
25
+ throw new Error('configfs-tsm outblob was empty (quote generation produced no bytes)');
26
+ }
27
+ return new Uint8Array(quote);
28
+ }
29
+ finally {
30
+ try {
31
+ rmdirSync(entry);
32
+ }
33
+ catch {
34
+ // best-effort cleanup; the entry is a one-shot configfs dir
35
+ }
36
+ }
37
+ }
38
+ //# sourceMappingURL=configfs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configfs.js","sourceRoot":"","sources":["../../src/collect/configfs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC;;;;;GAKG;AACH,MAAM,cAAc,GAAG,+BAA+B,CAAA;AAEtD;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAsB;IACrD,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,oCAAoC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;IAC1E,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC/E,SAAS,CAAC,KAAK,CAAC,CAAA;IAChB,IAAI,CAAC;QACH,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;QAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAA;QAClD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAA;QACxF,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,CAAA;IAC9B,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,SAAS,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;QAC9D,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generate a raw Intel TDX quote bound to `reportData` (64 bytes) via the dstack guest agent.
3
+ * `socketPath` overrides the default locations (e.g. a custom mount or the dstack simulator).
4
+ * It throws when no socket answers or the agent errors. The prover treats that as "cannot offer
5
+ * this source" and omits the capability, like configfs off-TEE.
6
+ */
7
+ export declare function generateDstackQuote(reportData: Uint8Array, socketPath?: string): Promise<Uint8Array>;
8
+ //# sourceMappingURL=dstack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dstack.d.ts","sourceRoot":"","sources":["../../src/collect/dstack.ts"],"names":[],"mappings":"AAmDA;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAyB1G"}
@@ -0,0 +1,79 @@
1
+ import { request } from 'node:http';
2
+ /**
3
+ * dstack collector: it mints a TDX quote via the dstack guest-agent unix socket. This is the
4
+ * canonical quoting path inside dstack CVMs (e.g. Phala), where the Linux configfs-tsm
5
+ * interface is not exposed. It POSTs the 64-byte report_data (hex) to GetQuote, which uses it
6
+ * raw (no hashing, max 64 bytes). The quote's report_data is then byte-identical to the configfs
7
+ * path, and the buyer verifies it unchanged.
8
+ *
9
+ * Wire contract (POST http://dstack/GetQuote over the socket):
10
+ * request { "report_data": "<hex, <=64 bytes>" }
11
+ * response { "quote": "<hex>", "event_log": ..., ... }
12
+ */
13
+ /** Default guest-agent socket locations, tried in order (mirrors @phala/dstack-sdk). */
14
+ const DEFAULT_DSTACK_SOCKETS = ['/var/run/dstack.sock', '/run/dstack.sock'];
15
+ const DSTACK_TIMEOUT_MS = 20_000;
16
+ function msg(err) {
17
+ return err instanceof Error ? err.message : String(err);
18
+ }
19
+ /** Connection-level failure (socket absent or refused) — try the next candidate, do not abort. */
20
+ function isConnError(err) {
21
+ const code = err?.code;
22
+ return code === 'ENOENT' || code === 'ECONNREFUSED' || code === 'EACCES';
23
+ }
24
+ /** POST JSON to a unix-socket HTTP server and read the whole response body. */
25
+ function postUnix(socketPath, path, body) {
26
+ return new Promise((resolve, reject) => {
27
+ const req = request({
28
+ socketPath,
29
+ path,
30
+ method: 'POST',
31
+ headers: { 'content-type': 'application/json', 'content-length': Buffer.byteLength(body) },
32
+ timeout: DSTACK_TIMEOUT_MS,
33
+ }, (res) => {
34
+ const chunks = [];
35
+ res.on('data', (c) => chunks.push(c));
36
+ res.on('end', () => resolve({ status: res.statusCode ?? 0, body: Buffer.concat(chunks).toString('utf8') }));
37
+ });
38
+ req.on('error', reject);
39
+ req.on('timeout', () => req.destroy(new Error('dstack request timed out')));
40
+ req.end(body);
41
+ });
42
+ }
43
+ /**
44
+ * Generate a raw Intel TDX quote bound to `reportData` (64 bytes) via the dstack guest agent.
45
+ * `socketPath` overrides the default locations (e.g. a custom mount or the dstack simulator).
46
+ * It throws when no socket answers or the agent errors. The prover treats that as "cannot offer
47
+ * this source" and omits the capability, like configfs off-TEE.
48
+ */
49
+ export async function generateDstackQuote(reportData, socketPath) {
50
+ if (reportData.length !== 64) {
51
+ throw new Error(`reportData must be 64 bytes, got ${reportData.length}`);
52
+ }
53
+ const body = JSON.stringify({ report_data: Buffer.from(reportData).toString('hex') });
54
+ const candidates = socketPath ? [socketPath] : DEFAULT_DSTACK_SOCKETS;
55
+ let lastErr;
56
+ for (const sock of candidates) {
57
+ try {
58
+ const { status, body: resp } = await postUnix(sock, '/GetQuote', body);
59
+ if (status !== 200)
60
+ throw new Error(`dstack GetQuote returned HTTP ${status}`);
61
+ const parsed = JSON.parse(resp);
62
+ if (typeof parsed.quote !== 'string' || parsed.quote.length === 0) {
63
+ throw new Error('dstack GetQuote response missing "quote"');
64
+ }
65
+ const quote = Buffer.from(parsed.quote.replace(/^0x/, ''), 'hex');
66
+ if (quote.length === 0)
67
+ throw new Error('dstack GetQuote "quote" is not valid hex');
68
+ return new Uint8Array(quote);
69
+ }
70
+ catch (err) {
71
+ lastErr = err;
72
+ if (isConnError(err))
73
+ continue; // this socket is not there — try the next candidate
74
+ throw new Error(`dstack quote generation failed: ${msg(err)}`);
75
+ }
76
+ }
77
+ throw new Error(`dstack guest agent not reachable at ${candidates.join(', ')}: ${msg(lastErr)}`);
78
+ }
79
+ //# sourceMappingURL=dstack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dstack.js","sourceRoot":"","sources":["../../src/collect/dstack.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Generic HTTP collector: it fetches a TDX quote from a seller-configured attestation endpoint.
3
+ * Everything provider-specific (host, path, JSON location of the quote) comes from the caller
4
+ * — no hardcoded hosts or schemas — so any HTTP attestation service wires up through config
5
+ * alone. The {nonce} placeholder in `urlTemplate` is replaced with the hex nonce. `field` is a
6
+ * dot-path to the base64 quote in the response (e.g. "quote" or "data.quote").
7
+ */
8
+ /**
9
+ * Fetch the provider evidence route once. It returns the base64-decoded quote and, when a pubkey
10
+ * field is named, the report_data-binding pubkey string. One fetch keeps the quote and the pubkey
11
+ * from the same response — a two-fetch split could pair a quote with a different instance's key.
12
+ */
13
+ export declare function collectTdxAndPubkey(urlTemplate: string, nonce: Uint8Array, quoteField: string, pubkeyField?: string): Promise<{
14
+ quote: Uint8Array;
15
+ pubkey?: string;
16
+ }>;
17
+ export declare function collectViaHttp(urlTemplate: string, nonce: Uint8Array, field: string): Promise<Uint8Array>;
18
+ /**
19
+ * Like collectViaHttp, but it returns the extracted field re-encoded as JSON bytes instead of
20
+ * base64-decoding it. Why separate: the TDX path wants a lone base64 quote decoded to raw bytes;
21
+ * the GPU path's field holds a structured value (e.g. { arch, evidence_list }) whose shape must
22
+ * survive intact to the NRAS submit, so the code keeps it as JSON rather than decode it.
23
+ */
24
+ export declare function collectJsonFieldViaHttp(urlTemplate: string, nonce: Uint8Array, field: string): Promise<Uint8Array>;
25
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/collect/http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+BH;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBjD;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,CAAC,CAOrB"}