@super-protocol/addons-tee 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/bindings/amd-sev-snp-napi-rs/amd-sev-snp-napi-rs.linux-x64-gnu.node +0 -0
  2. package/bindings/amd-sev-snp-napi-rs/index.d.ts +51 -0
  3. package/bindings/amd-sev-snp-napi-rs/index.js +339 -0
  4. package/bindings/nvidia-native/build/Release/libnvat.so.1.1.0 +0 -0
  5. package/bindings/nvidia-native/build/Release/nvidia_native.node +0 -0
  6. package/bindings/sgx-native/build/Release/libmbedcrypto_gramine.so.15 +0 -0
  7. package/bindings/sgx-native/build/Release/libmbedx509_gramine.so.6 +0 -0
  8. package/bindings/sgx-native/build/Release/libsgx_dcap_quoteverify.so.1 +0 -0
  9. package/bindings/sgx-native/build/Release/libtdx_attest.so.1 +0 -0
  10. package/bindings/sgx-native/build/Release/sgx_native.node +0 -0
  11. package/bindings/usr/lib/node_modules/node-addon-api/node_api.Makefile +6 -0
  12. package/bindings/usr/lib/node_modules/node-addon-api/nothing.target.mk +159 -0
  13. package/bindings/utils/virtee/LICENSE +201 -0
  14. package/bindings/utils/virtee/libsev.so +0 -0
  15. package/bindings/utils/virtee/snpguest +0 -0
  16. package/dist/index.d.ts +2 -1
  17. package/dist/index.js +29 -1
  18. package/dist/nvidia-native-module/nvidia-attestation.d.ts +146 -0
  19. package/dist/nvidia-native-module/nvidia-attestation.js +374 -0
  20. package/dist/nvidia-native-module/nvidia-debug-state-policy.rego +45 -0
  21. package/dist/nvidia-native-module/nvidia-detailed-policy.rego +205 -0
  22. package/dist/proto/AmdSevSnp.d.ts +194 -0
  23. package/dist/proto/AmdSevSnp.js +363 -0
  24. package/dist/sgx-native-module/consts.d.ts +24 -0
  25. package/dist/sgx-native-module/consts.js +38 -0
  26. package/dist/sgx-native-module/dcap-quote-verify.service.d.ts +12 -0
  27. package/dist/sgx-native-module/dcap-quote-verify.service.js +84 -0
  28. package/dist/sgx-native-module/enclave.service.d.ts +93 -0
  29. package/dist/sgx-native-module/enclave.service.js +211 -0
  30. package/dist/sgx-native-module/errors.d.ts +19 -0
  31. package/dist/sgx-native-module/errors.js +69 -0
  32. package/dist/sgx-native-module/helpers.d.ts +1 -0
  33. package/dist/sgx-native-module/helpers.js +50 -0
  34. package/dist/sgx-native-module/index.d.ts +9 -0
  35. package/dist/sgx-native-module/index.js +26 -0
  36. package/dist/sgx-native-module/pki.service.d.ts +50 -0
  37. package/dist/sgx-native-module/pki.service.js +74 -0
  38. package/dist/sgx-native-module/sev-snp-mrenclave.d.ts +59 -0
  39. package/dist/sgx-native-module/sev-snp-mrenclave.js +322 -0
  40. package/dist/sgx-native-module/sev-snp-schema.d.ts +22 -0
  41. package/dist/sgx-native-module/sev-snp-schema.js +24 -0
  42. package/dist/sgx-native-module/sev-snp.d.ts +127 -0
  43. package/dist/sgx-native-module/sev-snp.js +513 -0
  44. package/package.json +1 -1
@@ -0,0 +1,374 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.NvidiaAttestationService = exports.ParseGpuClaim = exports.NvidiaAttestationErrorWithLogs = exports.NvidiaAttestationError = exports.NvidiaDeviceType = exports.NVIDIA_DEBUG_STATE_POLICY_RELATIVE_PATH = exports.NVIDIA_DETAILED_POLICY_RELATIVE_PATH = exports.DEFAULT_NRAS_URL = exports.MIN_NONCE_LENGTH = void 0;
27
+ const NATIVE_MODULE_PATH = "../../bindings/nvidia-native/build/Release/nvidia_native.node";
28
+ let _nativeModule;
29
+ function getNativeModule() {
30
+ if (!_nativeModule) {
31
+ _nativeModule = require(NATIVE_MODULE_PATH);
32
+ }
33
+ return _nativeModule;
34
+ }
35
+ const promises_1 = require("fs/promises");
36
+ const path = __importStar(require("path"));
37
+ const typebox_1 = require("@sinclair/typebox");
38
+ const value_1 = require("@sinclair/typebox/value");
39
+ // ============================================================================
40
+ // CONSTANTS
41
+ // ============================================================================
42
+ exports.MIN_NONCE_LENGTH = 32;
43
+ exports.DEFAULT_NRAS_URL = "https://nras.attestation.nvidia.com";
44
+ exports.NVIDIA_DETAILED_POLICY_RELATIVE_PATH = "nvidia-detailed-policy.rego";
45
+ exports.NVIDIA_DEBUG_STATE_POLICY_RELATIVE_PATH = "nvidia-debug-state-policy.rego";
46
+ var NvidiaDeviceType;
47
+ (function (NvidiaDeviceType) {
48
+ NvidiaDeviceType[NvidiaDeviceType["GPU"] = 0] = "GPU";
49
+ NvidiaDeviceType[NvidiaDeviceType["NVSWITCH"] = 1] = "NVSWITCH";
50
+ })(NvidiaDeviceType || (exports.NvidiaDeviceType = NvidiaDeviceType = {}));
51
+ // ============================================================================
52
+ // TYPES
53
+ // ============================================================================
54
+ const NvidiaAttestationResultSchema = typebox_1.Type.Object({
55
+ success: typebox_1.Type.Boolean(),
56
+ jwt: typebox_1.Type.String(),
57
+ claims: typebox_1.Type.String(),
58
+ logs: typebox_1.Type.String(),
59
+ });
60
+ const NvidiaDeviceTopologySchema = typebox_1.Type.Object({
61
+ gpuCount: typebox_1.Type.Integer({ minimum: 0 }),
62
+ nvswitchCount: typebox_1.Type.Integer({ minimum: 0 }),
63
+ logs: typebox_1.Type.String(),
64
+ });
65
+ const NvidiaJwtVerificationResultSchema = typebox_1.Type.Object({
66
+ result: typebox_1.Type.Boolean(),
67
+ claims: typebox_1.Type.String(),
68
+ msg: typebox_1.Type.String(),
69
+ logs: typebox_1.Type.String(),
70
+ });
71
+ const NvidiaPolicyEvaluationResultSchema = typebox_1.Type.Object({
72
+ result: typebox_1.Type.Boolean(),
73
+ msg: typebox_1.Type.String(),
74
+ details: typebox_1.Type.Array(typebox_1.Type.String()),
75
+ logs: typebox_1.Type.String(),
76
+ });
77
+ const NvidiaJwtPayloadSchema = typebox_1.Type.Object({
78
+ hwmodel: typebox_1.Type.String(),
79
+ "x-nvidia-gpu-driver-version": typebox_1.Type.String(),
80
+ "x-nvidia-gpu-vbios-version": typebox_1.Type.String(),
81
+ dbgstat: typebox_1.Type.String(),
82
+ }, { additionalProperties: true });
83
+ const NvtrustGPUInfoSchema = typebox_1.Type.Object({
84
+ model: typebox_1.Type.String(),
85
+ driverVersion: typebox_1.Type.String(),
86
+ vbios: typebox_1.Type.String(),
87
+ dbgStat: typebox_1.Type.Boolean(),
88
+ });
89
+ // ============================================================================
90
+ // ERRORS
91
+ // ============================================================================
92
+ class NvidiaAttestationError extends Error {
93
+ constructor(message) {
94
+ super(message);
95
+ this.name = NvidiaAttestationError.name;
96
+ }
97
+ }
98
+ exports.NvidiaAttestationError = NvidiaAttestationError;
99
+ class NvidiaAttestationErrorWithLogs extends NvidiaAttestationError {
100
+ constructor(message, logs) {
101
+ super(message);
102
+ this.logs = logs;
103
+ this.name = NvidiaAttestationErrorWithLogs.name;
104
+ }
105
+ }
106
+ exports.NvidiaAttestationErrorWithLogs = NvidiaAttestationErrorWithLogs;
107
+ // ============================================================================
108
+ // NATIVE CLASS INTERFACE
109
+ // ============================================================================
110
+ function extractNativeLogs(error) {
111
+ if (error instanceof Error && "logs" in error && typeof error.logs === "string") {
112
+ return error.logs;
113
+ }
114
+ return undefined;
115
+ }
116
+ // ============================================================================
117
+ // SERVICE
118
+ // ============================================================================
119
+ /**
120
+ * Parses a raw claims JSON string (array of JWT payloads) into typed GPU info objects.
121
+ *
122
+ * @param claims - JSON string containing an array of NVIDIA JWT payload objects.
123
+ * @returns Array of parsed and validated GPU info objects.
124
+ * @throws NvidiaAttestationError when the input is not valid JSON, not an array,
125
+ * or any element fails schema validation.
126
+ */
127
+ function ParseGpuClaim(claims) {
128
+ let parsed;
129
+ try {
130
+ parsed = JSON.parse(claims);
131
+ }
132
+ catch {
133
+ throw new NvidiaAttestationError("Failed to parse GPU claims: invalid JSON");
134
+ }
135
+ if (!Array.isArray(parsed)) {
136
+ throw new NvidiaAttestationError("Failed to parse GPU claims: expected a JSON array");
137
+ }
138
+ return parsed.map((item, index) => {
139
+ if (!value_1.Value.Check(NvidiaJwtPayloadSchema, item)) {
140
+ throw new NvidiaAttestationError(`Failed to parse GPU claims: element at index ${index} does not match expected schema`);
141
+ }
142
+ const payload = item;
143
+ return {
144
+ model: payload.hwmodel,
145
+ driverVersion: payload["x-nvidia-gpu-driver-version"],
146
+ vbios: payload["x-nvidia-gpu-vbios-version"],
147
+ dbgStat: payload.dbgstat !== "disabled",
148
+ };
149
+ });
150
+ }
151
+ exports.ParseGpuClaim = ParseGpuClaim;
152
+ class NvidiaAttestationService {
153
+ getNvidiaDetailedPolicyPath() {
154
+ return path.join(__dirname, exports.NVIDIA_DETAILED_POLICY_RELATIVE_PATH);
155
+ }
156
+ getNvidiaDebugStatePolicyPath() {
157
+ return path.join(__dirname, exports.NVIDIA_DEBUG_STATE_POLICY_RELATIVE_PATH);
158
+ }
159
+ /**
160
+ * Loads bundled detailed NVIDIA Rego policy from package files.
161
+ *
162
+ * The policy content is cached after first successful read.
163
+ *
164
+ * @returns Rego policy text.
165
+ */
166
+ async getNvidiaDetailedPolicy() {
167
+ return this.loadCachedPolicy(this.getNvidiaDetailedPolicyPath());
168
+ }
169
+ /**
170
+ * Loads bundled debug-state NVIDIA Rego policy from package files.
171
+ *
172
+ * Checks device type, secure boot and debug status.
173
+ * The policy content is cached after first successful read.
174
+ *
175
+ * @returns Rego policy text.
176
+ */
177
+ async getNvidiaDebugStatePolicy() {
178
+ return this.loadCachedPolicy(this.getNvidiaDebugStatePolicyPath());
179
+ }
180
+ /**
181
+ * Loads a policy file using single-flight caching keyed by absolute path.
182
+ *
183
+ * Concurrent callers for the same path share one in-flight read.
184
+ * On failure the cache entry is removed so the next call retries.
185
+ */
186
+ loadCachedPolicy(policyPath) {
187
+ const cached = NvidiaAttestationService.policyCache.get(policyPath);
188
+ if (cached !== undefined) {
189
+ return cached;
190
+ }
191
+ const promise = (0, promises_1.readFile)(policyPath, "utf8").catch(() => {
192
+ NvidiaAttestationService.policyCache.delete(policyPath);
193
+ throw new NvidiaAttestationError(`Unable to load bundled NVIDIA policy from ${policyPath}`);
194
+ });
195
+ NvidiaAttestationService.policyCache.set(policyPath, promise);
196
+ return promise;
197
+ }
198
+ /**
199
+ * Creates NVIDIA attestation service instance and initializes native SDK bindings.
200
+ *
201
+ * @throws NvidiaAttestationError when native NVIDIA attestation layer cannot be initialized.
202
+ */
203
+ constructor() {
204
+ try {
205
+ const { TNvidiaAttestation } = getNativeModule();
206
+ this.native = new TNvidiaAttestation();
207
+ }
208
+ catch (error) {
209
+ if (error instanceof Error) {
210
+ throw new NvidiaAttestationError(`Failed to initialize NVIDIA attestation: ${error.message}`);
211
+ }
212
+ throw error;
213
+ }
214
+ }
215
+ /**
216
+ * Generates cryptographically secure nonce via native NVIDIA SDK.
217
+ *
218
+ * @param length - Nonce size in bytes (default: 32).
219
+ * @returns Nonce bytes.
220
+ */
221
+ async generateNonce(length = exports.MIN_NONCE_LENGTH) {
222
+ if (!Number.isInteger(length)) {
223
+ throw new NvidiaAttestationError("Nonce length must be an integer");
224
+ }
225
+ if (length < exports.MIN_NONCE_LENGTH) {
226
+ throw new NvidiaAttestationError(`Nonce length must be at least ${exports.MIN_NONCE_LENGTH}`);
227
+ }
228
+ try {
229
+ const nonce = await this.native.generateNonce(length);
230
+ if (!Buffer.isBuffer(nonce) || nonce.length !== length) {
231
+ throw new NvidiaAttestationError("Invalid nonce returned from native SDK");
232
+ }
233
+ return nonce;
234
+ }
235
+ catch (error) {
236
+ if (error instanceof NvidiaAttestationError) {
237
+ throw error;
238
+ }
239
+ if (error instanceof Error) {
240
+ throw new NvidiaAttestationErrorWithLogs(`Failed to generate nonce: ${error.message}`, extractNativeLogs(error));
241
+ }
242
+ throw new NvidiaAttestationError(`Failed to generate nonce: ${String(error)}`);
243
+ }
244
+ }
245
+ /**
246
+ * Performs GPU attestation via NVIDIA Remote Attestation Service (NRAS).
247
+ *
248
+ * @param options - Attestation options.
249
+ * @returns Attestation result (`success`, `jwt`, `claims`).
250
+ */
251
+ async attestGpuWithNRAS(options = {}) {
252
+ try {
253
+ const nonce = options.nonce ?? (await this.generateNonce());
254
+ const result = await this.native.attestGpuWithNRAS(nonce, options.serviceKey, options.nrasUrl);
255
+ if (!value_1.Value.Check(NvidiaAttestationResultSchema, result)) {
256
+ throw new NvidiaAttestationError("Invalid attestation result returned from NRAS");
257
+ }
258
+ return result;
259
+ }
260
+ catch (error) {
261
+ if (error instanceof NvidiaAttestationError) {
262
+ throw error;
263
+ }
264
+ if (error instanceof Error) {
265
+ throw new NvidiaAttestationErrorWithLogs(`Attestation failed: ${error.message}`, extractNativeLogs(error));
266
+ }
267
+ throw new NvidiaAttestationError(`Attestation failed: ${String(error)}`);
268
+ }
269
+ }
270
+ /**
271
+ * Performs NVSwitch attestation via NVIDIA Remote Attestation Service (NRAS).
272
+ *
273
+ * @param options - Attestation options.
274
+ * @returns Attestation result (`success`, `jwt`, `claims`).
275
+ */
276
+ async attestNvSwitchWithNRAS(options = {}) {
277
+ try {
278
+ const nonce = options.nonce ?? (await this.generateNonce());
279
+ const result = await this.native.attestNvSwitchWithNRAS(nonce, options.serviceKey, options.nrasUrl);
280
+ if (!value_1.Value.Check(NvidiaAttestationResultSchema, result)) {
281
+ throw new NvidiaAttestationError("Invalid NVSwitch attestation result returned from NRAS");
282
+ }
283
+ return result;
284
+ }
285
+ catch (error) {
286
+ if (error instanceof NvidiaAttestationError) {
287
+ throw error;
288
+ }
289
+ if (error instanceof Error) {
290
+ throw new NvidiaAttestationErrorWithLogs(`NVSwitch attestation failed: ${error.message}`, extractNativeLogs(error));
291
+ }
292
+ throw new NvidiaAttestationError(`NVSwitch attestation failed: ${String(error)}`);
293
+ }
294
+ }
295
+ /**
296
+ * Retrieves NVIDIA device topology (GPU and NVSwitch counts) from native layer.
297
+ *
298
+ * @returns Device topology data.
299
+ */
300
+ async getDeviceTopology() {
301
+ try {
302
+ const topology = await this.native.getDeviceTopology();
303
+ if (!value_1.Value.Check(NvidiaDeviceTopologySchema, topology)) {
304
+ throw new NvidiaAttestationError("Invalid topology returned from native SDK");
305
+ }
306
+ return topology;
307
+ }
308
+ catch (error) {
309
+ if (error instanceof NvidiaAttestationError) {
310
+ throw error;
311
+ }
312
+ if (error instanceof Error) {
313
+ throw new NvidiaAttestationErrorWithLogs(`Failed to get device topology: ${error.message}`, extractNativeLogs(error));
314
+ }
315
+ throw new NvidiaAttestationError(`Failed to get device topology: ${String(error)}`);
316
+ }
317
+ }
318
+ /**
319
+ * Verifies detached EAT JWT cryptographically via NRAS and returns decoded claims.
320
+ */
321
+ async verifyJwt(params) {
322
+ try {
323
+ const { jwt, serviceKey, nrasUrl } = params;
324
+ if (!jwt.trim()) {
325
+ throw new NvidiaAttestationError("JWT must be a non-empty string");
326
+ }
327
+ const result = await this.native.verifyJwt(jwt, serviceKey, nrasUrl);
328
+ if (!value_1.Value.Check(NvidiaJwtVerificationResultSchema, result)) {
329
+ throw new NvidiaAttestationError("Invalid JWT verification result returned from native SDK");
330
+ }
331
+ return result;
332
+ }
333
+ catch (error) {
334
+ if (error instanceof NvidiaAttestationError) {
335
+ throw error;
336
+ }
337
+ if (error instanceof Error) {
338
+ throw new NvidiaAttestationErrorWithLogs(`JWT verification failed: ${error.message}`, extractNativeLogs(error));
339
+ }
340
+ throw new NvidiaAttestationError(`JWT verification failed: ${String(error)}`);
341
+ }
342
+ }
343
+ /**
344
+ * Evaluates attestation claims against a Rego policy and returns policy diagnostics.
345
+ */
346
+ async evaluatePolicy(params) {
347
+ try {
348
+ const { claims, regoPolicy } = params;
349
+ if (!claims.trim()) {
350
+ throw new NvidiaAttestationError("Claims JSON must be a non-empty string");
351
+ }
352
+ if (!regoPolicy.trim()) {
353
+ throw new NvidiaAttestationError("Rego policy must be a non-empty string");
354
+ }
355
+ const result = await this.native.evaluatePolicy(claims, regoPolicy);
356
+ if (!value_1.Value.Check(NvidiaPolicyEvaluationResultSchema, result)) {
357
+ throw new NvidiaAttestationError("Invalid policy evaluation result returned from native SDK");
358
+ }
359
+ return result;
360
+ }
361
+ catch (error) {
362
+ if (error instanceof NvidiaAttestationError) {
363
+ throw error;
364
+ }
365
+ if (error instanceof Error) {
366
+ throw new NvidiaAttestationErrorWithLogs(`Policy evaluation failed: ${error.message}`, extractNativeLogs(error));
367
+ }
368
+ throw new NvidiaAttestationError(`Policy evaluation failed: ${String(error)}`);
369
+ }
370
+ }
371
+ }
372
+ exports.NvidiaAttestationService = NvidiaAttestationService;
373
+ NvidiaAttestationService.policyCache = new Map();
374
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnZpZGlhLWF0dGVzdGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL252aWRpYS1uYXRpdmUtbW9kdWxlL252aWRpYS1hdHRlc3RhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE1BQU0sa0JBQWtCLEdBQUcsK0RBQStELENBQUM7QUFFM0YsSUFBSSxhQUFxRixDQUFDO0FBRTFGLFNBQVMsZUFBZTtJQUNwQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDakIsYUFBYSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFFRCxPQUFPLGFBQWMsQ0FBQztBQUMxQixDQUFDO0FBRUQsMENBQXVDO0FBQ3ZDLDJDQUE2QjtBQUM3QiwrQ0FBaUQ7QUFDakQsbURBQWdEO0FBRWhELCtFQUErRTtBQUMvRSxZQUFZO0FBQ1osK0VBQStFO0FBRWxFLFFBQUEsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0FBQ3RCLFFBQUEsZ0JBQWdCLEdBQUcscUNBQXFDLENBQUM7QUFDekQsUUFBQSxvQ0FBb0MsR0FBRyw2QkFBNkIsQ0FBQztBQUNyRSxRQUFBLHVDQUF1QyxHQUFHLGdDQUFnQyxDQUFDO0FBRXhGLElBQVksZ0JBR1g7QUFIRCxXQUFZLGdCQUFnQjtJQUN4QixxREFBTyxDQUFBO0lBQ1AsK0RBQVksQ0FBQTtBQUNoQixDQUFDLEVBSFcsZ0JBQWdCLGdDQUFoQixnQkFBZ0IsUUFHM0I7QUFFRCwrRUFBK0U7QUFDL0UsUUFBUTtBQUNSLCtFQUErRTtBQUUvRSxNQUFNLDZCQUE2QixHQUFHLGNBQUksQ0FBQyxNQUFNLENBQUM7SUFDOUMsT0FBTyxFQUFFLGNBQUksQ0FBQyxPQUFPLEVBQUU7SUFDdkIsR0FBRyxFQUFFLGNBQUksQ0FBQyxNQUFNLEVBQUU7SUFDbEIsTUFBTSxFQUFFLGNBQUksQ0FBQyxNQUFNLEVBQUU7SUFDckIsSUFBSSxFQUFF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
@@ -0,0 +1,45 @@
1
+ package policy
2
+
3
+ import future.keywords.every
4
+
5
+ # Returns object at data.policy.nv_match:
6
+ # {
7
+ # "result": boolean,
8
+ # "failed_rules": string[]
9
+ # }
10
+
11
+ default nv_match := {
12
+ "result": false,
13
+ "failed_rules": ["No attestation claims provided"]
14
+ }
15
+
16
+ nv_match := {
17
+ "result": count(failed_rules) == 0,
18
+ "failed_rules": failed_rules
19
+ } {
20
+ count(input) > 0
21
+ failed_rules := sort([msg | failed_rule[msg]])
22
+ }
23
+
24
+ # --------------------
25
+ # Failed rules
26
+ # --------------------
27
+
28
+ failed_rule[sprintf("Device %d: unsupported device type (expected 'gpu')", [i])] {
29
+ some i
30
+ claim := input[i]
31
+ object.get(claim, "x-nvidia-device-type", "") != "gpu"
32
+ }
33
+
34
+ failed_rule[sprintf("Device %d: secure boot is not enabled", [i])] {
35
+ some i
36
+ claim := input[i]
37
+ object.get(claim, "secboot", false) != true
38
+ }
39
+
40
+ failed_rule[sprintf("Device %d: debug mode is not disabled (dbgstat = '%s')", [i, dbgstat])] {
41
+ some i
42
+ claim := input[i]
43
+ dbgstat := object.get(claim, "dbgstat", "")
44
+ dbgstat != "disabled"
45
+ }
@@ -0,0 +1,205 @@
1
+ package policy
2
+
3
+ import future.keywords.every
4
+
5
+ # Returns object at data.policy.nv_match:
6
+ # {
7
+ # "result": boolean,
8
+ # "failed_rules": string[]
9
+ # }
10
+
11
+ default nv_match := {
12
+ "result": false,
13
+ "failed_rules": ["No attestation claims provided"]
14
+ }
15
+
16
+ nv_match := {
17
+ "result": count(failed_rules) == 0,
18
+ "failed_rules": failed_rules
19
+ } {
20
+ count(input) > 0
21
+ failed_rules := sort([msg | failed_rule[msg]])
22
+ }
23
+
24
+ # --------------------
25
+ # Failed rules
26
+ # --------------------
27
+
28
+ failed_rule[sprintf("Device %d: measurement result is not 'success'", [i])] {
29
+ some i
30
+ claim := input[i]
31
+ object.get(claim, "measres", "") != "success"
32
+ }
33
+
34
+ failed_rule[sprintf("Device %d: unsupported device type (expected 'gpu' or 'nvswitch')", [i])] {
35
+ some i
36
+ claim := input[i]
37
+ device_type := object.get(claim, "x-nvidia-device-type", "")
38
+ device_type != "gpu"
39
+ device_type != "nvswitch"
40
+ }
41
+
42
+ # GPU: attestation report cert chain
43
+ failed_rule[sprintf("GPU %d: attestation report cert chain status is not valid", [i])] {
44
+ some i
45
+ claim := input[i]
46
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
47
+ cert := object.get(claim, "x-nvidia-gpu-attestation-report-cert-chain", {})
48
+ object.get(cert, "x-nvidia-cert-status", "") != "valid"
49
+ }
50
+
51
+ failed_rule[sprintf("GPU %d: attestation report cert chain OCSP status is not good", [i])] {
52
+ some i
53
+ claim := input[i]
54
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
55
+ cert := object.get(claim, "x-nvidia-gpu-attestation-report-cert-chain", {})
56
+ object.get(cert, "x-nvidia-cert-ocsp-status", "") != "good"
57
+ }
58
+
59
+ failed_rule[sprintf("GPU %d: attestation report cert chain OCSP nonce does not match", [i])] {
60
+ some i
61
+ claim := input[i]
62
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
63
+ cert := object.get(claim, "x-nvidia-gpu-attestation-report-cert-chain", {})
64
+ object.get(cert, "x-nvidia-cert-ocsp-nonce-matches", false) != true
65
+ }
66
+
67
+ failed_rule[sprintf("GPU %d: attestation report cert chain OCSP response is not valid", [i])] {
68
+ some i
69
+ claim := input[i]
70
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
71
+ cert := object.get(claim, "x-nvidia-gpu-attestation-report-cert-chain", {})
72
+ object.get(cert, "x-nvidia-cert-ocsp-response-valid", false) != true
73
+ }
74
+
75
+ # GPU: driver RIM cert chain
76
+ failed_rule[sprintf("GPU %d: driver RIM cert chain status is not valid", [i])] {
77
+ some i
78
+ claim := input[i]
79
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
80
+ cert := object.get(claim, "x-nvidia-gpu-driver-rim-cert-chain", {})
81
+ object.get(cert, "x-nvidia-cert-status", "") != "valid"
82
+ }
83
+
84
+ failed_rule[sprintf("GPU %d: driver RIM cert chain OCSP status is not good", [i])] {
85
+ some i
86
+ claim := input[i]
87
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
88
+ cert := object.get(claim, "x-nvidia-gpu-driver-rim-cert-chain", {})
89
+ object.get(cert, "x-nvidia-cert-ocsp-status", "") != "good"
90
+ }
91
+
92
+ failed_rule[sprintf("GPU %d: driver RIM cert chain OCSP nonce does not match", [i])] {
93
+ some i
94
+ claim := input[i]
95
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
96
+ cert := object.get(claim, "x-nvidia-gpu-driver-rim-cert-chain", {})
97
+ object.get(cert, "x-nvidia-cert-ocsp-nonce-matches", false) != true
98
+ }
99
+
100
+ failed_rule[sprintf("GPU %d: driver RIM cert chain OCSP response is not valid", [i])] {
101
+ some i
102
+ claim := input[i]
103
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
104
+ cert := object.get(claim, "x-nvidia-gpu-driver-rim-cert-chain", {})
105
+ object.get(cert, "x-nvidia-cert-ocsp-response-valid", false) != true
106
+ }
107
+
108
+ # GPU: vbios RIM cert chain
109
+ failed_rule[sprintf("GPU %d: VBIOS RIM cert chain status is not valid", [i])] {
110
+ some i
111
+ claim := input[i]
112
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
113
+ cert := object.get(claim, "x-nvidia-gpu-vbios-rim-cert-chain", {})
114
+ object.get(cert, "x-nvidia-cert-status", "") != "valid"
115
+ }
116
+
117
+ failed_rule[sprintf("GPU %d: VBIOS RIM cert chain OCSP status is not good", [i])] {
118
+ some i
119
+ claim := input[i]
120
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
121
+ cert := object.get(claim, "x-nvidia-gpu-vbios-rim-cert-chain", {})
122
+ object.get(cert, "x-nvidia-cert-ocsp-status", "") != "good"
123
+ }
124
+
125
+ failed_rule[sprintf("GPU %d: VBIOS RIM cert chain OCSP nonce does not match", [i])] {
126
+ some i
127
+ claim := input[i]
128
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
129
+ cert := object.get(claim, "x-nvidia-gpu-vbios-rim-cert-chain", {})
130
+ object.get(cert, "x-nvidia-cert-ocsp-nonce-matches", false) != true
131
+ }
132
+
133
+ failed_rule[sprintf("GPU %d: VBIOS RIM cert chain OCSP response is not valid", [i])] {
134
+ some i
135
+ claim := input[i]
136
+ object.get(claim, "x-nvidia-device-type", "") == "gpu"
137
+ cert := object.get(claim, "x-nvidia-gpu-vbios-rim-cert-chain", {})
138
+ object.get(cert, "x-nvidia-cert-ocsp-response-valid", false) != true
139
+ }
140
+
141
+ # NVSwitch: attestation report cert chain
142
+ failed_rule[sprintf("NVSwitch %d: attestation report cert chain status is not valid", [i])] {
143
+ some i
144
+ claim := input[i]
145
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
146
+ cert := object.get(claim, "x-nvidia-switch-attestation-report-cert-chain", {})
147
+ object.get(cert, "x-nvidia-cert-status", "") != "valid"
148
+ }
149
+
150
+ failed_rule[sprintf("NVSwitch %d: attestation report cert chain OCSP status is not good", [i])] {
151
+ some i
152
+ claim := input[i]
153
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
154
+ cert := object.get(claim, "x-nvidia-switch-attestation-report-cert-chain", {})
155
+ object.get(cert, "x-nvidia-cert-ocsp-status", "") != "good"
156
+ }
157
+
158
+ failed_rule[sprintf("NVSwitch %d: attestation report cert chain OCSP nonce does not match", [i])] {
159
+ some i
160
+ claim := input[i]
161
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
162
+ cert := object.get(claim, "x-nvidia-switch-attestation-report-cert-chain", {})
163
+ object.get(cert, "x-nvidia-cert-ocsp-nonce-matches", false) != true
164
+ }
165
+
166
+ failed_rule[sprintf("NVSwitch %d: attestation report cert chain OCSP response is not valid", [i])] {
167
+ some i
168
+ claim := input[i]
169
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
170
+ cert := object.get(claim, "x-nvidia-switch-attestation-report-cert-chain", {})
171
+ object.get(cert, "x-nvidia-cert-ocsp-response-valid", false) != true
172
+ }
173
+
174
+ # NVSwitch: bios RIM cert chain
175
+ failed_rule[sprintf("NVSwitch %d: BIOS RIM cert chain status is not valid", [i])] {
176
+ some i
177
+ claim := input[i]
178
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
179
+ cert := object.get(claim, "x-nvidia-switch-bios-rim-cert-chain", {})
180
+ object.get(cert, "x-nvidia-cert-status", "") != "valid"
181
+ }
182
+
183
+ failed_rule[sprintf("NVSwitch %d: BIOS RIM cert chain OCSP status is not good", [i])] {
184
+ some i
185
+ claim := input[i]
186
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
187
+ cert := object.get(claim, "x-nvidia-switch-bios-rim-cert-chain", {})
188
+ object.get(cert, "x-nvidia-cert-ocsp-status", "") != "good"
189
+ }
190
+
191
+ failed_rule[sprintf("NVSwitch %d: BIOS RIM cert chain OCSP nonce does not match", [i])] {
192
+ some i
193
+ claim := input[i]
194
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
195
+ cert := object.get(claim, "x-nvidia-switch-bios-rim-cert-chain", {})
196
+ object.get(cert, "x-nvidia-cert-ocsp-nonce-matches", false) != true
197
+ }
198
+
199
+ failed_rule[sprintf("NVSwitch %d: BIOS RIM cert chain OCSP response is not valid", [i])] {
200
+ some i
201
+ claim := input[i]
202
+ object.get(claim, "x-nvidia-device-type", "") == "nvswitch"
203
+ cert := object.get(claim, "x-nvidia-switch-bios-rim-cert-chain", {})
204
+ object.get(cert, "x-nvidia-cert-ocsp-response-valid", false) != true
205
+ }