secretvm-verify 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.
package/dist/tdx.js ADDED
@@ -0,0 +1,371 @@
1
+ import crypto from "node:crypto";
2
+ import { makeResult } from "./types.js";
3
+ const INTEL_PCS_BASE = "https://pccs.scrtlabs.com/sgx/certification/v4";
4
+ // "https://api.trustedservices.intel.com/sgx/certification/v4";
5
+ // ---------------------------------------------------------------------------
6
+ // Helpers
7
+ // ---------------------------------------------------------------------------
8
+ function readU16LE(buf, off) {
9
+ return buf.readUInt16LE(off);
10
+ }
11
+ function readU32LE(buf, off) {
12
+ return buf.readUInt32LE(off);
13
+ }
14
+ /** Verify ECDSA-P256-SHA256 with raw 64-byte pubkey and 64-byte R||S sig. */
15
+ function verifyEcdsaP256(pubKeyRaw, message, sigRaw) {
16
+ // Build uncompressed point: 0x04 || X(32) || Y(32)
17
+ const uncompressed = Buffer.concat([Buffer.from([0x04]), pubKeyRaw]);
18
+ const key = crypto.createPublicKey({
19
+ key: Buffer.concat([
20
+ // DER header for EC P-256 uncompressed point
21
+ Buffer.from("3059301306072a8648ce3d020106082a8648ce3d030107034200", "hex"),
22
+ uncompressed,
23
+ ]),
24
+ format: "der",
25
+ type: "spki",
26
+ });
27
+ // Convert R||S to DER signature
28
+ const r = sigRaw.subarray(0, 32);
29
+ const s = sigRaw.subarray(32, 64);
30
+ const derSig = ecdsaRsToDer(r, s);
31
+ const verifier = crypto.createVerify("SHA256");
32
+ verifier.update(message);
33
+ try {
34
+ return verifier.verify({ key, dsaEncoding: "der" }, derSig);
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
40
+ /** Convert raw R, S buffers to DER-encoded ECDSA signature. */
41
+ function ecdsaRsToDer(r, s) {
42
+ function encodeInt(v) {
43
+ // Strip leading zeros but keep one if high bit set
44
+ let i = 0;
45
+ while (i < v.length - 1 && v[i] === 0)
46
+ i++;
47
+ let trimmed = v.subarray(i);
48
+ if (trimmed[0] & 0x80) {
49
+ trimmed = Buffer.concat([Buffer.from([0x00]), trimmed]);
50
+ }
51
+ return Buffer.concat([Buffer.from([0x02, trimmed.length]), trimmed]);
52
+ }
53
+ const ri = encodeInt(r);
54
+ const si = encodeInt(s);
55
+ return Buffer.concat([
56
+ Buffer.from([0x30, ri.length + si.length]),
57
+ ri,
58
+ si,
59
+ ]);
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // PEM cert helpers
63
+ // ---------------------------------------------------------------------------
64
+ function extractPemCerts(pem) {
65
+ const certs = [];
66
+ const re = /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g;
67
+ let m;
68
+ while ((m = re.exec(pem)) !== null) {
69
+ certs.push(new crypto.X509Certificate(m[0]));
70
+ }
71
+ return certs;
72
+ }
73
+ function verifyCertChain(certs) {
74
+ for (let i = 0; i < certs.length - 1; i++) {
75
+ if (!certs[i].checkIssued(certs[i + 1]))
76
+ return false;
77
+ try {
78
+ if (!certs[i].verify(certs[i + 1].publicKey))
79
+ return false;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ if (certs.length > 0) {
86
+ const root = certs[certs.length - 1];
87
+ try {
88
+ if (!root.verify(root.publicKey))
89
+ return false;
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ return true;
96
+ }
97
+ function extractFmspc(cert) {
98
+ // Parse the raw DER to find FMSPC OID 1.2.840.113741.1.13.1.4
99
+ const raw = Buffer.from(cert.raw);
100
+ const fmspcOid = Buffer.from("060a2a864886f84d010d0104", "hex");
101
+ const idx = raw.indexOf(fmspcOid);
102
+ if (idx < 0)
103
+ return null;
104
+ const searchStart = idx + fmspcOid.length;
105
+ for (let j = searchStart; j < Math.min(searchStart + 20, raw.length - 6); j++) {
106
+ if (raw[j] === 0x04 && raw[j + 1] === 0x06) {
107
+ return raw.subarray(j + 2, j + 8).toString("hex");
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ // ---------------------------------------------------------------------------
113
+ // TCB status
114
+ // ---------------------------------------------------------------------------
115
+ async function fetchTcbStatus(fmspc, teeTcbSvn) {
116
+ const url = `${INTEL_PCS_BASE}/tcb?fmspc=${fmspc}&type=TDX`;
117
+ const resp = await fetch(url);
118
+ if (!resp.ok)
119
+ return `PCS returned ${resp.status}`;
120
+ const body = (await resp.json());
121
+ const tcbInfo = body.tcbInfo ?? body;
122
+ for (const level of tcbInfo.tcbLevels ?? []) {
123
+ const tdxComponents = level.tcb?.tdxtcbcomponents ?? [];
124
+ let match = true;
125
+ for (let i = 0; i < tdxComponents.length; i++) {
126
+ if (i < teeTcbSvn.length && teeTcbSvn[i] < (tdxComponents[i]?.svn ?? 0)) {
127
+ match = false;
128
+ break;
129
+ }
130
+ }
131
+ if (match) {
132
+ const status = level.tcbStatus ?? "Unknown";
133
+ const date = level.tcbDate ?? "";
134
+ return date ? `${status} (as of ${date})` : status;
135
+ }
136
+ }
137
+ return "OutOfDate (no matching TCB level found)";
138
+ }
139
+ // ---------------------------------------------------------------------------
140
+ // Public
141
+ // ---------------------------------------------------------------------------
142
+ export async function checkTdxCpuAttestation(data) {
143
+ const errors = [];
144
+ const checks = {};
145
+ // Parse
146
+ let raw;
147
+ let q;
148
+ try {
149
+ raw = Buffer.from(data.trim(), "hex");
150
+ q = parseQuote(raw);
151
+ checks.quote_parsed = true;
152
+ }
153
+ catch (e) {
154
+ return makeResult("TDX", {
155
+ checks: { quote_parsed: false },
156
+ errors: [e.message],
157
+ });
158
+ }
159
+ const td = q.td;
160
+ // Cert chain
161
+ if (q.certDataType !== 5 && q.certDataType !== 6) {
162
+ errors.push(`Unsupported cert data type: ${q.certDataType}`);
163
+ checks.cert_chain_valid = false;
164
+ }
165
+ else {
166
+ const certs = extractPemCerts(q.certData.toString("ascii"));
167
+ if (certs.length < 2) {
168
+ errors.push(`Expected at least 2 certificates, got ${certs.length}`);
169
+ checks.cert_chain_valid = false;
170
+ }
171
+ else {
172
+ checks.cert_chain_valid = verifyCertChain(certs);
173
+ if (!checks.cert_chain_valid) {
174
+ errors.push("PCK certificate chain signature verification failed");
175
+ }
176
+ // QE Report Signature
177
+ const pckPubKey = certs[0].publicKey;
178
+ const qeSigDer = ecdsaRsToDer(q.qeReportSignature.subarray(0, 32), q.qeReportSignature.subarray(32, 64));
179
+ try {
180
+ const v = crypto.createVerify("SHA256");
181
+ v.update(q.qeReport);
182
+ checks.qe_report_signature_valid = v.verify({ key: pckPubKey, dsaEncoding: "der" }, qeSigDer);
183
+ }
184
+ catch {
185
+ checks.qe_report_signature_valid = false;
186
+ }
187
+ if (!checks.qe_report_signature_valid) {
188
+ errors.push("QE Report signature verification failed");
189
+ }
190
+ // Attestation key binding
191
+ const attKeyHash = crypto
192
+ .createHash("sha256")
193
+ .update(q.attestationPubKey)
194
+ .update(q.qeAuthData)
195
+ .digest();
196
+ const qeReportData = q.qeReport.subarray(320, 384);
197
+ checks.attestation_key_bound = qeReportData
198
+ .subarray(0, 32)
199
+ .equals(attKeyHash);
200
+ if (!checks.attestation_key_bound) {
201
+ errors.push("Attestation key hash does not match QE Report REPORTDATA");
202
+ }
203
+ // FMSPC
204
+ var fmspc = extractFmspc(certs[0]);
205
+ }
206
+ }
207
+ if (!checks.cert_chain_valid) {
208
+ checks.qe_report_signature_valid ??= false;
209
+ checks.attestation_key_bound = false;
210
+ }
211
+ // Quote signature
212
+ const signedData = Buffer.concat([q.rawHeader, q.rawTdReport]);
213
+ checks.quote_signature_valid = verifyEcdsaP256(q.attestationPubKey, signedData, q.quoteSignature);
214
+ if (!checks.quote_signature_valid) {
215
+ errors.push("Quote signature verification failed");
216
+ }
217
+ // TCB status
218
+ let tcbStatus = "Unknown";
219
+ if (fmspc) {
220
+ try {
221
+ tcbStatus = await fetchTcbStatus(fmspc, td.teeTcbSvn);
222
+ }
223
+ catch (e) {
224
+ tcbStatus = `Could not fetch: ${e.message}`;
225
+ }
226
+ }
227
+ const valid = !!checks.quote_parsed &&
228
+ !!checks.cert_chain_valid &&
229
+ !!checks.qe_report_signature_valid &&
230
+ !!checks.attestation_key_bound &&
231
+ !!checks.quote_signature_valid;
232
+ const report = {
233
+ version: q.version,
234
+ att_key_type: q.attKeyType,
235
+ tee_type: q.teeType,
236
+ qe_svn: q.qeSvn,
237
+ pce_svn: q.pceSvn,
238
+ qe_vendor_id: q.qeVendorId.toString("hex"),
239
+ tee_tcb_svn: td.teeTcbSvn.toString("hex"),
240
+ mr_seam: td.mrSeam.toString("hex"),
241
+ mr_td: td.mrTd.toString("hex"),
242
+ mr_config_id: td.mrConfigId.toString("hex"),
243
+ mr_owner: td.mrOwner.toString("hex"),
244
+ mr_owner_config: td.mrOwnerConfig.toString("hex"),
245
+ rt_mr0: td.rtMr0.toString("hex"),
246
+ rt_mr1: td.rtMr1.toString("hex"),
247
+ rt_mr2: td.rtMr2.toString("hex"),
248
+ rt_mr3: td.rtMr3.toString("hex"),
249
+ report_data: td.reportData.toString("hex"),
250
+ td_attributes: td.tdAttributes.toString("hex"),
251
+ xfam: td.xfam.toString("hex"),
252
+ fmspc: fmspc ?? "",
253
+ tcb_status: tcbStatus,
254
+ };
255
+ return makeResult("TDX", { valid, checks, report, errors });
256
+ }
257
+ // ---------------------------------------------------------------------------
258
+ // Quote parser (internal)
259
+ // ---------------------------------------------------------------------------
260
+ function parseQuote(raw) {
261
+ if (raw.length < 632) {
262
+ throw new Error(`Quote too short: ${raw.length} bytes (minimum 632)`);
263
+ }
264
+ const version = readU16LE(raw, 0);
265
+ const attKeyType = readU16LE(raw, 2);
266
+ const teeType = readU32LE(raw, 4);
267
+ const qeSvn = readU16LE(raw, 8);
268
+ const pceSvn = readU16LE(raw, 10);
269
+ const qeVendorId = raw.subarray(12, 28);
270
+ const userData = raw.subarray(28, 48);
271
+ const rawHeader = raw.subarray(0, 48);
272
+ if (version !== 4)
273
+ throw new Error(`Unsupported quote version: ${version}`);
274
+ if (teeType !== 0x81)
275
+ throw new Error(`Not a TDX quote (tee_type=0x${teeType.toString(16)})`);
276
+ // TD Report Body: 584 bytes at offset 48
277
+ const off = 48;
278
+ const rawTdReport = raw.subarray(off, off + 584);
279
+ const td = {
280
+ teeTcbSvn: raw.subarray(off, off + 16),
281
+ mrSeam: raw.subarray(off + 16, off + 64),
282
+ mrSignerSeam: raw.subarray(off + 64, off + 112),
283
+ seamAttributes: raw.subarray(off + 112, off + 120),
284
+ tdAttributes: raw.subarray(off + 120, off + 128),
285
+ xfam: raw.subarray(off + 128, off + 136),
286
+ mrTd: raw.subarray(off + 136, off + 184),
287
+ mrConfigId: raw.subarray(off + 184, off + 232),
288
+ mrOwner: raw.subarray(off + 232, off + 280),
289
+ mrOwnerConfig: raw.subarray(off + 280, off + 328),
290
+ rtMr0: raw.subarray(off + 328, off + 376),
291
+ rtMr1: raw.subarray(off + 376, off + 424),
292
+ rtMr2: raw.subarray(off + 424, off + 472),
293
+ rtMr3: raw.subarray(off + 472, off + 520),
294
+ reportData: raw.subarray(off + 520, off + 584),
295
+ };
296
+ // Signature data at offset 632
297
+ let soff = 636; // skip 4-byte sig_data_len
298
+ const quoteSignature = raw.subarray(soff, soff + 64);
299
+ soff += 64;
300
+ const attestationPubKey = raw.subarray(soff, soff + 64);
301
+ soff += 64;
302
+ const outerCertType = readU16LE(raw, soff);
303
+ soff += 2;
304
+ const outerCertSize = readU32LE(raw, soff);
305
+ soff += 4;
306
+ const outerCertData = raw.subarray(soff, soff + outerCertSize);
307
+ let qeReport;
308
+ let qeReportSignature;
309
+ let qeAuthData;
310
+ let certDataType;
311
+ let certData;
312
+ if (outerCertType === 6) {
313
+ let c = 0;
314
+ qeReport = outerCertData.subarray(c, c + 384);
315
+ c += 384;
316
+ qeReportSignature = outerCertData.subarray(c, c + 64);
317
+ c += 64;
318
+ const qaLen = readU16LE(outerCertData, c);
319
+ c += 2;
320
+ qeAuthData = outerCertData.subarray(c, c + qaLen);
321
+ c += qaLen;
322
+ certDataType = readU16LE(outerCertData, c);
323
+ c += 2;
324
+ const cdLen = readU32LE(outerCertData, c);
325
+ c += 4;
326
+ certData = outerCertData.subarray(c, c + cdLen);
327
+ }
328
+ else {
329
+ qeReport = outerCertData.subarray(0, 384);
330
+ qeReportSignature = outerCertData.subarray(384, 448);
331
+ let c = 448;
332
+ const qaLen = readU16LE(outerCertData, c);
333
+ c += 2;
334
+ qeAuthData = outerCertData.subarray(c, c + qaLen);
335
+ c += qaLen;
336
+ certDataType = outerCertType;
337
+ certData = outerCertData;
338
+ }
339
+ return {
340
+ version,
341
+ attKeyType,
342
+ teeType,
343
+ qeSvn,
344
+ pceSvn,
345
+ qeVendorId,
346
+ userData,
347
+ rawHeader,
348
+ td,
349
+ rawTdReport,
350
+ quoteSignature,
351
+ attestationPubKey,
352
+ qeReport,
353
+ qeReportSignature,
354
+ qeAuthData,
355
+ certDataType,
356
+ certData,
357
+ };
358
+ }
359
+ /** Parse a raw TDX quote (hex-encoded) and return measurement fields only. */
360
+ export function parseTdxQuoteFields(data) {
361
+ const raw = Buffer.from(data.trim(), "hex");
362
+ const q = parseQuote(raw);
363
+ return {
364
+ mrtd: q.td.mrTd.toString("hex"),
365
+ rtmr0: q.td.rtMr0.toString("hex"),
366
+ rtmr1: q.td.rtMr1.toString("hex"),
367
+ rtmr2: q.td.rtMr2.toString("hex"),
368
+ rtmr3: q.td.rtMr3.toString("hex"),
369
+ };
370
+ }
371
+ //# sourceMappingURL=tdx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tdx.js","sourceRoot":"","sources":["../src/tdx.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface AttestationResult {
2
+ valid: boolean;
3
+ attestationType: string;
4
+ checks: Record<string, boolean>;
5
+ report: Record<string, any>;
6
+ errors: string[];
7
+ }
8
+ export declare function makeResult(attestationType: string, overrides?: Partial<AttestationResult>): AttestationResult;
9
+ export interface AgentService {
10
+ name: string;
11
+ endpoint: string;
12
+ }
13
+ export interface AgentMetadata {
14
+ name: string;
15
+ description?: string;
16
+ supportedTrust: string[];
17
+ services: AgentService[];
18
+ }
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ export function makeResult(attestationType, overrides = {}) {
2
+ return {
3
+ valid: false,
4
+ attestationType,
5
+ checks: {},
6
+ report: {},
7
+ errors: [],
8
+ ...overrides,
9
+ };
10
+ }
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,UAAU,CACxB,eAAuB,EACvB,YAAwC,EAAE;IAE1C,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,eAAe;QACf,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;QACV,GAAG,SAAS;KACb,CAAC;AACJ,CAAC"}
package/dist/vm.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { AttestationResult } from "./types.js";
2
+ export declare function parseVmUrl(url: string): {
3
+ host: string;
4
+ port: number;
5
+ };
6
+ export declare function checkSecretVm(url: string, product?: string): Promise<AttestationResult>;
package/dist/vm.js ADDED
@@ -0,0 +1,208 @@
1
+ import crypto from "node:crypto";
2
+ import tls from "node:tls";
3
+ import { makeResult } from "./types.js";
4
+ import { checkCpuAttestation } from "./cpu.js";
5
+ import { checkNvidiaGpuAttestation } from "./nvidia.js";
6
+ import { verifyWorkload } from "./workload.js";
7
+ const SECRET_VM_PORT = 29343;
8
+ // ---------------------------------------------------------------------------
9
+ // Helpers
10
+ // ---------------------------------------------------------------------------
11
+ /** Extract YAML from an HTML-wrapped response (the VM serves docker-compose inside a &lt;pre&gt; tag with HTML-encoded entities). */
12
+ function extractDockerCompose(raw) {
13
+ let text = raw.trim();
14
+ // If wrapped in HTML, extract content from <pre>...</pre>
15
+ const preMatch = text.match(/<pre>([\s\S]*?)<\/pre>/i);
16
+ if (preMatch) {
17
+ text = preMatch[1];
18
+ }
19
+ // Decode HTML entities
20
+ text = text
21
+ .replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number(code)))
22
+ .replace(/&#x([0-9a-fA-F]+);/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
23
+ .replace(/&amp;/g, "&")
24
+ .replace(/&lt;/g, "<")
25
+ .replace(/&gt;/g, ">")
26
+ .replace(/&quot;/g, '"')
27
+ .replace(/&apos;/g, "'");
28
+ // Strip zero-width spaces and other invisible Unicode characters
29
+ text = text.replace(/[\u200B\u200C\u200D\uFEFF]/g, "");
30
+ return text;
31
+ }
32
+ export function parseVmUrl(url) {
33
+ if (!url.includes("://"))
34
+ url = `https://${url}`;
35
+ const parsed = new URL(url);
36
+ return {
37
+ host: parsed.hostname,
38
+ port: parsed.port ? Number(parsed.port) : SECRET_VM_PORT,
39
+ };
40
+ }
41
+ function getTlsCertFingerprint(host, port) {
42
+ return new Promise((resolve, reject) => {
43
+ const socket = tls.connect({ host, port, rejectUnauthorized: true }, () => {
44
+ const cert = socket.getPeerX509Certificate();
45
+ if (!cert) {
46
+ socket.destroy();
47
+ return reject(new Error("No certificate received"));
48
+ }
49
+ const fingerprint = crypto
50
+ .createHash("sha256")
51
+ .update(cert.raw)
52
+ .digest();
53
+ socket.destroy();
54
+ resolve(fingerprint);
55
+ });
56
+ socket.on("error", reject);
57
+ socket.setTimeout(10_000, () => {
58
+ socket.destroy();
59
+ reject(new Error("TLS connection timed out"));
60
+ });
61
+ });
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Public
65
+ // ---------------------------------------------------------------------------
66
+ export async function checkSecretVm(url, product = "") {
67
+ const errors = [];
68
+ const checks = {};
69
+ const report = {};
70
+ let host;
71
+ let port;
72
+ try {
73
+ ({ host, port } = parseVmUrl(url));
74
+ }
75
+ catch (e) {
76
+ return makeResult("SECRET-VM", { errors: [e.message] });
77
+ }
78
+ const baseUrl = `https://${host}:${port}`;
79
+ // 1. TLS certificate fingerprint
80
+ let tlsFingerprint;
81
+ try {
82
+ tlsFingerprint = await getTlsCertFingerprint(host, port);
83
+ checks.tls_cert_obtained = true;
84
+ report.tls_fingerprint = tlsFingerprint.toString("hex");
85
+ }
86
+ catch (e) {
87
+ errors.push(`Failed to get TLS certificate: ${e.message}`);
88
+ checks.tls_cert_obtained = false;
89
+ return makeResult("SECRET-VM", { checks, report, errors });
90
+ }
91
+ // 2. Fetch and verify CPU quote
92
+ let cpuData;
93
+ try {
94
+ const resp = await fetch(`${baseUrl}/cpu`);
95
+ if (!resp.ok)
96
+ throw new Error(`HTTP ${resp.status}`);
97
+ cpuData = await resp.text();
98
+ checks.cpu_quote_fetched = true;
99
+ }
100
+ catch (e) {
101
+ errors.push(`Failed to fetch CPU quote: ${e.message}`);
102
+ checks.cpu_quote_fetched = false;
103
+ return makeResult("SECRET-VM", { checks, report, errors });
104
+ }
105
+ const cpuResult = await checkCpuAttestation(cpuData, product);
106
+ checks.cpu_attestation_valid = cpuResult.valid;
107
+ report.cpu = cpuResult.report;
108
+ report.cpu_type = cpuResult.attestationType;
109
+ if (!cpuResult.valid) {
110
+ errors.push(...cpuResult.errors);
111
+ }
112
+ // 3. TLS binding: first 32 bytes of report_data == SHA-256(TLS cert)
113
+ const reportDataHex = cpuResult.report.report_data ?? "";
114
+ if (reportDataHex.length >= 64) {
115
+ const firstHalf = reportDataHex.slice(0, 64);
116
+ checks.tls_binding = firstHalf === tlsFingerprint.toString("hex");
117
+ if (!checks.tls_binding) {
118
+ errors.push(`TLS binding failed: report_data first half (${firstHalf.slice(0, 16)}...) ` +
119
+ `!= TLS fingerprint (${tlsFingerprint.toString("hex").slice(0, 16)}...)`);
120
+ }
121
+ }
122
+ else {
123
+ checks.tls_binding = false;
124
+ errors.push("report_data too short for TLS binding check");
125
+ }
126
+ // 4. Fetch GPU quote (optional)
127
+ let gpuPresent = false;
128
+ let gpuData = "";
129
+ try {
130
+ const resp = await fetch(`${baseUrl}/gpu`);
131
+ if (resp.ok) {
132
+ gpuData = await resp.text();
133
+ const parsed = JSON.parse(gpuData);
134
+ if ("error" in parsed) {
135
+ checks.gpu_quote_fetched = false;
136
+ }
137
+ else {
138
+ gpuPresent = true;
139
+ checks.gpu_quote_fetched = true;
140
+ }
141
+ }
142
+ else {
143
+ checks.gpu_quote_fetched = false;
144
+ }
145
+ }
146
+ catch {
147
+ checks.gpu_quote_fetched = false;
148
+ }
149
+ if (gpuPresent) {
150
+ const gpuResult = await checkNvidiaGpuAttestation(gpuData);
151
+ checks.gpu_attestation_valid = gpuResult.valid;
152
+ report.gpu = gpuResult.report;
153
+ if (!gpuResult.valid) {
154
+ errors.push(...gpuResult.errors);
155
+ }
156
+ // 5. GPU binding: second 32 bytes of report_data == GPU nonce
157
+ const gpuJson = JSON.parse(gpuData);
158
+ const gpuNonce = gpuJson.nonce ?? "";
159
+ if (reportDataHex.length >= 128) {
160
+ const secondHalf = reportDataHex.slice(64, 128);
161
+ checks.gpu_binding = secondHalf === gpuNonce;
162
+ if (!checks.gpu_binding) {
163
+ errors.push(`GPU binding failed: report_data second half (${secondHalf.slice(0, 16)}...) ` +
164
+ `!= GPU nonce (${gpuNonce.slice(0, 16)}...)`);
165
+ }
166
+ }
167
+ else {
168
+ checks.gpu_binding = false;
169
+ errors.push("report_data too short for GPU binding check");
170
+ }
171
+ }
172
+ // 6. Fetch and verify workload (docker-compose)
173
+ try {
174
+ const resp = await fetch(`${baseUrl}/docker-compose`);
175
+ if (!resp.ok)
176
+ throw new Error(`HTTP ${resp.status}`);
177
+ const dockerCompose = extractDockerCompose(await resp.text());
178
+ checks.workload_fetched = true;
179
+ const workloadResult = verifyWorkload(cpuData, dockerCompose);
180
+ checks.workload_verified = workloadResult.status === "authentic_match";
181
+ report.workload = workloadResult;
182
+ if (workloadResult.status === "authentic_mismatch") {
183
+ errors.push("Workload mismatch: VM is authentic but docker-compose does not match");
184
+ }
185
+ else if (workloadResult.status === "not_authentic") {
186
+ errors.push("Workload verification failed: not an authentic SecretVM");
187
+ }
188
+ }
189
+ catch (e) {
190
+ errors.push(`Failed to fetch workload: ${e.message}`);
191
+ checks.workload_fetched = false;
192
+ }
193
+ // Overall validity
194
+ const requiredChecks = [
195
+ checks.tls_cert_obtained,
196
+ checks.cpu_quote_fetched,
197
+ checks.cpu_attestation_valid,
198
+ checks.tls_binding,
199
+ !!checks.workload_verified,
200
+ ];
201
+ if (gpuPresent) {
202
+ requiredChecks.push(!!checks.gpu_attestation_valid);
203
+ requiredChecks.push(!!checks.gpu_binding);
204
+ }
205
+ const valid = requiredChecks.every(Boolean);
206
+ return makeResult("SECRET-VM", { valid, checks, report, errors });
207
+ }
208
+ //# sourceMappingURL=vm.js.map
package/dist/vm.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vm.js","sourceRoot":"","sources":["../src/vm.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAqB,UAAU,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,cAAc,GAAG,KAAK,CAAC;AAE7B,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,qIAAqI;AACrI,SAAS,oBAAoB,CAAC,GAAW;IACvC,IAAI,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACtB,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACvD,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;IACtB,CAAC;IACD,uBAAuB;IACvB,IAAI,GAAG,IAAI;SACR,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;SACpE,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;SAClF,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3B,iEAAiE;IACjE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,GAAG,GAAG,WAAW,GAAG,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,QAAQ;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc;KACzD,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAAY,EACZ,IAAY;IAEZ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CACxB,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,EACxC,GAAG,EAAE;YACH,MAAM,IAAI,GAAG,MAAM,CAAC,sBAAsB,EAAE,CAAC;YAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACtD,CAAC;YACD,MAAM,WAAW,GAAG,MAAM;iBACvB,UAAU,CAAC,QAAQ,CAAC;iBACpB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;iBAChB,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CACF,CAAC;QACF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE;YAC7B,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,OAAO,GAAG,EAAE;IAEZ,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAwB,EAAE,CAAC;IAEvC,IAAI,IAAY,CAAC;IACjB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,UAAU,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,IAAI,IAAI,IAAI,EAAE,CAAC;IAE1C,iCAAiC;IACjC,IAAI,cAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzD,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAChC,MAAM,CAAC,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;QACjC,OAAO,UAAU,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,gCAAgC;IAChC,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAClC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;QACjC,OAAO,UAAU,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9D,MAAM,CAAC,qBAAqB,GAAG,SAAS,CAAC,KAAK,CAAC;IAC/C,MAAM,CAAC,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC;IAC9B,MAAM,CAAC,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC;IAC5C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,qEAAqE;IACrE,MAAM,aAAa,GAAW,SAAS,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IACjE,IAAI,aAAa,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,GAAG,SAAS,KAAK,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CACT,+CAA+C,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO;gBAC1E,uBAAuB,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC;IAED,gCAAgC;IAChC,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC;QAC3C,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;gBACtB,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAClC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;QACnC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC;IACnC,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,MAAM,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,CAAC,qBAAqB,GAAG,SAAS,CAAC,KAAK,CAAC;QAC/C,MAAM,CAAC,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QAED,8DAA8D;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAW,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,IAAI,aAAa,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,GAAG,UAAU,KAAK,QAAQ,CAAC;YAC7C,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,CACT,gDAAgD,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO;oBAC5E,iBAAiB,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAC/C,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,iBAAiB,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,MAAM,aAAa,GAAG,oBAAoB,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAE/B,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC9D,MAAM,CAAC,iBAAiB,GAAG,cAAc,CAAC,MAAM,KAAK,iBAAiB,CAAC;QACvE,MAAM,CAAC,QAAQ,GAAG,cAAc,CAAC;QACjC,IAAI,cAAc,CAAC,MAAM,KAAK,oBAAoB,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;QACtF,CAAC;aAAM,IAAI,cAAc,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAClC,CAAC;IAED,mBAAmB;IACnB,MAAM,cAAc,GAAG;QACrB,MAAM,CAAC,iBAAiB;QACxB,MAAM,CAAC,iBAAiB;QACxB,MAAM,CAAC,qBAAqB;QAC5B,MAAM,CAAC,WAAW;QAClB,CAAC,CAAC,MAAM,CAAC,iBAAiB;KAC3B,CAAC;IACF,IAAI,UAAU,EAAE,CAAC;QACf,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACpD,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAE5C,OAAO,UAAU,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AACpE,CAAC"}