privateer-agent 0.15.4 → 0.15.6

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 (229) hide show
  1. package/README.md +11 -0
  2. package/bin/boot-bundle.d.mts +2 -0
  3. package/bin/boot-bundle.mjs +44 -0
  4. package/bin/fresh-supervisor.d.mts +5 -1
  5. package/bin/fresh-supervisor.mjs +47 -10
  6. package/bin/privateer-launch.mjs +27 -3
  7. package/bin/privateer-subagent.mjs +5 -2
  8. package/bin/privateer-verify.mjs +12 -0
  9. package/bin/session-recovery.d.mts +53 -0
  10. package/bin/session-recovery.mjs +240 -0
  11. package/bin/session-seal-preload.mjs +17 -0
  12. package/bin/session-seal.d.mts +25 -0
  13. package/bin/session-seal.mjs +242 -0
  14. package/dist-boot/boot.mjs +3 -0
  15. package/dist-boot/c-27JKSMWL.mjs +1460 -0
  16. package/dist-boot/c-2BMRFV24.mjs +269 -0
  17. package/dist-boot/c-2CTF6JA3.mjs +166 -0
  18. package/dist-boot/c-2G3BBHRJ.mjs +84 -0
  19. package/dist-boot/c-2IDLKXX6.mjs +250 -0
  20. package/dist-boot/c-2NJD5VYM.mjs +8 -0
  21. package/dist-boot/c-2S5EEQPW.mjs +1602 -0
  22. package/dist-boot/c-2WRDCUVI.mjs +25 -0
  23. package/dist-boot/c-2YN3M256.mjs +14 -0
  24. package/dist-boot/c-37GM3GMU.mjs +187 -0
  25. package/dist-boot/c-3STKRSVO.mjs +2480 -0
  26. package/dist-boot/c-3TPV6TQQ.mjs +2320 -0
  27. package/dist-boot/c-3UVHLQDJ.mjs +225 -0
  28. package/dist-boot/c-42PUUZYC.mjs +697 -0
  29. package/dist-boot/c-4D5UMWVW.mjs +683 -0
  30. package/dist-boot/c-4ETZRMTA.mjs +46 -0
  31. package/dist-boot/c-4QT25BD5.mjs +1482 -0
  32. package/dist-boot/c-4WVR32AP.mjs +2579 -0
  33. package/dist-boot/c-5EMM567G.mjs +152 -0
  34. package/dist-boot/c-5FA4CV63.mjs +145 -0
  35. package/dist-boot/c-5GV3X3RB.mjs +14 -0
  36. package/dist-boot/c-5JCEPRIY.mjs +52 -0
  37. package/dist-boot/c-5NDKIIWT.mjs +16 -0
  38. package/dist-boot/c-5QL3AR26.mjs +4665 -0
  39. package/dist-boot/c-5XY6MFKN.mjs +5142 -0
  40. package/dist-boot/c-65UZIZC7.mjs +2897 -0
  41. package/dist-boot/c-6FUXKHOK.mjs +1969 -0
  42. package/dist-boot/c-6JHWQE4V.mjs +18242 -0
  43. package/dist-boot/c-6LOBR4I6.mjs +5280 -0
  44. package/dist-boot/c-6QHOZXKQ.mjs +14394 -0
  45. package/dist-boot/c-6ZO2SADQ.mjs +178 -0
  46. package/dist-boot/c-6ZORVVZP.mjs +1449 -0
  47. package/dist-boot/c-76QH4UCP.mjs +2441 -0
  48. package/dist-boot/c-77GO5L5Y.mjs +20982 -0
  49. package/dist-boot/c-7M23XFTN.mjs +5052 -0
  50. package/dist-boot/c-7TC367E2.mjs +32 -0
  51. package/dist-boot/c-7UOG7POX.mjs +1524 -0
  52. package/dist-boot/c-7VHP3FLN.mjs +376 -0
  53. package/dist-boot/c-A73JHZP2.mjs +13207 -0
  54. package/dist-boot/c-ABXULAFL.mjs +71 -0
  55. package/dist-boot/c-ANDD2AQO.mjs +74 -0
  56. package/dist-boot/c-AOY77AZL.mjs +1430 -0
  57. package/dist-boot/c-AXEPZ22I.mjs +108 -0
  58. package/dist-boot/c-B2Y7VNHU.mjs +427 -0
  59. package/dist-boot/c-B7VJUH73.mjs +77 -0
  60. package/dist-boot/c-BFW6CDVL.mjs +24 -0
  61. package/dist-boot/c-BHNIF2AR.mjs +188 -0
  62. package/dist-boot/c-BKF2O6BL.mjs +23 -0
  63. package/dist-boot/c-BOZXFTZN.mjs +8 -0
  64. package/dist-boot/c-BRNYJWZL.mjs +28 -0
  65. package/dist-boot/c-C3N4Z2HO.mjs +93 -0
  66. package/dist-boot/c-C4IV7ZFG.mjs +717 -0
  67. package/dist-boot/c-C5NK6UYV.mjs +793 -0
  68. package/dist-boot/c-C67644MB.mjs +1659 -0
  69. package/dist-boot/c-C6S2YB53.mjs +620 -0
  70. package/dist-boot/c-CDBEJSBF.mjs +37 -0
  71. package/dist-boot/c-CG47HBKU.mjs +435 -0
  72. package/dist-boot/c-CKCTWCT5.mjs +51 -0
  73. package/dist-boot/c-CN77DCGF.mjs +60 -0
  74. package/dist-boot/c-CRBXNKFO.mjs +1795 -0
  75. package/dist-boot/c-CRIHASQ6.mjs +973 -0
  76. package/dist-boot/c-CU4NGAUO.mjs +3786 -0
  77. package/dist-boot/c-CWRFLGQU.mjs +1883 -0
  78. package/dist-boot/c-CYQB2USO.mjs +32 -0
  79. package/dist-boot/c-DEE67DJO.mjs +379 -0
  80. package/dist-boot/c-DIFDBYOP.mjs +1258 -0
  81. package/dist-boot/c-DOSGVXDZ.mjs +34879 -0
  82. package/dist-boot/c-DR7XQI32.mjs +381 -0
  83. package/dist-boot/c-DTGPSB46.mjs +14666 -0
  84. package/dist-boot/c-DTHDNA4P.mjs +320 -0
  85. package/dist-boot/c-E4Z3Y5B5.mjs +3864 -0
  86. package/dist-boot/c-E66Z2TI7.mjs +203 -0
  87. package/dist-boot/c-EBU6RLRV.mjs +1527 -0
  88. package/dist-boot/c-EBZZNGSF.mjs +432 -0
  89. package/dist-boot/c-EC3LJ2KF.mjs +1032 -0
  90. package/dist-boot/c-EQBKXWNX.mjs +15829 -0
  91. package/dist-boot/c-EUEPIW4S.mjs +574 -0
  92. package/dist-boot/c-EX4YVWAT.mjs +378 -0
  93. package/dist-boot/c-EYZGSAJU.mjs +98 -0
  94. package/dist-boot/c-F75VRKY4.mjs +172 -0
  95. package/dist-boot/c-FH4NXKHV.mjs +177 -0
  96. package/dist-boot/c-FHNUCTEM.mjs +140 -0
  97. package/dist-boot/c-FJ5T42DS.mjs +5349 -0
  98. package/dist-boot/c-FPCNRL7G.mjs +1728 -0
  99. package/dist-boot/c-G4DLN7Q4.mjs +8 -0
  100. package/dist-boot/c-G56GYQFZ.mjs +2507 -0
  101. package/dist-boot/c-GLIOERDQ.mjs +1200 -0
  102. package/dist-boot/c-GMJ5HUBM.mjs +14 -0
  103. package/dist-boot/c-H3HSGMAQ.mjs +461 -0
  104. package/dist-boot/c-HIKTO6P7.mjs +275 -0
  105. package/dist-boot/c-I2MCJ34O.mjs +464 -0
  106. package/dist-boot/c-I3C6LBW4.mjs +765 -0
  107. package/dist-boot/c-I54OKQHW.mjs +387 -0
  108. package/dist-boot/c-IFSP3R4D.mjs +80 -0
  109. package/dist-boot/c-IZK77VB7.mjs +171 -0
  110. package/dist-boot/c-J3Y25UGE.mjs +54 -0
  111. package/dist-boot/c-J5IESS7W.mjs +27750 -0
  112. package/dist-boot/c-JJWZBY7L.mjs +254 -0
  113. package/dist-boot/c-JKTFXTGF.mjs +463 -0
  114. package/dist-boot/c-JN57AXQ4.mjs +77 -0
  115. package/dist-boot/c-KFIO6LUW.mjs +1096 -0
  116. package/dist-boot/c-KIEMEFWW.mjs +478 -0
  117. package/dist-boot/c-KIVXWBYD.mjs +28 -0
  118. package/dist-boot/c-KP6CRIP4.mjs +580 -0
  119. package/dist-boot/c-L26VOJX4.mjs +11558 -0
  120. package/dist-boot/c-L5GHWG5G.mjs +5988 -0
  121. package/dist-boot/c-M7NSQAKK.mjs +353 -0
  122. package/dist-boot/c-MCEWOPBW.mjs +56 -0
  123. package/dist-boot/c-MGPIEG7I.mjs +20 -0
  124. package/dist-boot/c-NREXJV3M.mjs +393 -0
  125. package/dist-boot/c-O5PP6CTX.mjs +162 -0
  126. package/dist-boot/c-OBQDHSXM.mjs +1774 -0
  127. package/dist-boot/c-OLQHHDD4.mjs +21 -0
  128. package/dist-boot/c-OXW4JQQH.mjs +319 -0
  129. package/dist-boot/c-P3D7ZUWN.mjs +1288 -0
  130. package/dist-boot/c-P4PQZVV5.mjs +948 -0
  131. package/dist-boot/c-P63T3XL2.mjs +26373 -0
  132. package/dist-boot/c-P6N5DQGZ.mjs +194 -0
  133. package/dist-boot/c-P7MLKQFC.mjs +58 -0
  134. package/dist-boot/c-PB3PZJL5.mjs +1276 -0
  135. package/dist-boot/c-PTN4S6G2.mjs +1259 -0
  136. package/dist-boot/c-PYCE5J7U.mjs +1083 -0
  137. package/dist-boot/c-Q4HYCRLB.mjs +19410 -0
  138. package/dist-boot/c-QUXMETGG.mjs +68 -0
  139. package/dist-boot/c-RDMJZCOX.mjs +356 -0
  140. package/dist-boot/c-ROGJK76M.mjs +17 -0
  141. package/dist-boot/c-RQJJ26T4.mjs +708 -0
  142. package/dist-boot/c-RSKCUPJF.mjs +7559 -0
  143. package/dist-boot/c-RVJU4O6P.mjs +37 -0
  144. package/dist-boot/c-S2RVHR3M.mjs +165 -0
  145. package/dist-boot/c-SKMK3PEE.mjs +91120 -0
  146. package/dist-boot/c-TI7SM4EG.mjs +20 -0
  147. package/dist-boot/c-TILJ6GXD.mjs +1235 -0
  148. package/dist-boot/c-TT6BCUJD.mjs +114 -0
  149. package/dist-boot/c-U4ITOXAN.mjs +2107 -0
  150. package/dist-boot/c-UGERXVO2.mjs +7120 -0
  151. package/dist-boot/c-UPBH5AXY.mjs +1363 -0
  152. package/dist-boot/c-US2PUNZL.mjs +597 -0
  153. package/dist-boot/c-UU4WZPPE.mjs +20 -0
  154. package/dist-boot/c-UWVIYPQS.mjs +39 -0
  155. package/dist-boot/c-V4RHQBPQ.mjs +17683 -0
  156. package/dist-boot/c-V5MRVK47.mjs +351 -0
  157. package/dist-boot/c-V6CL266R.mjs +1755 -0
  158. package/dist-boot/c-VJTMFKYE.mjs +14975 -0
  159. package/dist-boot/c-VJTRUKIB.mjs +773 -0
  160. package/dist-boot/c-W4IFSHPW.mjs +43 -0
  161. package/dist-boot/c-WETGB2CF.mjs +113 -0
  162. package/dist-boot/c-WO3QSZUU.mjs +1337 -0
  163. package/dist-boot/c-WQLH73TY.mjs +242 -0
  164. package/dist-boot/c-XL735JW5.mjs +500 -0
  165. package/dist-boot/c-Y7HADL5B.mjs +1107 -0
  166. package/dist-boot/c-YGQHSVSK.mjs +41 -0
  167. package/dist-boot/c-YMP2AMEB.mjs +10350 -0
  168. package/dist-boot/c-YRDO2WEF.mjs +12012 -0
  169. package/dist-boot/c-YUSTRATJ.mjs +8 -0
  170. package/dist-boot/c-Z2262R22.mjs +2697 -0
  171. package/dist-boot/c-Z4ALQMJC.mjs +709 -0
  172. package/dist-boot/c-Z5ZUQVUY.mjs +62 -0
  173. package/dist-boot/c-ZDZUKXF7.mjs +874 -0
  174. package/dist-boot/c-ZJYLGIC3.mjs +32 -0
  175. package/dist-boot/c-ZNA5CDMI.mjs +77 -0
  176. package/dist-boot/c-ZSO6DI3M.mjs +204 -0
  177. package/dist-boot/c-ZWUVHKMK.mjs +100 -0
  178. package/dist-boot/c-ZY4MESEW.mjs +832 -0
  179. package/dist-boot/c-ZZ5REI4L.mjs +329 -0
  180. package/dist-boot/cli.mjs +51 -0
  181. package/dist-boot/ext-anthropic-attribution.mjs +207 -0
  182. package/dist-boot/ext-pi-background-tasks.mjs +7234 -0
  183. package/dist-boot/ext-pi-subagents.mjs +37 -0
  184. package/dist-boot/ext-privateer-account.mjs +4426 -0
  185. package/dist-boot/ext-privateer-brand.mjs +5274 -0
  186. package/dist-boot/ext-privateer-codemode.mjs +37 -0
  187. package/dist-boot/ext-privateer-computer.mjs +626 -0
  188. package/dist-boot/ext-privateer-connect.mjs +1862 -0
  189. package/dist-boot/ext-privateer-context.mjs +323 -0
  190. package/dist-boot/ext-privateer-desktop.mjs +92 -0
  191. package/dist-boot/ext-privateer-final-audit.mjs +48 -0
  192. package/dist-boot/ext-privateer-fresh.mjs +81 -0
  193. package/dist-boot/ext-privateer-gate.mjs +5959 -0
  194. package/dist-boot/ext-privateer-hints.mjs +236 -0
  195. package/dist-boot/ext-privateer-media.mjs +2626 -0
  196. package/dist-boot/ext-privateer-models.mjs +3397 -0
  197. package/dist-boot/ext-privateer-posture.mjs +3006 -0
  198. package/dist-boot/ext-privateer-privacy.mjs +4578 -0
  199. package/dist-boot/ext-privateer-recovery.mjs +287 -0
  200. package/dist-boot/ext-privateer-speak.mjs +4754 -0
  201. package/dist-boot/ext-privateer-terminals.mjs +725 -0
  202. package/dist-boot/ext-privateer-tools.mjs +528 -0
  203. package/dist-boot/ext-privateer-truncation.mjs +74 -0
  204. package/dist-boot/ext-privateer-update.mjs +210 -0
  205. package/dist-boot/ext-privateer-vision.mjs +148 -0
  206. package/dist-boot/ext-privateer-web.mjs +543 -0
  207. package/dist-boot/ext-rpiv-ask-user-question.mjs +710 -0
  208. package/dist-boot/manifest.json +9 -0
  209. package/extensions/privateer-brand.ts +3 -1
  210. package/extensions/privateer-context.ts +4 -2
  211. package/extensions/privateer-final-audit.ts +17 -0
  212. package/extensions/privateer-gate.ts +55 -9
  213. package/extensions/privateer-recovery.ts +175 -0
  214. package/extensions/privateer-web.ts +4 -4
  215. package/package.json +3 -1
  216. package/patches/@earendil-works+pi-coding-agent+1.3.0.patch +199 -2
  217. package/patches/pi-background-tasks+2.6.10.patch +91 -7
  218. package/src/cli/chat.ts +7 -1
  219. package/src/config/moatManifest.json +2 -0
  220. package/src/config/whatsNew.json +4 -4
  221. package/src/context.ts +33 -5
  222. package/src/engine/finalAudit.ts +38 -0
  223. package/src/engine/stallWatchdog.ts +8 -1
  224. package/src/providers/account.ts +34 -3
  225. package/src/remote/attentionPush.ts +40 -0
  226. package/src/remote/liveTaskSession.ts +7 -1
  227. package/src/remote/relayClient.ts +38 -4
  228. package/src/remote/remoteBridge.ts +17 -0
  229. package/src/remote/transcriptSnapshot.ts +104 -0
@@ -0,0 +1,1659 @@
1
+ import{createRequire as __pvCR}from"node:module";import{fileURLToPath as __pvF}from"node:url";import{dirname as __pvD}from"node:path";const require=__pvCR(import.meta.url);const __pvUrl=(r)=>new URL(r,import.meta.url).href;const __pvFile=(r)=>__pvF(new URL(r,import.meta.url));
2
+ import {
3
+ X509Certificate
4
+ } from "./c-65UZIZC7.mjs";
5
+ import {
6
+ ASN1Obj,
7
+ HashAlgorithms,
8
+ KeyTypes,
9
+ uint8ArrayEqual
10
+ } from "./c-U4ITOXAN.mjs";
11
+ import {
12
+ __name
13
+ } from "./c-CN77DCGF.mjs";
14
+
15
+ // node_modules/@tinfoilsh/verifier/dist/errors.js
16
+ var TinfoilError = class extends Error {
17
+ static {
18
+ __name(this, "TinfoilError");
19
+ }
20
+ constructor(message, options) {
21
+ super(message);
22
+ this.name = "TinfoilError";
23
+ if (options?.cause) {
24
+ this.cause = options.cause;
25
+ }
26
+ }
27
+ };
28
+ var ConfigurationError = class extends TinfoilError {
29
+ static {
30
+ __name(this, "ConfigurationError");
31
+ }
32
+ constructor(message, options) {
33
+ super(message, options);
34
+ this.name = "ConfigurationError";
35
+ }
36
+ };
37
+ var FetchError = class extends TinfoilError {
38
+ static {
39
+ __name(this, "FetchError");
40
+ }
41
+ constructor(message, options) {
42
+ super(message, options);
43
+ this.name = "FetchError";
44
+ }
45
+ };
46
+ var AttestationError = class extends TinfoilError {
47
+ static {
48
+ __name(this, "AttestationError");
49
+ }
50
+ constructor(message, options) {
51
+ super(message, options);
52
+ this.name = "AttestationError";
53
+ }
54
+ };
55
+ function wrapOrThrow(e, ErrorClass, message) {
56
+ if (e instanceof TinfoilError) {
57
+ throw e;
58
+ }
59
+ throw new ErrorClass(message, { cause: e });
60
+ }
61
+ __name(wrapOrThrow, "wrapOrThrow");
62
+
63
+ // node_modules/@tinfoilsh/verifier/dist/types.js
64
+ var PredicateType;
65
+ (function(PredicateType2) {
66
+ PredicateType2["SevGuestV1"] = "https://tinfoil.sh/predicate/sev-snp-guest/v1";
67
+ PredicateType2["SevGuestV2"] = "https://tinfoil.sh/predicate/sev-snp-guest/v2";
68
+ PredicateType2["SnpTdxMultiplatformV1"] = "https://tinfoil.sh/predicate/snp-tdx-multiplatform/v1";
69
+ })(PredicateType || (PredicateType = {}));
70
+ function compareMeasurements(a, b) {
71
+ if (a.type === b.type) {
72
+ if (a.registers.length !== b.registers.length || !a.registers.every((reg, i) => reg === b.registers[i])) {
73
+ throw new AttestationError("Code measurement mismatch: The enclave is running different code than the expected release");
74
+ }
75
+ return;
76
+ }
77
+ if (a.type === PredicateType.SnpTdxMultiplatformV1 && b.type === PredicateType.SevGuestV2) {
78
+ if (a.registers.length < 1 || b.registers.length < 1) {
79
+ throw new AttestationError("Invalid measurement data: Missing measurement registers");
80
+ }
81
+ if (a.registers[0] !== b.registers[0]) {
82
+ throw new AttestationError("Code measurement mismatch: The SNP measurement from the enclave does not match the expected measurement from the signed release");
83
+ }
84
+ return;
85
+ }
86
+ if (a.type === PredicateType.SevGuestV2 && b.type === PredicateType.SnpTdxMultiplatformV1) {
87
+ if (a.registers.length < 1 || b.registers.length < 1) {
88
+ throw new AttestationError("Invalid measurement data: Missing measurement registers");
89
+ }
90
+ if (a.registers[0] !== b.registers[0]) {
91
+ throw new AttestationError("Code measurement mismatch: The SNP measurement from the enclave does not match the expected measurement from the signed release");
92
+ }
93
+ return;
94
+ }
95
+ throw new AttestationError(`Cannot compare measurements: Incompatible measurement types "${a.type}" and "${b.type}"`);
96
+ }
97
+ __name(compareMeasurements, "compareMeasurements");
98
+ async function measurementFingerprint(m) {
99
+ if (m.registers.length === 1) {
100
+ return m.registers[0];
101
+ }
102
+ const allData = m.type + m.registers.join("");
103
+ const encoder = new TextEncoder();
104
+ const hashBuffer = await crypto.subtle.digest("SHA-256", encoder.encode(allData));
105
+ const hashArray = new Uint8Array(hashBuffer);
106
+ return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
107
+ }
108
+ __name(measurementFingerprint, "measurementFingerprint");
109
+ async function hashAttestationDocument(doc) {
110
+ const data = doc.format + doc.body;
111
+ const encoder = new TextEncoder();
112
+ const hashBuffer = await crypto.subtle.digest("SHA-256", encoder.encode(data));
113
+ const hashArray = new Uint8Array(hashBuffer);
114
+ return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
115
+ }
116
+ __name(hashAttestationDocument, "hashAttestationDocument");
117
+
118
+ // node_modules/@tinfoilsh/verifier/dist/sev/constants.js
119
+ var POLICY_RESERVED_1_BIT = 17;
120
+ var REPORT_SIZE = 1184;
121
+ var SIGNATURE_OFFSET = 672;
122
+ var ECDSA_RS_SIZE = 72;
123
+ var ECDSA_P384_SHA384_SIGNATURE_SIZE = ECDSA_RS_SIZE + ECDSA_RS_SIZE;
124
+ var ZEN3ZEN4_FAMILY = 25;
125
+ var ZEN5_FAMILY = 26;
126
+ var MILAN_MODEL = 0 | 1;
127
+ var GENOA_MODEL = 1 << 4 | 1;
128
+ var TURIN_MODEL = 2;
129
+ var ReportSigner;
130
+ (function(ReportSigner2) {
131
+ ReportSigner2[ReportSigner2["VcekReportSigner"] = 0] = "VcekReportSigner";
132
+ ReportSigner2[ReportSigner2["VlekReportSigner"] = 1] = "VlekReportSigner";
133
+ ReportSigner2[ReportSigner2["endorseReserved2"] = 2] = "endorseReserved2";
134
+ ReportSigner2[ReportSigner2["endorseReserved3"] = 3] = "endorseReserved3";
135
+ ReportSigner2[ReportSigner2["endorseReserved4"] = 4] = "endorseReserved4";
136
+ ReportSigner2[ReportSigner2["endorseReserved5"] = 5] = "endorseReserved5";
137
+ ReportSigner2[ReportSigner2["endorseReserved6"] = 6] = "endorseReserved6";
138
+ ReportSigner2[ReportSigner2["NoneReportSigner"] = 7] = "NoneReportSigner";
139
+ })(ReportSigner || (ReportSigner = {}));
140
+
141
+ // node_modules/@tinfoilsh/verifier/dist/sev/utils.js
142
+ function tcbFromInt(tcb) {
143
+ return {
144
+ ucodeSpl: Number(tcb >> 56n & 0xffn),
145
+ snpSpl: Number(tcb >> 48n & 0xffn),
146
+ teeSpl: Number(tcb >> 8n & 0xffn),
147
+ blSpl: Number(tcb & 0xffn)
148
+ };
149
+ }
150
+ __name(tcbFromInt, "tcbFromInt");
151
+ function tcbMeetsMinimum(tcb, minimum) {
152
+ return tcb.blSpl >= minimum.blSpl && tcb.teeSpl >= minimum.teeSpl && tcb.snpSpl >= minimum.snpSpl && tcb.ucodeSpl >= minimum.ucodeSpl;
153
+ }
154
+ __name(tcbMeetsMinimum, "tcbMeetsMinimum");
155
+ function platformInfoFromInt(value) {
156
+ return {
157
+ smtEnabled: !!(value & 1n),
158
+ tsmeEnabled: !!(value & 2n),
159
+ eccEnabled: !!(value & 4n),
160
+ raplDisabled: !!(value & 8n),
161
+ ciphertextHidingDramEnabled: !!(value & 16n),
162
+ aliasCheckComplete: !!(value & 32n),
163
+ tioEnabled: !!(value & 128n)
164
+ };
165
+ }
166
+ __name(platformInfoFromInt, "platformInfoFromInt");
167
+ function policyFromInt(value) {
168
+ return {
169
+ abiMinor: Number(value & 0xffn),
170
+ abiMajor: Number(value >> 8n & 0xffn),
171
+ smt: !!(value & 1n << 16n),
172
+ migrateMa: !!(value & 1n << 18n),
173
+ debug: !!(value & 1n << 19n),
174
+ singleSocket: !!(value & 1n << 20n),
175
+ cxlAllowed: !!(value & 1n << 21n),
176
+ memAes256Xts: !!(value & 1n << 22n),
177
+ raplDis: !!(value & 1n << 23n),
178
+ ciphertextHidingDram: !!(value & 1n << 24n),
179
+ pageSwapDisabled: !!(value & 1n << 25n)
180
+ };
181
+ }
182
+ __name(policyFromInt, "policyFromInt");
183
+ function bytesToHex(bytes) {
184
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
185
+ }
186
+ __name(bytesToHex, "bytesToHex");
187
+
188
+ // node_modules/@tinfoilsh/verifier/dist/sev/report.js
189
+ var Report = class {
190
+ static {
191
+ __name(this, "Report");
192
+ }
193
+ /**
194
+ * Parse an attestation report from raw bytes in SEV SNP ABI format.
195
+ *
196
+ * @param data - Raw bytes of the attestation report
197
+ * @returns Report object containing parsed data
198
+ * @throws Error if data is malformed or validation fails
199
+ */
200
+ constructor(data) {
201
+ if (data.length < REPORT_SIZE) {
202
+ throw new AttestationError(`Invalid attestation report: Data size (${data.length} bytes) is smaller than expected SEV-SNP report size (${REPORT_SIZE} bytes)`);
203
+ }
204
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
205
+ this.version = view.getUint32(0, true);
206
+ this.guestSvn = view.getUint32(4, true);
207
+ this.policy = view.getBigUint64(8, true);
208
+ if (!(this.policy & 1n << BigInt(POLICY_RESERVED_1_BIT))) {
209
+ throw new AttestationError("Invalid attestation report: Policy field has invalid reserved bit (must be 1)");
210
+ }
211
+ if (this.policy >> 26n) {
212
+ throw new AttestationError("Invalid attestation report: Policy field has non-zero reserved bits");
213
+ }
214
+ this.familyId = data.slice(16, 32);
215
+ this.imageId = data.slice(32, 48);
216
+ this.vmpl = view.getUint32(48, true);
217
+ this.signatureAlgo = view.getUint32(52, true);
218
+ this.currentTcb = view.getBigUint64(56, true);
219
+ try {
220
+ mbz64(this.currentTcb, "current_tcb", 47, 16);
221
+ } catch (e) {
222
+ throw new AttestationError("Invalid attestation report: TCB (Trusted Computing Base) version field is malformed", { cause: e });
223
+ }
224
+ this.platformInfo = view.getBigUint64(64, true);
225
+ this.policyParsed = policyFromInt(this.policy);
226
+ this.platformInfoParsed = platformInfoFromInt(this.platformInfo);
227
+ this.signerInfo = view.getUint32(72, true);
228
+ try {
229
+ mbz64(BigInt(this.signerInfo), "signer_info", 31, 5);
230
+ } catch (e) {
231
+ throw new AttestationError("Invalid attestation report: Signer info field is malformed", { cause: e });
232
+ }
233
+ const signingKey = this.signerInfo >> 2 & 7;
234
+ if (signingKey !== ReportSigner.VcekReportSigner) {
235
+ throw new AttestationError(`Unsupported signing key type: This verifier only supports VCEK-signed attestation reports (got signing key type ${signingKey})`);
236
+ }
237
+ this.signerInfoParsed = {
238
+ signingKey,
239
+ maskChipKey: !!(this.signerInfo & 2),
240
+ authorKeyEn: !!(this.signerInfo & 1)
241
+ };
242
+ try {
243
+ mbz(data, 76, 80);
244
+ } catch (e) {
245
+ throw new AttestationError("Invalid attestation report: Reserved bytes at offset 0x4C are not zeroed", { cause: e });
246
+ }
247
+ this.reportData = data.slice(80, 144);
248
+ this.measurement = data.slice(144, 192);
249
+ this.hostData = data.slice(192, 224);
250
+ this.idKeyDigest = data.slice(224, 272);
251
+ this.authorKeyDigest = data.slice(272, 320);
252
+ this.reportId = data.slice(320, 352);
253
+ this.reportIdMa = data.slice(352, 384);
254
+ this.reportedTcb = view.getBigUint64(384, true);
255
+ try {
256
+ mbz64(this.reportedTcb, "reported_tcb", 47, 16);
257
+ } catch (e) {
258
+ throw new AttestationError("Invalid attestation report: Reported TCB field is malformed", { cause: e });
259
+ }
260
+ let mbzLo = 392;
261
+ if (this.version >= 3) {
262
+ this.family = view.getUint8(392);
263
+ this.model = view.getUint8(393);
264
+ this.stepping = view.getUint8(394);
265
+ this.productName = this.initProductName();
266
+ mbzLo = 395;
267
+ } else if (this.version === 2) {
268
+ this.family = ZEN3ZEN4_FAMILY;
269
+ this.model = GENOA_MODEL;
270
+ this.stepping = 1;
271
+ this.productName = "Genoa";
272
+ } else {
273
+ throw new AttestationError(`Unsupported attestation report version: ${this.version}. Only version 2 (revision 1.55) and version 3+ are supported`);
274
+ }
275
+ try {
276
+ mbz(data, mbzLo, 416);
277
+ } catch (e) {
278
+ throw new AttestationError("Invalid attestation report: Reserved bytes in version section are not zeroed", { cause: e });
279
+ }
280
+ this.chipId = data.slice(416, 480);
281
+ this.committedTcb = view.getBigUint64(480, true);
282
+ try {
283
+ mbz64(this.committedTcb, "committed_tcb", 47, 16);
284
+ } catch (e) {
285
+ throw new AttestationError("Invalid attestation report: Committed TCB field is malformed", { cause: e });
286
+ }
287
+ this.currentBuild = view.getUint8(488);
288
+ this.currentMinor = view.getUint8(489);
289
+ this.currentMajor = view.getUint8(490);
290
+ try {
291
+ mbz(data, 491, 492);
292
+ } catch (e) {
293
+ throw new AttestationError("Invalid attestation report: Reserved bytes after current version are not zeroed", { cause: e });
294
+ }
295
+ this.committedBuild = view.getUint8(492);
296
+ this.committedMinor = view.getUint8(493);
297
+ this.committedMajor = view.getUint8(494);
298
+ try {
299
+ mbz(data, 495, 496);
300
+ } catch (e) {
301
+ throw new AttestationError("Invalid attestation report: Reserved bytes after committed version are not zeroed", { cause: e });
302
+ }
303
+ this.launchTcb = view.getBigUint64(496, true);
304
+ try {
305
+ mbz64(this.launchTcb, "launch_tcb", 47, 16);
306
+ } catch (e) {
307
+ throw new AttestationError("Invalid attestation report: Launch TCB field is malformed", { cause: e });
308
+ }
309
+ const mbzBeforeSig = this.version < 5 ? 504 : 520;
310
+ try {
311
+ mbz(data, mbzBeforeSig, SIGNATURE_OFFSET);
312
+ } catch (e) {
313
+ throw new AttestationError("Invalid attestation report: Reserved bytes before signature are not zeroed", { cause: e });
314
+ }
315
+ if (this.signatureAlgo === 1) {
316
+ try {
317
+ mbz(data, SIGNATURE_OFFSET + ECDSA_P384_SHA384_SIGNATURE_SIZE, REPORT_SIZE);
318
+ } catch (e) {
319
+ throw new AttestationError("Invalid attestation report: Reserved bytes after signature are not zeroed", { cause: e });
320
+ }
321
+ }
322
+ this.signedData = data.slice(0, SIGNATURE_OFFSET);
323
+ this.signature = data.slice(SIGNATURE_OFFSET, REPORT_SIZE);
324
+ }
325
+ initProductName() {
326
+ if (this.family === ZEN3ZEN4_FAMILY) {
327
+ if (this.model === MILAN_MODEL)
328
+ return "Milan";
329
+ if (this.model === GENOA_MODEL)
330
+ return "Genoa";
331
+ } else if (this.family === ZEN5_FAMILY) {
332
+ if (this.model === TURIN_MODEL)
333
+ return "Turin";
334
+ }
335
+ return "Unknown";
336
+ }
337
+ };
338
+ function findNonZero(data, lo, hi) {
339
+ for (let i = lo; i < hi; i++) {
340
+ if (data[i] !== 0)
341
+ return i;
342
+ }
343
+ return hi;
344
+ }
345
+ __name(findNonZero, "findNonZero");
346
+ function mbz(data, lo, hi) {
347
+ const firstNonZero = findNonZero(data, lo, hi);
348
+ if (firstNonZero !== hi) {
349
+ const hexStr = Array.from(data.slice(lo, hi)).map((b) => b.toString(16).padStart(2, "0")).join("");
350
+ throw new AttestationError(`reserved bytes at offset 0x${lo.toString(16)}-0x${hi.toString(16)} contain non-zero data: ${hexStr}`);
351
+ }
352
+ }
353
+ __name(mbz, "mbz");
354
+ function mbz64(data, base, hi, lo) {
355
+ const mask = (1n << BigInt(hi - lo + 1)) - 1n;
356
+ const bits = data >> BigInt(lo) & mask;
357
+ if (bits !== 0n) {
358
+ throw new AttestationError(`Reserved bits in ${base} field contain non-zero data: 0x${data.toString(16)}`);
359
+ }
360
+ }
361
+ __name(mbz64, "mbz64");
362
+
363
+ // node_modules/@tinfoilsh/verifier/dist/sev/certs.js
364
+ var ARK_CERT = `-----BEGIN CERTIFICATE-----
365
+ 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
399
+ /wMz1R1BHg==
400
+ -----END CERTIFICATE-----`;
401
+ var ASK_CERT = `-----BEGIN CERTIFICATE-----
402
+ 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
437
+ -----END CERTIFICATE-----`;
438
+
439
+ // node_modules/@tinfoilsh/verifier/dist/sev/cert-chain.js
440
+ var SnpOid = {
441
+ STRUCT_VERSION: "1.3.6.1.4.1.3704.1.1",
442
+ PRODUCT_NAME: "1.3.6.1.4.1.3704.1.2",
443
+ BL_SPL: "1.3.6.1.4.1.3704.1.3.1",
444
+ TEE_SPL: "1.3.6.1.4.1.3704.1.3.2",
445
+ SNP_SPL: "1.3.6.1.4.1.3704.1.3.3",
446
+ SPL4: "1.3.6.1.4.1.3704.1.3.4",
447
+ SPL5: "1.3.6.1.4.1.3704.1.3.5",
448
+ SPL6: "1.3.6.1.4.1.3704.1.3.6",
449
+ SPL7: "1.3.6.1.4.1.3704.1.3.7",
450
+ UCODE: "1.3.6.1.4.1.3704.1.3.8",
451
+ HWID: "1.3.6.1.4.1.3704.1.4",
452
+ CSP_ID: "1.3.6.1.4.1.3704.1.5",
453
+ // Aliases for compatibility
454
+ BOOTLOADER: "1.3.6.1.4.1.3704.1.3.1",
455
+ TEE: "1.3.6.1.4.1.3704.1.3.2",
456
+ SNP: "1.3.6.1.4.1.3704.1.3.3"
457
+ };
458
+ var OID_RSASSA_PSS = "1.2.840.113549.1.1.10";
459
+ var OID_EC_PUBLIC_KEY = "1.2.840.10045.2.1";
460
+ var OID_SECP384R1 = "1.3.132.0.34";
461
+ var CertificateChain = class _CertificateChain {
462
+ static {
463
+ __name(this, "CertificateChain");
464
+ }
465
+ constructor(ark, ask, vcek) {
466
+ this.ark = ark;
467
+ this.ask = ask;
468
+ this.vcek = vcek;
469
+ }
470
+ static async fromReport(report, vcekDer) {
471
+ if (report.productName !== "Genoa") {
472
+ throw new AttestationError(`Unsupported processor: ${report.productName}. This verifier only supports AMD EPYC Genoa processors`);
473
+ }
474
+ if (report.signerInfoParsed.signingKey !== ReportSigner.VcekReportSigner) {
475
+ throw new AttestationError("Unsupported signing key: This verifier only supports VCEK-signed attestation reports");
476
+ }
477
+ const ark = X509Certificate.parse(ARK_CERT);
478
+ const ask = X509Certificate.parse(ASK_CERT);
479
+ const vcekCert = X509Certificate.parse(vcekDer);
480
+ return new _CertificateChain(ark, ask, vcekCert);
481
+ }
482
+ async verifyChain() {
483
+ try {
484
+ this.validateArkFormat();
485
+ this.validateAskFormat();
486
+ this.validateVcekFormat();
487
+ const now = /* @__PURE__ */ new Date();
488
+ if (!this.ark.validForDate(now)) {
489
+ throw new AttestationError("AMD Root Key (ARK) certificate has expired or is not yet valid");
490
+ }
491
+ if (!this.ask.validForDate(now)) {
492
+ throw new AttestationError("AMD SEV Key (ASK) certificate has expired or is not yet valid");
493
+ }
494
+ if (!this.vcek.validForDate(now)) {
495
+ throw new AttestationError("VCEK certificate has expired or is not yet valid");
496
+ }
497
+ const arkSelfSigned = await this.ark.verify();
498
+ if (!arkSelfSigned) {
499
+ throw new AttestationError("AMD Root Key (ARK) certificate signature verification failed: Not properly self-signed");
500
+ }
501
+ const askSignedByArk = await this.ask.verify(this.ark);
502
+ if (!askSignedByArk) {
503
+ throw new AttestationError("AMD SEV Key (ASK) certificate signature verification failed: Not signed by ARK");
504
+ }
505
+ const vcekSignedByAsk = await this.vcek.verify(this.ask);
506
+ if (!vcekSignedByAsk) {
507
+ throw new AttestationError("VCEK certificate signature verification failed: Not signed by ASK");
508
+ }
509
+ return true;
510
+ } catch (e) {
511
+ wrapOrThrow(e, AttestationError, "AMD certificate chain verification failed");
512
+ }
513
+ }
514
+ validateVcekTcb(tcb) {
515
+ const blSplExt = this.vcek.extension(SnpOid.BL_SPL);
516
+ if (!blSplExt) {
517
+ throw new AttestationError("Invalid VCEK certificate: Missing bootloader security patch level (BL_SPL) extension");
518
+ }
519
+ const blSpl = this.decodeExtensionInteger(blSplExt.value);
520
+ if (blSpl !== tcb.blSpl) {
521
+ throw new AttestationError(`VCEK TCB mismatch: Bootloader SPL in certificate (${blSpl}) does not match report (${tcb.blSpl})`);
522
+ }
523
+ const teeSplExt = this.vcek.extension(SnpOid.TEE_SPL);
524
+ if (!teeSplExt) {
525
+ throw new AttestationError("Invalid VCEK certificate: Missing TEE security patch level (TEE_SPL) extension");
526
+ }
527
+ const teeSpl = this.decodeExtensionInteger(teeSplExt.value);
528
+ if (teeSpl !== tcb.teeSpl) {
529
+ throw new AttestationError(`VCEK TCB mismatch: TEE SPL in certificate (${teeSpl}) does not match report (${tcb.teeSpl})`);
530
+ }
531
+ const snpSplExt = this.vcek.extension(SnpOid.SNP_SPL);
532
+ if (!snpSplExt) {
533
+ throw new AttestationError("Invalid VCEK certificate: Missing SNP security patch level (SNP_SPL) extension");
534
+ }
535
+ const snpSpl = this.decodeExtensionInteger(snpSplExt.value);
536
+ if (snpSpl !== tcb.snpSpl) {
537
+ throw new AttestationError(`VCEK TCB mismatch: SNP SPL in certificate (${snpSpl}) does not match report (${tcb.snpSpl})`);
538
+ }
539
+ const ucodeExt = this.vcek.extension(SnpOid.UCODE);
540
+ if (!ucodeExt) {
541
+ throw new AttestationError("Invalid VCEK certificate: Missing microcode security patch level (UCODE) extension");
542
+ }
543
+ const ucodeSpl = this.decodeExtensionInteger(ucodeExt.value);
544
+ if (ucodeSpl !== tcb.ucodeSpl) {
545
+ throw new AttestationError(`VCEK TCB mismatch: Microcode SPL in certificate (${ucodeSpl}) does not match report (${tcb.ucodeSpl})`);
546
+ }
547
+ }
548
+ validateVcekHwid(chipId) {
549
+ const hwidExt = this.vcek.extension(SnpOid.HWID);
550
+ if (!hwidExt) {
551
+ throw new AttestationError("Invalid VCEK certificate: Missing hardware ID (HWID) extension");
552
+ }
553
+ if (!uint8ArrayEqual(hwidExt.value, chipId)) {
554
+ throw new AttestationError("VCEK hardware ID mismatch: Certificate HWID does not match the chip ID in the attestation report");
555
+ }
556
+ }
557
+ validateArkFormat() {
558
+ if (this.ark.version !== "v3") {
559
+ throw new AttestationError(`Invalid ARK certificate: Expected X.509 version v3, got ${this.ark.version}`);
560
+ }
561
+ if (!this.validateAmdLocation(this.ark.issuerDN)) {
562
+ throw new AttestationError("Invalid ARK certificate: Issuer is not a valid AMD organization");
563
+ }
564
+ if (!this.validateAmdLocation(this.ark.subjectDN)) {
565
+ throw new AttestationError("Invalid ARK certificate: Subject is not a valid AMD organization");
566
+ }
567
+ const cn = this.ark.subjectDN.get("CN");
568
+ if (cn !== "ARK-Genoa") {
569
+ throw new AttestationError(`Invalid ARK certificate: Expected common name "ARK-Genoa", got "${cn}"`);
570
+ }
571
+ }
572
+ validateAskFormat() {
573
+ if (this.ask.version !== "v3") {
574
+ throw new AttestationError(`Invalid ASK certificate: Expected X.509 version v3, got ${this.ask.version}`);
575
+ }
576
+ if (!this.validateAmdLocation(this.ask.issuerDN)) {
577
+ throw new AttestationError("Invalid ASK certificate: Issuer is not a valid AMD organization");
578
+ }
579
+ if (!this.validateAmdLocation(this.ask.subjectDN)) {
580
+ throw new AttestationError("Invalid ASK certificate: Subject is not a valid AMD organization");
581
+ }
582
+ const cn = this.ask.subjectDN.get("CN");
583
+ if (cn !== "SEV-Genoa") {
584
+ throw new AttestationError(`Invalid ASK certificate: Expected common name "SEV-Genoa", got "${cn}"`);
585
+ }
586
+ }
587
+ validateVcekFormat() {
588
+ if (this.vcek.version !== "v3") {
589
+ throw new AttestationError(`Invalid VCEK certificate: Expected X.509 version v3, got ${this.vcek.version}`);
590
+ }
591
+ if (!this.validateAmdLocation(this.vcek.issuerDN)) {
592
+ throw new AttestationError("Invalid VCEK certificate: Issuer is not a valid AMD organization");
593
+ }
594
+ if (!this.validateAmdLocation(this.vcek.subjectDN)) {
595
+ throw new AttestationError("Invalid VCEK certificate: Subject is not a valid AMD organization");
596
+ }
597
+ const cn = this.vcek.subjectDN.get("CN");
598
+ if (cn !== "SEV-VCEK") {
599
+ throw new AttestationError(`Invalid VCEK certificate: Expected common name "SEV-VCEK", got "${cn}"`);
600
+ }
601
+ const sigAlgOid = this.getSignatureAlgorithmOid(this.vcek);
602
+ if (sigAlgOid !== OID_RSASSA_PSS) {
603
+ throw new AttestationError("Invalid VCEK certificate: Signature algorithm must be RSASSA-PSS");
604
+ }
605
+ const { algorithm, curve } = this.getPublicKeyInfo(this.vcek);
606
+ if (algorithm !== OID_EC_PUBLIC_KEY) {
607
+ throw new AttestationError("Invalid VCEK certificate: Public key must be ECDSA");
608
+ }
609
+ if (curve !== OID_SECP384R1) {
610
+ throw new AttestationError("Invalid VCEK certificate: Public key curve must be secp384r1 (P-384)");
611
+ }
612
+ const cspIdExt = this.vcek.extension(SnpOid.CSP_ID);
613
+ if (cspIdExt) {
614
+ throw new AttestationError("Invalid VCEK certificate: CSP_ID extension should not be present (this looks like a VLEK certificate)");
615
+ }
616
+ const hwidExt = this.vcek.extension(SnpOid.HWID);
617
+ if (!hwidExt || hwidExt.value.length !== 64) {
618
+ throw new AttestationError("Invalid VCEK certificate: Missing or malformed hardware ID (HWID) extension");
619
+ }
620
+ const productNameExt = this.vcek.extension(SnpOid.PRODUCT_NAME);
621
+ if (!productNameExt) {
622
+ throw new AttestationError("Invalid VCEK certificate: Missing product name extension");
623
+ }
624
+ const expectedProductName = new Uint8Array([22, 5, 71, 101, 110, 111, 97]);
625
+ if (!uint8ArrayEqual(productNameExt.value, expectedProductName)) {
626
+ throw new AttestationError('Invalid VCEK certificate: Product name must be "Genoa"');
627
+ }
628
+ }
629
+ validateAmdLocation(name) {
630
+ const country = name.get("C");
631
+ const locality = name.get("L");
632
+ const state = name.get("ST");
633
+ const org = name.get("O");
634
+ const orgUnit = name.get("OU");
635
+ return country === "US" && locality === "Santa Clara" && state === "CA" && org === "Advanced Micro Devices" && orgUnit === "Engineering";
636
+ }
637
+ getSignatureAlgorithmOid(cert) {
638
+ const sigAlgObj = cert.root.subs[1];
639
+ return sigAlgObj.subs[0].toOID();
640
+ }
641
+ getPublicKeyInfo(cert) {
642
+ const tbsCert = cert.root.subs[0];
643
+ const spki = tbsCert.subs[6];
644
+ const algorithmSeq = spki.subs[0];
645
+ const algorithm = algorithmSeq.subs[0].toOID();
646
+ const curve = algorithmSeq.subs[1]?.toOID() || "";
647
+ return { algorithm, curve };
648
+ }
649
+ decodeExtensionInteger(value) {
650
+ const asn1 = ASN1Obj.parseBuffer(value);
651
+ return Number(asn1.toInteger());
652
+ }
653
+ get vcekPublicKey() {
654
+ return this.vcek.publicKeyObj;
655
+ }
656
+ };
657
+
658
+ // node_modules/@tinfoilsh/verifier/dist/sev/verify.js
659
+ async function verifyReportSignature(vcekPublicKey, report) {
660
+ if (report.version < 2) {
661
+ throw new AttestationError(`Unsupported attestation report version ${report.version}. Minimum required version is 2`);
662
+ }
663
+ if (!(report.policy & 1n << BigInt(POLICY_RESERVED_1_BIT))) {
664
+ throw new AttestationError("Invalid attestation report: Policy field has invalid reserved bit");
665
+ }
666
+ if (report.policy >> 26n) {
667
+ throw new AttestationError("Invalid attestation report: Policy field has non-zero reserved bits");
668
+ }
669
+ if (report.signatureAlgo !== 1) {
670
+ throw new AttestationError(`Unsupported signature algorithm (${report.signatureAlgo}). Only ECDSA P-384 with SHA-384 (algorithm 1) is supported`);
671
+ }
672
+ const rBytesLE = report.signature.slice(0, 72);
673
+ const sBytesLE = report.signature.slice(72, 144);
674
+ const rBytesBE = reverseBytes(rBytesLE);
675
+ const sBytesBE = reverseBytes(sBytesLE);
676
+ const r = bytesToBigInt(stripLeadingZeros(rBytesBE));
677
+ const s = bytesToBigInt(stripLeadingZeros(sBytesBE));
678
+ const rRaw = bigIntToFixedBytes(r, 48);
679
+ const sRaw = bigIntToFixedBytes(s, 48);
680
+ const rawSignature = new Uint8Array(96);
681
+ rawSignature.set(rRaw, 0);
682
+ rawSignature.set(sRaw, 48);
683
+ const signedData = report.signedData.slice();
684
+ try {
685
+ const isValid = await crypto.subtle.verify({ name: KeyTypes.Ecdsa, hash: HashAlgorithms.SHA384 }, vcekPublicKey, rawSignature, signedData);
686
+ return isValid;
687
+ } catch (e) {
688
+ wrapOrThrow(e, AttestationError, "Failed to verify attestation report signature using VCEK public key");
689
+ }
690
+ }
691
+ __name(verifyReportSignature, "verifyReportSignature");
692
+ async function verifyAttestation(chain, report) {
693
+ const isChainValid = await chain.verifyChain();
694
+ if (!isChainValid) {
695
+ throw new AttestationError("AMD certificate chain verification failed: The chain from ARK to ASK to VCEK could not be verified");
696
+ }
697
+ const vcekPublicKey = await chain.vcekPublicKey;
698
+ const isSignatureValid = await verifyReportSignature(vcekPublicKey, report);
699
+ if (!isSignatureValid) {
700
+ throw new AttestationError("Attestation report signature is invalid: The report was not signed by the expected VCEK key");
701
+ }
702
+ return true;
703
+ }
704
+ __name(verifyAttestation, "verifyAttestation");
705
+ function reverseBytes(bytes) {
706
+ return new Uint8Array([...bytes].reverse());
707
+ }
708
+ __name(reverseBytes, "reverseBytes");
709
+ function stripLeadingZeros(bytes) {
710
+ let start = 0;
711
+ while (start < bytes.length && bytes[start] === 0) {
712
+ start++;
713
+ }
714
+ if (start === bytes.length) {
715
+ return new Uint8Array([0]);
716
+ }
717
+ return bytes.slice(start);
718
+ }
719
+ __name(stripLeadingZeros, "stripLeadingZeros");
720
+ function bytesToBigInt(bytes) {
721
+ if (bytes.length === 0) {
722
+ return 0n;
723
+ }
724
+ let result = 0n;
725
+ for (const byte of bytes) {
726
+ result = result << 8n | BigInt(byte);
727
+ }
728
+ return result;
729
+ }
730
+ __name(bytesToBigInt, "bytesToBigInt");
731
+ function bigIntToFixedBytes(value, size) {
732
+ let hex = value.toString(16);
733
+ if (hex.length % 2) {
734
+ hex = "0" + hex;
735
+ }
736
+ const bytes = new Uint8Array(size);
737
+ const hexBytes = hex.length / 2;
738
+ const startOffset = size - hexBytes;
739
+ for (let i = 0; i < hexBytes; i++) {
740
+ bytes[startOffset + i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
741
+ }
742
+ return bytes;
743
+ }
744
+ __name(bigIntToFixedBytes, "bigIntToFixedBytes");
745
+
746
+ // node_modules/@tinfoilsh/verifier/dist/sev/validation.js
747
+ var defaultValidationOptions = {
748
+ guestPolicy: {
749
+ abiMinor: 0,
750
+ abiMajor: 0,
751
+ smt: true,
752
+ migrateMa: false,
753
+ debug: false,
754
+ singleSocket: false,
755
+ cxlAllowed: false,
756
+ memAes256Xts: false,
757
+ raplDis: false,
758
+ ciphertextHidingDram: false,
759
+ pageSwapDisabled: false
760
+ },
761
+ minimumGuestSvn: 0,
762
+ minimumBuild: 21,
763
+ minimumVersion: 1 << 8 | 55,
764
+ // 1.55
765
+ minimumTcb: {
766
+ blSpl: 7,
767
+ teeSpl: 0,
768
+ snpSpl: 14,
769
+ ucodeSpl: 72
770
+ },
771
+ minimumLaunchTcb: {
772
+ blSpl: 7,
773
+ teeSpl: 0,
774
+ snpSpl: 14,
775
+ ucodeSpl: 72
776
+ },
777
+ permitProvisionalFirmware: false,
778
+ platformInfo: {
779
+ smtEnabled: true,
780
+ tsmeEnabled: true,
781
+ eccEnabled: false,
782
+ raplDisabled: false,
783
+ ciphertextHidingDramEnabled: false,
784
+ aliasCheckComplete: false,
785
+ tioEnabled: false
786
+ },
787
+ requireAuthorKey: false,
788
+ requireIdBlock: false
789
+ };
790
+ function validatePolicy(reportPolicy, required) {
791
+ if (comparePolicyVersions(required, reportPolicy) > 0) {
792
+ throw new AttestationError(`Required ABI version (${required.abiMajor}.${required.abiMinor}) is greater than report's ABI version (${reportPolicy.abiMajor}.${reportPolicy.abiMinor})`);
793
+ }
794
+ if (!required.migrateMa && reportPolicy.migrateMa) {
795
+ throw new AttestationError("Security policy violation: Migration agent is enabled but not allowed");
796
+ }
797
+ if (!required.debug && reportPolicy.debug) {
798
+ throw new AttestationError("Security policy violation: Debug mode is enabled but not allowed. The enclave must have debug disabled for production use");
799
+ }
800
+ if (!required.smt && reportPolicy.smt) {
801
+ throw new AttestationError("Security policy violation: Simultaneous multithreading (SMT) is enabled but not allowed");
802
+ }
803
+ if (!required.cxlAllowed && reportPolicy.cxlAllowed) {
804
+ throw new AttestationError("Security policy violation: CXL (Compute Express Link) is enabled but not allowed");
805
+ }
806
+ if (!required.memAes256Xts && reportPolicy.memAes256Xts) {
807
+ throw new AttestationError("Security policy violation: AES-256-XTS memory encryption mode is enabled but not allowed");
808
+ }
809
+ if (required.singleSocket && !reportPolicy.singleSocket) {
810
+ throw new AttestationError("Security policy violation: Single socket mode is required but not enabled");
811
+ }
812
+ if (required.memAes256Xts && !reportPolicy.memAes256Xts) {
813
+ throw new AttestationError("Security policy violation: AES-256-XTS memory encryption mode is required but not enabled");
814
+ }
815
+ if (required.raplDis && !reportPolicy.raplDis) {
816
+ throw new AttestationError("Security policy violation: RAPL (power monitoring) must be disabled but is enabled");
817
+ }
818
+ if (required.ciphertextHidingDram && !reportPolicy.ciphertextHidingDram) {
819
+ throw new AttestationError("Security policy violation: DRAM ciphertext hiding is required but not enabled");
820
+ }
821
+ if (required.pageSwapDisabled && !reportPolicy.pageSwapDisabled) {
822
+ throw new AttestationError("Security policy violation: Page swap must be disabled but is enabled");
823
+ }
824
+ }
825
+ __name(validatePolicy, "validatePolicy");
826
+ function comparePolicyVersions(required, report) {
827
+ if (required.abiMajor !== report.abiMajor) {
828
+ return required.abiMajor - report.abiMajor;
829
+ }
830
+ return required.abiMinor - report.abiMinor;
831
+ }
832
+ __name(comparePolicyVersions, "comparePolicyVersions");
833
+ function tcbPartsToString(tcb) {
834
+ return `TCBParts(bootloader=${tcb.blSpl}, tee=${tcb.teeSpl}, snp=${tcb.snpSpl}, microcode=${tcb.ucodeSpl})`;
835
+ }
836
+ __name(tcbPartsToString, "tcbPartsToString");
837
+ function validateReport(report, chain, options) {
838
+ if (options.guestPolicy) {
839
+ validatePolicy(report.policyParsed, options.guestPolicy);
840
+ }
841
+ if (options.minimumGuestSvn !== void 0) {
842
+ if (report.guestSvn < options.minimumGuestSvn) {
843
+ throw new AttestationError(`Guest SVN ${report.guestSvn} is less than minimum required ${options.minimumGuestSvn}`);
844
+ }
845
+ }
846
+ if (options.minimumBuild !== void 0) {
847
+ if (report.currentBuild < options.minimumBuild) {
848
+ throw new AttestationError(`Current SNP firmware build number ${report.currentBuild} is less than minimum required ${options.minimumBuild}`);
849
+ }
850
+ if (report.committedBuild < options.minimumBuild) {
851
+ throw new AttestationError(`Committed SNP firmware build number ${report.committedBuild} is less than minimum required ${options.minimumBuild}`);
852
+ }
853
+ }
854
+ if (options.minimumVersion !== void 0) {
855
+ const currentVersion = report.currentMajor << 8 | report.currentMinor;
856
+ const committedVersion = report.committedMajor << 8 | report.committedMinor;
857
+ if (currentVersion < options.minimumVersion) {
858
+ throw new AttestationError(`Current SNP firmware version ${report.currentMajor}.${report.currentMinor} is less than minimum required ${options.minimumVersion >> 8}.${options.minimumVersion & 255}`);
859
+ }
860
+ if (committedVersion < options.minimumVersion) {
861
+ throw new AttestationError(`Committed SNP firmware version ${report.committedMajor}.${report.committedMinor} is less than minimum required ${options.minimumVersion >> 8}.${options.minimumVersion & 255}`);
862
+ }
863
+ }
864
+ if (options.minimumTcb) {
865
+ const currentTcbParts = tcbFromInt(report.currentTcb);
866
+ const committedTcbParts = tcbFromInt(report.committedTcb);
867
+ const reportedTcbParts = tcbFromInt(report.reportedTcb);
868
+ if (!tcbMeetsMinimum(currentTcbParts, options.minimumTcb)) {
869
+ throw new AttestationError(`Current TCB ${tcbPartsToString(currentTcbParts)} does not meet minimum requirements ${tcbPartsToString(options.minimumTcb)}`);
870
+ }
871
+ if (!tcbMeetsMinimum(committedTcbParts, options.minimumTcb)) {
872
+ throw new AttestationError(`Committed TCB ${tcbPartsToString(committedTcbParts)} does not meet minimum requirements ${tcbPartsToString(options.minimumTcb)}`);
873
+ }
874
+ if (!tcbMeetsMinimum(reportedTcbParts, options.minimumTcb)) {
875
+ throw new AttestationError(`Reported TCB ${tcbPartsToString(reportedTcbParts)} does not meet minimum requirements ${tcbPartsToString(options.minimumTcb)}`);
876
+ }
877
+ }
878
+ chain.validateVcekTcb(tcbFromInt(report.reportedTcb));
879
+ if (options.minimumLaunchTcb) {
880
+ const launchTcbParts = tcbFromInt(report.launchTcb);
881
+ if (!tcbMeetsMinimum(launchTcbParts, options.minimumLaunchTcb)) {
882
+ throw new AttestationError(`Launch TCB ${tcbPartsToString(launchTcbParts)} does not meet minimum requirements ${tcbPartsToString(options.minimumLaunchTcb)}`);
883
+ }
884
+ }
885
+ if (options.reportData) {
886
+ if (report.reportData.length !== 64) {
887
+ throw new AttestationError(`Report data length is ${report.reportData.length}, expected 64 bytes`);
888
+ }
889
+ if (!uint8ArrayEqual(report.reportData, options.reportData)) {
890
+ throw new AttestationError(`Report data mismatch: got ${bytesToHex(report.reportData)}, expected ${bytesToHex(options.reportData)}`);
891
+ }
892
+ }
893
+ if (options.hostData) {
894
+ if (report.hostData.length !== 32) {
895
+ throw new AttestationError(`Host data length is ${report.hostData.length}, expected 32 bytes`);
896
+ }
897
+ if (!uint8ArrayEqual(report.hostData, options.hostData)) {
898
+ throw new AttestationError(`Host data mismatch: got ${bytesToHex(report.hostData)}, expected ${bytesToHex(options.hostData)}`);
899
+ }
900
+ }
901
+ if (options.measurement) {
902
+ if (report.measurement.length !== 48) {
903
+ throw new AttestationError(`Measurement length is ${report.measurement.length}, expected 48 bytes`);
904
+ }
905
+ if (!uint8ArrayEqual(report.measurement, options.measurement)) {
906
+ throw new AttestationError(`Measurement mismatch: got ${bytesToHex(report.measurement)}, expected ${bytesToHex(options.measurement)}`);
907
+ }
908
+ }
909
+ if (options.chipId) {
910
+ if (report.chipId.length !== 64) {
911
+ throw new AttestationError(`Chip ID length is ${report.chipId.length}, expected 64 bytes`);
912
+ }
913
+ if (!uint8ArrayEqual(report.chipId, options.chipId)) {
914
+ throw new AttestationError(`Chip ID mismatch: got ${bytesToHex(report.chipId)}, expected ${bytesToHex(options.chipId)}`);
915
+ }
916
+ }
917
+ if (options.imageId) {
918
+ if (report.imageId.length !== 16) {
919
+ throw new AttestationError(`Image ID length is ${report.imageId.length}, expected 16 bytes`);
920
+ }
921
+ if (!uint8ArrayEqual(report.imageId, options.imageId)) {
922
+ throw new AttestationError(`Image ID mismatch: got ${bytesToHex(report.imageId)}, expected ${bytesToHex(options.imageId)}`);
923
+ }
924
+ }
925
+ if (options.familyId) {
926
+ if (report.familyId.length !== 16) {
927
+ throw new AttestationError(`Family ID length is ${report.familyId.length}, expected 16 bytes`);
928
+ }
929
+ if (!uint8ArrayEqual(report.familyId, options.familyId)) {
930
+ throw new AttestationError(`Family ID mismatch: got ${bytesToHex(report.familyId)}, expected ${bytesToHex(options.familyId)}`);
931
+ }
932
+ }
933
+ if (options.reportId) {
934
+ if (report.reportId.length !== 32) {
935
+ throw new AttestationError(`Report ID length is ${report.reportId.length}, expected 32 bytes`);
936
+ }
937
+ if (!uint8ArrayEqual(report.reportId, options.reportId)) {
938
+ throw new AttestationError(`Report ID mismatch: got ${bytesToHex(report.reportId)}, expected ${bytesToHex(options.reportId)}`);
939
+ }
940
+ }
941
+ if (options.reportIdMa) {
942
+ if (report.reportIdMa.length !== 32) {
943
+ throw new AttestationError(`Report ID MA length is ${report.reportIdMa.length}, expected 32 bytes`);
944
+ }
945
+ if (!uint8ArrayEqual(report.reportIdMa, options.reportIdMa)) {
946
+ throw new AttestationError(`Report ID MA mismatch: got ${bytesToHex(report.reportIdMa)}, expected ${bytesToHex(options.reportIdMa)}`);
947
+ }
948
+ }
949
+ if (report.signerInfoParsed.signingKey === ReportSigner.VcekReportSigner) {
950
+ if (report.signerInfoParsed.maskChipKey && report.chipId.some((b) => b !== 0)) {
951
+ throw new AttestationError("Invalid attestation report: chip ID masking is enabled but chip ID field is not zeroed");
952
+ }
953
+ if (!report.signerInfoParsed.maskChipKey) {
954
+ chain.validateVcekHwid(report.chipId);
955
+ }
956
+ }
957
+ if (options.platformInfo) {
958
+ validatePlatformInfo(report.platformInfoParsed, options.platformInfo);
959
+ }
960
+ if (options.vmpl !== void 0) {
961
+ if (!(0 <= report.vmpl && report.vmpl <= 3)) {
962
+ throw new AttestationError(`VMPL ${report.vmpl} is not in valid range 0-3`);
963
+ }
964
+ if (report.vmpl !== options.vmpl) {
965
+ throw new AttestationError(`VMPL mismatch: got ${report.vmpl}, expected ${options.vmpl}`);
966
+ }
967
+ }
968
+ if (options.permitProvisionalFirmware) {
969
+ throw new AttestationError("Unsupported option: Provisional firmware validation is not yet implemented");
970
+ }
971
+ if (report.committedBuild !== report.currentBuild) {
972
+ throw new AttestationError(`Firmware version mismatch: Committed build (${report.committedBuild}) does not match current build (${report.currentBuild}). This may indicate provisional firmware`);
973
+ }
974
+ if (report.committedMinor !== report.currentMinor) {
975
+ throw new AttestationError(`Firmware version mismatch: Committed minor version (${report.committedMinor}) does not match current (${report.currentMinor})`);
976
+ }
977
+ if (report.committedMajor !== report.currentMajor) {
978
+ throw new AttestationError(`Firmware version mismatch: Committed major version (${report.committedMajor}) does not match current (${report.currentMajor})`);
979
+ }
980
+ if (report.committedTcb !== report.currentTcb) {
981
+ throw new AttestationError(`Firmware version mismatch: Committed TCB does not match current TCB. This may indicate provisional firmware`);
982
+ }
983
+ if (options.requireAuthorKey || options.requireIdBlock) {
984
+ throw new AttestationError("Unsupported option: ID-block and author key validation is not yet implemented");
985
+ }
986
+ }
987
+ __name(validateReport, "validateReport");
988
+ function validatePlatformInfo(reportInfo, required) {
989
+ if (reportInfo.smtEnabled && !required.smtEnabled) {
990
+ throw new AttestationError("Platform policy violation: SMT (simultaneous multithreading) is enabled but not allowed");
991
+ }
992
+ if (!reportInfo.eccEnabled && required.eccEnabled) {
993
+ throw new AttestationError("Platform policy violation: ECC memory is required but not enabled");
994
+ }
995
+ if (!reportInfo.tsmeEnabled && required.tsmeEnabled) {
996
+ throw new AttestationError("Platform policy violation: TSME (transparent SME) is required but not enabled");
997
+ }
998
+ if (!reportInfo.raplDisabled && required.raplDisabled) {
999
+ throw new AttestationError("Platform policy violation: RAPL (power monitoring) must be disabled but is enabled");
1000
+ }
1001
+ if (!reportInfo.ciphertextHidingDramEnabled && required.ciphertextHidingDramEnabled) {
1002
+ throw new AttestationError("Platform policy violation: DRAM ciphertext hiding is required but not enabled");
1003
+ }
1004
+ if (!reportInfo.aliasCheckComplete && required.aliasCheckComplete) {
1005
+ throw new AttestationError("Platform policy violation: Memory alias check is required but has not completed");
1006
+ }
1007
+ if (!reportInfo.tioEnabled && required.tioEnabled) {
1008
+ throw new AttestationError("Platform policy violation: TIO (trusted I/O) is required but not enabled");
1009
+ }
1010
+ }
1011
+ __name(validatePlatformInfo, "validatePlatformInfo");
1012
+
1013
+ // node_modules/@tinfoilsh/verifier/dist/attestation.js
1014
+ async function verifyAttestation2(doc, vcekBase64) {
1015
+ if (doc.format === PredicateType.SevGuestV2) {
1016
+ return verifySevAttestationV2(doc.body, base64ToBytes(vcekBase64));
1017
+ } else {
1018
+ throw new AttestationError(`Unsupported attestation document format: "${doc.format}". Only SEV-SNP Guest V2 format is supported`);
1019
+ }
1020
+ }
1021
+ __name(verifyAttestation2, "verifyAttestation");
1022
+ async function verifySevAttestationV2(attestationDoc, vcekDer) {
1023
+ const report = await verifySevReport(attestationDoc, true, vcekDer);
1024
+ const measurement = {
1025
+ type: PredicateType.SevGuestV2,
1026
+ registers: [bytesToHex(report.measurement)]
1027
+ };
1028
+ const keys = report.reportData;
1029
+ const tlsKeyFp = bytesToHex(keys.slice(0, 32));
1030
+ const hpkePublicKey = bytesToHex(keys.slice(32, 64));
1031
+ return {
1032
+ measurement,
1033
+ tlsPublicKeyFingerprint: tlsKeyFp,
1034
+ hpkePublicKey
1035
+ };
1036
+ }
1037
+ __name(verifySevAttestationV2, "verifySevAttestationV2");
1038
+ async function verifySevReport(attestationDoc, isCompressed, vcekDer) {
1039
+ let attDocBytes;
1040
+ try {
1041
+ attDocBytes = base64ToBytes(attestationDoc);
1042
+ } catch (e) {
1043
+ throw new AttestationError("Failed to decode attestation document: Invalid base64 encoding", { cause: e });
1044
+ }
1045
+ if (isCompressed) {
1046
+ attDocBytes = await decompressGzip(attDocBytes);
1047
+ }
1048
+ let report;
1049
+ try {
1050
+ report = new Report(attDocBytes);
1051
+ } catch (e) {
1052
+ throw new AttestationError("Failed to parse SEV-SNP attestation report", { cause: e });
1053
+ }
1054
+ const chain = await CertificateChain.fromReport(report, vcekDer);
1055
+ let res;
1056
+ try {
1057
+ res = await verifyAttestation(chain, report);
1058
+ } catch (e) {
1059
+ wrapOrThrow(e, AttestationError, "Attestation cryptographic verification failed");
1060
+ }
1061
+ if (!res) {
1062
+ throw new AttestationError("Attestation verification failed: Report signature or certificate chain is invalid");
1063
+ }
1064
+ try {
1065
+ validateReport(report, chain, defaultValidationOptions);
1066
+ } catch (e) {
1067
+ wrapOrThrow(e, AttestationError, "Attestation policy validation failed");
1068
+ }
1069
+ return report;
1070
+ }
1071
+ __name(verifySevReport, "verifySevReport");
1072
+ function base64ToBytes(base64) {
1073
+ const binaryString = atob(base64);
1074
+ const bytes = new Uint8Array(binaryString.length);
1075
+ for (let i = 0; i < binaryString.length; i++) {
1076
+ bytes[i] = binaryString.charCodeAt(i);
1077
+ }
1078
+ return bytes;
1079
+ }
1080
+ __name(base64ToBytes, "base64ToBytes");
1081
+ async function decompressGzip(data) {
1082
+ if (typeof DecompressionStream !== "undefined") {
1083
+ const stream = new Response(data.buffer).body;
1084
+ if (!stream) {
1085
+ throw new Error("Failed to create stream from data");
1086
+ }
1087
+ const decompressedStream = stream.pipeThrough(new DecompressionStream("gzip"));
1088
+ const decompressed = await new Response(decompressedStream).arrayBuffer();
1089
+ return new Uint8Array(decompressed);
1090
+ }
1091
+ const { gunzipSync } = await import("zlib");
1092
+ return new Uint8Array(gunzipSync(data));
1093
+ }
1094
+ __name(decompressGzip, "decompressGzip");
1095
+
1096
+ // node_modules/@tinfoilsh/verifier/dist/bundle.js
1097
+ var GITHUB_PROXY = "https://github-proxy.tinfoil.sh";
1098
+ var KDS = "https://kds-proxy.tinfoil.sh";
1099
+ async function assembleAttestationBundle(enclaveHost, configRepo) {
1100
+ const [attestation, digest, enclaveCert] = await Promise.all([
1101
+ withRetry(async () => {
1102
+ const doc = await fetchJson(`https://${enclaveHost}/.well-known/tinfoil-attestation`);
1103
+ return { format: doc.format, body: doc.body };
1104
+ }),
1105
+ withRetry(async () => {
1106
+ const { tag_name } = await fetchJson(`${GITHUB_PROXY}/repos/${configRepo}/releases/latest`);
1107
+ return (await fetchText(`${GITHUB_PROXY}/${configRepo}/releases/download/${tag_name}/tinfoil.hash`)).trim();
1108
+ }),
1109
+ withRetry(async () => {
1110
+ const data = await fetchJson(`https://${enclaveHost}/.well-known/tinfoil-certificate`);
1111
+ return data.certificate;
1112
+ })
1113
+ ]);
1114
+ const sigstoreBundle = await withRetry(async () => {
1115
+ const data = await fetchJson(`${GITHUB_PROXY}/repos/${configRepo}/attestations/sha256:${digest}`);
1116
+ if (!data.attestations?.[0]?.bundle) {
1117
+ throw new FetchError(`No Sigstore bundle for ${configRepo} at digest ${digest}`);
1118
+ }
1119
+ return data.attestations[0].bundle;
1120
+ });
1121
+ let report;
1122
+ try {
1123
+ report = new Report(await decompressGzip(base64ToBytes(attestation.body)));
1124
+ } catch (e) {
1125
+ wrapOrThrow(e, AttestationError, "Failed to parse attestation report");
1126
+ }
1127
+ const vcek = await withRetry(async () => {
1128
+ const tcb = tcbFromInt(report.reportedTcb);
1129
+ const chip = bytesToHex(report.chipId);
1130
+ const der = await fetchBinary(`${KDS}/vcek/v1/${report.productName}/${chip}?blSPL=${tcb.blSpl}&teeSPL=${tcb.teeSpl}&snpSPL=${tcb.snpSpl}&ucodeSPL=${tcb.ucodeSpl}`);
1131
+ let bin = "";
1132
+ for (let i = 0; i < der.length; i++)
1133
+ bin += String.fromCharCode(der[i]);
1134
+ return btoa(bin);
1135
+ });
1136
+ return {
1137
+ domain: enclaveHost,
1138
+ enclaveAttestationReport: attestation,
1139
+ digest,
1140
+ sigstoreBundle,
1141
+ vcek,
1142
+ enclaveCert
1143
+ };
1144
+ }
1145
+ __name(assembleAttestationBundle, "assembleAttestationBundle");
1146
+ var MAX_RETRIES = 2;
1147
+ async function withRetry(fn) {
1148
+ for (let i = 0; i <= MAX_RETRIES; i++) {
1149
+ try {
1150
+ return await fn();
1151
+ } catch (e) {
1152
+ if (i === MAX_RETRIES || !(e instanceof FetchError))
1153
+ throw e;
1154
+ }
1155
+ await new Promise((r) => setTimeout(r, 500 * Math.pow(2, i)));
1156
+ }
1157
+ throw new Error("unreachable");
1158
+ }
1159
+ __name(withRetry, "withRetry");
1160
+ async function fetchOk(url) {
1161
+ let response;
1162
+ try {
1163
+ response = await fetch(url);
1164
+ } catch (e) {
1165
+ throw new FetchError(`Network error: ${url}`, { cause: e });
1166
+ }
1167
+ if (!response.ok) {
1168
+ throw new FetchError(`HTTP ${response.status}: ${url}`);
1169
+ }
1170
+ return response;
1171
+ }
1172
+ __name(fetchOk, "fetchOk");
1173
+ async function fetchJson(url) {
1174
+ try {
1175
+ return await (await fetchOk(url)).json();
1176
+ } catch (e) {
1177
+ wrapOrThrow(e, FetchError, `Invalid response from ${url}`);
1178
+ }
1179
+ }
1180
+ __name(fetchJson, "fetchJson");
1181
+ async function fetchText(url) {
1182
+ try {
1183
+ return await (await fetchOk(url)).text();
1184
+ } catch (e) {
1185
+ wrapOrThrow(e, FetchError, `Invalid response from ${url}`);
1186
+ }
1187
+ }
1188
+ __name(fetchText, "fetchText");
1189
+ async function fetchBinary(url) {
1190
+ try {
1191
+ return new Uint8Array(await (await fetchOk(url)).arrayBuffer());
1192
+ } catch (e) {
1193
+ wrapOrThrow(e, FetchError, `Invalid response from ${url}`);
1194
+ }
1195
+ }
1196
+ __name(fetchBinary, "fetchBinary");
1197
+
1198
+ // node_modules/@tinfoilsh/verifier/dist/sigstore-trusted-root.js
1199
+ var sigstore_trusted_root_default = {
1200
+ "mediaType": "application/vnd.dev.sigstore.trustedroot+json;version=0.1",
1201
+ "tlogs": [
1202
+ {
1203
+ "baseUrl": "https://rekor.sigstore.dev",
1204
+ "hashAlgorithm": "SHA2_256",
1205
+ "publicKey": {
1206
+ "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==",
1207
+ "keyDetails": "PKIX_ECDSA_P256_SHA_256",
1208
+ "validFor": {
1209
+ "start": "2021-01-12T11:53:27Z"
1210
+ }
1211
+ },
1212
+ "logId": {
1213
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
1214
+ }
1215
+ },
1216
+ {
1217
+ "baseUrl": "https://log2025-1.rekor.sigstore.dev",
1218
+ "hashAlgorithm": "SHA2_256",
1219
+ "publicKey": {
1220
+ "rawBytes": "MCowBQYDK2VwAyEAt8rlp1knGwjfbcXAYPYAkn0XiLz1x8O4t0YkEhie244=",
1221
+ "keyDetails": "PKIX_ED25519",
1222
+ "validFor": {
1223
+ "start": "2025-09-23T00:00:00Z"
1224
+ }
1225
+ },
1226
+ "logId": {
1227
+ "keyId": "zxGZFVvd0FEmjR8WrFwMdcAJ9vtaY/QXf44Y1wUeP6A="
1228
+ }
1229
+ }
1230
+ ],
1231
+ "certificateAuthorities": [
1232
+ {
1233
+ "subject": {
1234
+ "organization": "sigstore.dev",
1235
+ "commonName": "sigstore"
1236
+ },
1237
+ "uri": "https://fulcio.sigstore.dev",
1238
+ "certChain": {
1239
+ "certificates": [
1240
+ {
1241
+ "rawBytes": "MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ=="
1242
+ }
1243
+ ]
1244
+ },
1245
+ "validFor": {
1246
+ "start": "2021-03-07T03:20:29Z",
1247
+ "end": "2022-12-31T23:59:59.999Z"
1248
+ }
1249
+ },
1250
+ {
1251
+ "subject": {
1252
+ "organization": "sigstore.dev",
1253
+ "commonName": "sigstore"
1254
+ },
1255
+ "uri": "https://fulcio.sigstore.dev",
1256
+ "certChain": {
1257
+ "certificates": [
1258
+ {
1259
+ "rawBytes": "MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow="
1260
+ },
1261
+ {
1262
+ "rawBytes": "MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ"
1263
+ }
1264
+ ]
1265
+ },
1266
+ "validFor": {
1267
+ "start": "2022-04-13T20:06:15Z"
1268
+ }
1269
+ }
1270
+ ],
1271
+ "ctlogs": [
1272
+ {
1273
+ "baseUrl": "https://ctfe.sigstore.dev/test",
1274
+ "hashAlgorithm": "SHA2_256",
1275
+ "publicKey": {
1276
+ "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbfwR+RJudXscgRBRpKX1XFDy3PyudDxz/SfnRi1fT8ekpfBd2O1uoz7jr3Z8nKzxA69EUQ+eFCFI3zeubPWU7w==",
1277
+ "keyDetails": "PKIX_ECDSA_P256_SHA_256",
1278
+ "validFor": {
1279
+ "start": "2021-03-14T00:00:00Z",
1280
+ "end": "2022-10-31T23:59:59.999Z"
1281
+ }
1282
+ },
1283
+ "logId": {
1284
+ "keyId": "CGCS8ChS/2hF0dFrJ4ScRWcYrBY9wzjSbea8IgY2b3I="
1285
+ }
1286
+ },
1287
+ {
1288
+ "baseUrl": "https://ctfe.sigstore.dev/2022",
1289
+ "hashAlgorithm": "SHA2_256",
1290
+ "publicKey": {
1291
+ "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiPSlFi0CmFTfEjCUqF9HuCEcYXNKAaYalIJmBZ8yyezPjTqhxrKBpMnaocVtLJBI1eM3uXnQzQGAJdJ4gs9Fyw==",
1292
+ "keyDetails": "PKIX_ECDSA_P256_SHA_256",
1293
+ "validFor": {
1294
+ "start": "2022-10-20T00:00:00Z"
1295
+ }
1296
+ },
1297
+ "logId": {
1298
+ "keyId": "3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4="
1299
+ }
1300
+ }
1301
+ ],
1302
+ "timestampAuthorities": [
1303
+ {
1304
+ "subject": {
1305
+ "organization": "sigstore.dev",
1306
+ "commonName": "sigstore-tsa-selfsigned"
1307
+ },
1308
+ "uri": "https://timestamp.sigstore.dev/api/v1/timestamp",
1309
+ "certChain": {
1310
+ "certificates": [
1311
+ {
1312
+ "rawBytes": "MIICEDCCAZagAwIBAgIUOhNULwyQYe68wUMvy4qOiyojiwwwCgYIKoZIzj0EAwMwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZDAeFw0yNTA0MDgwNjU5NDNaFw0zNTA0MDYwNjU5NDNaMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ra2Z8hKNig2T9kFjCAToGG30jky+WQv3BzL+mKvh1SKNR/UwuwsfNCg4sryoYAd8E6isovVA3M4aoNdm9QDi50Z8nTEyvqgfDPtTIwXItfiW/AFf1V7uwkbkAoj0xxco2owaDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFIn9eUOHz9BlRsMCRscsc1t9tOsDMB8GA1UdIwQYMBaAFJjsAe9/u1H/1JUeb4qImFMHic6/MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMAoGCCqGSM49BAMDA2gAMGUCMDtpsV/6KaO0qyF/UMsX2aSUXKQFdoGTptQGc0ftq1csulHPGG6dsmyMNd3JB+G3EQIxAOajvBcjpJmKb4Nv+2Taoj8Uc5+b6ih6FXCCKraSqupe07zqswMcXJTe1cExvHvvlw=="
1313
+ },
1314
+ {
1315
+ "rawBytes": "MIIB9zCCAXygAwIBAgIUV7f0GLDOoEzIh8LXSW80OJiUp14wCgYIKoZIzj0EAwMwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZDAeFw0yNTA0MDgwNjU5NDNaFw0zNTA0MDYwNjU5NDNaMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQUQNtfRT/ou3YATa6wB/kKTe70cfJwyRIBovMnt8RcJph/COE82uyS6FmppLLL1VBPGcPfpQPYJNXzWwi8icwhKQ6W/Qe2h3oebBb2FHpwNJDqo+TMaC/tdfkv/ElJB72jRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSY7AHvf7tR/9SVHm+KiJhTB4nOvzAKBggqhkjOPQQDAwNpADBmAjEAwGEGrfGZR1cen1R8/DTVMI943LssZmJRtDp/i7SfGHmGRP6gRbuj9vOK3b67Z0QQAjEAuT2H673LQEaHTcyQSZrkp4mX7WwkmF+sVbkYY5mXN+RMH13KUEHHOqASaemYWK/E"
1316
+ }
1317
+ ]
1318
+ },
1319
+ "validFor": {
1320
+ "start": "2025-07-04T00:00:00Z"
1321
+ }
1322
+ }
1323
+ ]
1324
+ };
1325
+
1326
+ // node_modules/@tinfoilsh/verifier/dist/sigstore.js
1327
+ var GitHubWorkflowRefPattern = class {
1328
+ static {
1329
+ __name(this, "GitHubWorkflowRefPattern");
1330
+ }
1331
+ constructor(pattern) {
1332
+ this.pattern = typeof pattern === "string" ? new RegExp(pattern) : pattern;
1333
+ }
1334
+ verify(cert) {
1335
+ const ext = cert.extGitHubWorkflowRef;
1336
+ if (!ext) {
1337
+ throw new AttestationError("Sigstore certificate verification failed: Missing GitHub workflow reference extension");
1338
+ }
1339
+ if (!this.pattern.test(ext.workflowRef)) {
1340
+ throw new AttestationError(`Sigstore certificate verification failed: Workflow reference "${ext.workflowRef}" does not match expected pattern (must be a tagged release)`);
1341
+ }
1342
+ }
1343
+ };
1344
+ async function verifySigstoreBundle(bundleJson, digest, repo) {
1345
+ try {
1346
+ const { SigstoreVerifier, GITHUB_OIDC_ISSUER, AllOf, OIDCIssuer, GitHubWorkflowRepository } = await import("./c-F75VRKY4.mjs");
1347
+ const verifier = new SigstoreVerifier();
1348
+ await verifier.loadSigstoreRoot(sigstore_trusted_root_default);
1349
+ const bundle = bundleJson;
1350
+ if (bundle?.verificationMaterial?.x509CertificateChain) {
1351
+ throw new AttestationError("Legacy x509CertificateChain bundle format is not supported; only the v0.3 single-certificate format is accepted");
1352
+ }
1353
+ const policy = new AllOf([
1354
+ new OIDCIssuer(GITHUB_OIDC_ISSUER),
1355
+ new GitHubWorkflowRepository(repo),
1356
+ new GitHubWorkflowRefPattern(/^refs\/tags\//)
1357
+ ]);
1358
+ const { payloadType, payload: payloadBytes } = await verifier.verifyDsse(bundle, policy);
1359
+ const payload = JSON.parse(new TextDecoder().decode(payloadBytes));
1360
+ if (payloadType !== "application/vnd.in-toto+json") {
1361
+ throw new AttestationError(`Unsupported Sigstore payload type: "${payloadType}". Only in-toto statements (application/vnd.in-toto+json) are supported`);
1362
+ }
1363
+ {
1364
+ const allowed = /* @__PURE__ */ new Set(["_type", "subject", "predicateType", "predicate"]);
1365
+ const extra = Object.keys(payload).filter((k) => !allowed.has(k));
1366
+ if (extra.length > 0) {
1367
+ throw new AttestationError(`In-toto statement has unknown top-level field(s): ${extra.sort().join(", ")}`);
1368
+ }
1369
+ }
1370
+ const predicateType = payload.predicateType;
1371
+ const predicateFields = payload.predicate;
1372
+ if (digest !== payload.subject[0].digest.sha256) {
1373
+ throw new AttestationError(`Release digest mismatch: The release digest from GitHub (${digest}) does not match the digest in the sigstore bundle (${payload.subject[0].digest.sha256})`);
1374
+ }
1375
+ let registers;
1376
+ if (!predicateFields) {
1377
+ throw new AttestationError("Invalid Sigstore bundle: Payload is missing the predicate field containing measurements");
1378
+ }
1379
+ if (predicateType === PredicateType.SnpTdxMultiplatformV1) {
1380
+ if (!predicateFields.snp_measurement) {
1381
+ throw new AttestationError("Invalid Sigstore bundle: SNP/TDX multiplatform predicate is missing the snp_measurement field");
1382
+ }
1383
+ registers = [predicateFields.snp_measurement];
1384
+ } else {
1385
+ throw new AttestationError(`Unsupported in-toto predicate type: "${predicateType}". Only SNP/TDX multiplatform V1 is supported`);
1386
+ }
1387
+ return {
1388
+ type: predicateType,
1389
+ registers
1390
+ };
1391
+ } catch (e) {
1392
+ wrapOrThrow(e, AttestationError, "Sigstore code bundle verification failed");
1393
+ }
1394
+ }
1395
+ __name(verifySigstoreBundle, "verifySigstoreBundle");
1396
+
1397
+ // node_modules/@tinfoilsh/verifier/dist/dcode.js
1398
+ var B32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
1399
+ function base32Decode(input) {
1400
+ const s = input.toUpperCase().replace(/=+$/, "");
1401
+ if (!s)
1402
+ return new Uint8Array(0);
1403
+ const out = new Uint8Array(Math.floor(s.length * 5 / 8));
1404
+ let bits = 0, val = 0, idx = 0;
1405
+ for (const c of s) {
1406
+ const i = B32.indexOf(c);
1407
+ if (i < 0)
1408
+ throw new AttestationError(`Invalid certificate data: Unexpected character "${c}" in base32-encoded field`);
1409
+ val = val << 5 | i;
1410
+ if ((bits += 5) >= 8)
1411
+ out[idx++] = val >> (bits -= 8) & 255;
1412
+ }
1413
+ return out;
1414
+ }
1415
+ __name(base32Decode, "base32Decode");
1416
+ function decodeDomains(domains, prefix) {
1417
+ const pattern = `.${prefix}.`;
1418
+ const chunks = domains.filter((d) => d.includes(pattern)).sort((a, b) => +a.slice(0, 2) - +b.slice(0, 2)).map((d) => d.split(".")[0].slice(2)).join("");
1419
+ if (!chunks)
1420
+ throw new AttestationError(`Invalid certificate: Missing expected DNS names with prefix "${prefix}"`);
1421
+ return base32Decode(chunks);
1422
+ }
1423
+ __name(decodeDomains, "decodeDomains");
1424
+ var bytesToHex2 = /* @__PURE__ */ __name((b) => [...b].map((x) => x.toString(16).padStart(2, "0")).join(""), "bytesToHex");
1425
+
1426
+ // node_modules/@tinfoilsh/verifier/dist/cert-verify.js
1427
+ function extractSANs(cert) {
1428
+ const sanExtension = cert.extension("2.5.29.17");
1429
+ if (!sanExtension) {
1430
+ return [];
1431
+ }
1432
+ const sans = [];
1433
+ const asn1 = ASN1Obj.parseBuffer(sanExtension.value);
1434
+ for (const generalName of asn1.subs) {
1435
+ if (generalName.tag.number === 2 && !generalName.tag.constructed) {
1436
+ sans.push(new TextDecoder().decode(generalName.value));
1437
+ }
1438
+ }
1439
+ return sans;
1440
+ }
1441
+ __name(extractSANs, "extractSANs");
1442
+ function getParentDomain(domain) {
1443
+ const parts = domain.split(".");
1444
+ if (parts.length <= 2) {
1445
+ return domain;
1446
+ }
1447
+ return parts.slice(1).join(".");
1448
+ }
1449
+ __name(getParentDomain, "getParentDomain");
1450
+ function domainMatchesSans(sans, expectedDomain) {
1451
+ const parentDomain = getParentDomain(expectedDomain);
1452
+ for (const san of sans) {
1453
+ if (san === expectedDomain) {
1454
+ return true;
1455
+ }
1456
+ if (san.startsWith("*.") && san.substring(2) === parentDomain && expectedDomain !== parentDomain) {
1457
+ return true;
1458
+ }
1459
+ }
1460
+ return false;
1461
+ }
1462
+ __name(domainMatchesSans, "domainMatchesSans");
1463
+ async function verifyCertificate(certPem, expectedDomain, attestationDoc, expectedHpkeKey) {
1464
+ let cert;
1465
+ try {
1466
+ cert = X509Certificate.parse(certPem);
1467
+ } catch (error) {
1468
+ throw new AttestationError(`Failed to parse enclave TLS certificate: ${error.message}`, { cause: error });
1469
+ }
1470
+ const sans = extractSANs(cert);
1471
+ if (sans.length === 0) {
1472
+ throw new AttestationError("Invalid enclave certificate: No Subject Alternative Names found");
1473
+ }
1474
+ if (!domainMatchesSans(sans, expectedDomain)) {
1475
+ throw new AttestationError(`Certificate domain mismatch: Certificate is not valid for "${expectedDomain}"`);
1476
+ }
1477
+ const hpkeSans = sans.filter((s) => s.includes(".hpke."));
1478
+ if (hpkeSans.length === 0) {
1479
+ throw new AttestationError("Invalid enclave certificate: No HPKE key embedded in Subject Alternative Names");
1480
+ }
1481
+ let hpkeKeyBytes;
1482
+ try {
1483
+ hpkeKeyBytes = decodeDomains(hpkeSans, "hpke");
1484
+ } catch (error) {
1485
+ throw new AttestationError(`Failed to extract HPKE key from certificate: ${error.message}`, { cause: error });
1486
+ }
1487
+ const hpkePublicKey = bytesToHex2(hpkeKeyBytes);
1488
+ if (hpkePublicKey !== expectedHpkeKey) {
1489
+ throw new AttestationError("HPKE key mismatch: The encryption key in the certificate does not match the attested key");
1490
+ }
1491
+ const hattSans = sans.filter((s) => s.includes(".hatt."));
1492
+ if (hattSans.length === 0) {
1493
+ throw new AttestationError("Invalid enclave certificate: No attestation hash embedded in Subject Alternative Names");
1494
+ }
1495
+ let hashBytes;
1496
+ try {
1497
+ hashBytes = decodeDomains(hattSans, "hatt");
1498
+ } catch (error) {
1499
+ throw new AttestationError(`Failed to extract attestation hash from certificate: ${error.message}`, { cause: error });
1500
+ }
1501
+ const certAttestationHash = new TextDecoder().decode(hashBytes);
1502
+ const computedHash = await hashAttestationDocument(attestationDoc);
1503
+ if (certAttestationHash !== computedHash) {
1504
+ throw new AttestationError("Attestation hash mismatch: The hash in the certificate does not match the attestation document");
1505
+ }
1506
+ return {
1507
+ hpkePublicKey,
1508
+ attestationHash: computedHash,
1509
+ dnsNames: sans
1510
+ };
1511
+ }
1512
+ __name(verifyCertificate, "verifyCertificate");
1513
+
1514
+ // node_modules/@tinfoilsh/verifier/dist/client.js
1515
+ var Verifier = class {
1516
+ static {
1517
+ __name(this, "Verifier");
1518
+ }
1519
+ constructor(options) {
1520
+ if (!options.configRepo) {
1521
+ throw new ConfigurationError("configRepo is required for Verifier");
1522
+ }
1523
+ this.serverURL = options.serverURL;
1524
+ this.configRepo = options.configRepo;
1525
+ }
1526
+ async verify() {
1527
+ if (!this.serverURL) {
1528
+ throw new ConfigurationError("serverURL is required for verify(). Use verifyBundle() with an attestation bundle instead.");
1529
+ }
1530
+ const domain = new URL(this.serverURL).hostname;
1531
+ const bundle = await assembleAttestationBundle(domain, this.configRepo);
1532
+ return this.verifyBundle(bundle);
1533
+ }
1534
+ async verifyBundle(bundle) {
1535
+ const { enclaveAttestationReport: attestationDoc, vcek, digest, sigstoreBundle, domain, enclaveCert } = bundle;
1536
+ const steps = {
1537
+ fetchDigest: { status: "success" },
1538
+ // Already fetched by caller
1539
+ verifyCode: { status: "pending" },
1540
+ verifyEnclave: { status: "pending" },
1541
+ compareMeasurements: { status: "pending" },
1542
+ verifyCertificate: { status: "pending" }
1543
+ };
1544
+ try {
1545
+ let amdVerification;
1546
+ try {
1547
+ amdVerification = await verifyAttestation2(attestationDoc, vcek);
1548
+ steps.verifyEnclave = { status: "success" };
1549
+ } catch (error) {
1550
+ steps.verifyEnclave = { status: "failed", error: error.message };
1551
+ this.saveFailedVerificationDocument(steps, domain);
1552
+ throw error;
1553
+ }
1554
+ let codeMeasurements;
1555
+ try {
1556
+ codeMeasurements = await verifySigstoreBundle(sigstoreBundle, digest, this.configRepo);
1557
+ steps.verifyCode = { status: "success" };
1558
+ } catch (error) {
1559
+ steps.verifyCode = { status: "failed", error: error.message };
1560
+ this.saveFailedVerificationDocument(steps, domain);
1561
+ throw error;
1562
+ }
1563
+ try {
1564
+ compareMeasurements(codeMeasurements, amdVerification.measurement);
1565
+ steps.compareMeasurements = { status: "success" };
1566
+ } catch (error) {
1567
+ steps.compareMeasurements = { status: "failed", error: error.message };
1568
+ this.saveFailedVerificationDocument(steps, domain);
1569
+ throw error;
1570
+ }
1571
+ try {
1572
+ await verifyCertificate(enclaveCert, domain, attestationDoc, amdVerification.hpkePublicKey || "");
1573
+ steps.verifyCertificate = { status: "success" };
1574
+ } catch (error) {
1575
+ steps.verifyCertificate = { status: "failed", error: error.message };
1576
+ this.saveFailedVerificationDocument(steps, domain);
1577
+ throw error;
1578
+ }
1579
+ this.verificationDocument = {
1580
+ configRepo: this.configRepo,
1581
+ enclaveHost: domain,
1582
+ releaseDigest: digest,
1583
+ codeMeasurement: codeMeasurements,
1584
+ enclaveMeasurement: amdVerification,
1585
+ tlsPublicKey: amdVerification.tlsPublicKeyFingerprint || "",
1586
+ hpkePublicKey: amdVerification.hpkePublicKey || "",
1587
+ codeFingerprint: await measurementFingerprint(codeMeasurements),
1588
+ enclaveFingerprint: await measurementFingerprint(amdVerification.measurement),
1589
+ selectedRouterEndpoint: domain,
1590
+ securityVerified: true,
1591
+ steps
1592
+ };
1593
+ return amdVerification;
1594
+ } catch (error) {
1595
+ if (!this.verificationDocument) {
1596
+ this.saveFailedVerificationDocument(steps, domain);
1597
+ }
1598
+ throw error;
1599
+ }
1600
+ }
1601
+ saveFailedVerificationDocument(steps, domain) {
1602
+ this.verificationDocument = {
1603
+ configRepo: this.configRepo,
1604
+ enclaveHost: domain,
1605
+ releaseDigest: "",
1606
+ codeMeasurement: { type: "", registers: [] },
1607
+ enclaveMeasurement: { measurement: { type: "", registers: [] } },
1608
+ tlsPublicKey: "",
1609
+ hpkePublicKey: "",
1610
+ codeFingerprint: "",
1611
+ enclaveFingerprint: "",
1612
+ selectedRouterEndpoint: domain,
1613
+ securityVerified: false,
1614
+ steps
1615
+ };
1616
+ }
1617
+ getVerificationDocument() {
1618
+ return this.verificationDocument;
1619
+ }
1620
+ };
1621
+
1622
+ // node_modules/tinfoil/dist/env.js
1623
+ function isBun() {
1624
+ return typeof process !== "undefined" && !!process.versions && !!process.versions.bun;
1625
+ }
1626
+ __name(isBun, "isBun");
1627
+ function isRealBrowser() {
1628
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
1629
+ return false;
1630
+ }
1631
+ if (isBun()) {
1632
+ return false;
1633
+ }
1634
+ if (typeof globalThis.Deno !== "undefined") {
1635
+ return false;
1636
+ }
1637
+ if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
1638
+ return false;
1639
+ }
1640
+ if (typeof caches !== "undefined" && caches.default !== void 0) {
1641
+ return false;
1642
+ }
1643
+ if (typeof window !== "undefined" && typeof window.document !== "undefined") {
1644
+ if (typeof navigator !== "undefined" && navigator.userAgent) {
1645
+ return true;
1646
+ }
1647
+ }
1648
+ return false;
1649
+ }
1650
+ __name(isRealBrowser, "isRealBrowser");
1651
+
1652
+ export {
1653
+ ConfigurationError,
1654
+ FetchError,
1655
+ AttestationError,
1656
+ Verifier,
1657
+ isBun,
1658
+ isRealBrowser
1659
+ };