@reclaimprotocol/attestor-core 5.1.3 → 5.1.4

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.
@@ -1,5 +1,20 @@
1
1
  import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
2
2
  export declare const protobufPackage = "teeproto";
3
+ export declare const TLS12CBCRecordMode: {
4
+ readonly TLS12_CBC_RECORD_MODE_UNSPECIFIED: 0;
5
+ readonly TLS12_CBC_RECORD_MODE_MAC_THEN_ENCRYPT: 1;
6
+ readonly TLS12_CBC_RECORD_MODE_ENCRYPT_THEN_MAC: 2;
7
+ readonly UNRECOGNIZED: -1;
8
+ };
9
+ export type TLS12CBCRecordMode = typeof TLS12CBCRecordMode[keyof typeof TLS12CBCRecordMode];
10
+ export declare namespace TLS12CBCRecordMode {
11
+ type TLS12_CBC_RECORD_MODE_UNSPECIFIED = typeof TLS12CBCRecordMode.TLS12_CBC_RECORD_MODE_UNSPECIFIED;
12
+ type TLS12_CBC_RECORD_MODE_MAC_THEN_ENCRYPT = typeof TLS12CBCRecordMode.TLS12_CBC_RECORD_MODE_MAC_THEN_ENCRYPT;
13
+ type TLS12_CBC_RECORD_MODE_ENCRYPT_THEN_MAC = typeof TLS12CBCRecordMode.TLS12_CBC_RECORD_MODE_ENCRYPT_THEN_MAC;
14
+ type UNRECOGNIZED = typeof TLS12CBCRecordMode.UNRECOGNIZED;
15
+ }
16
+ export declare function tLS12CBCRecordModeFromJSON(object: any): TLS12CBCRecordMode;
17
+ export declare function tLS12CBCRecordModeToJSON(object: TLS12CBCRecordMode): string;
3
18
  /** Signature wrapper used everywhere */
4
19
  export declare const BodyType: {
5
20
  readonly BODY_TYPE_UNSPECIFIED: 0;
@@ -27,6 +42,13 @@ export interface ResponseRedactionRange {
27
42
  start: number;
28
43
  length: number;
29
44
  }
45
+ export interface TLS12CBCSessionBinding {
46
+ contractVersion: number;
47
+ cipherSuite: number;
48
+ recordMode: TLS12CBCRecordMode;
49
+ extendedMasterSecret: boolean;
50
+ sessionBinding: Uint8Array;
51
+ }
30
52
  export interface SignedRedactedDecryptionStream {
31
53
  redactedStream: Uint8Array;
32
54
  seqNum: number;
@@ -79,6 +101,9 @@ export interface KOutputPayload {
79
101
  sessionId: string;
80
102
  /** MPC OPRF outputs (TEE-to-TEE computation) - field 10 to match reclaim-tee */
81
103
  oprfOutputs: OPRFOutput[];
104
+ /** Signed TEE attestation generation */
105
+ attestationType: string;
106
+ tls12Cbc: TLS12CBCKOutput | undefined;
82
107
  }
83
108
  export interface TOutputPayload {
84
109
  /** NEW: Single consolidated ciphertext instead of individual packets */
@@ -91,6 +116,23 @@ export interface TOutputPayload {
91
116
  sessionId: string;
92
117
  /** MPC OPRF outputs (TEE-to-TEE computation) - field 10 to match reclaim-tee */
93
118
  oprfOutputs: OPRFOutput[];
119
+ /** Signed TEE attestation generation */
120
+ attestationType: string;
121
+ tls12Cbc: TLS12CBCTOutput | undefined;
122
+ }
123
+ export interface TLS12CBCKOutput {
124
+ binding: TLS12CBCSessionBinding | undefined;
125
+ authenticatedRedactedRequest: Uint8Array;
126
+ requestRecordsSha256: Uint8Array;
127
+ requestRedactionRanges: RequestRedactionRange[];
128
+ }
129
+ export interface TLS12CBCTOutput {
130
+ binding: TLS12CBCSessionBinding | undefined;
131
+ authenticatedRedactedResponse: Uint8Array;
132
+ responseRecordsSha256: Uint8Array;
133
+ responseRedactionRanges: ResponseRedactionRange[];
134
+ plaintextRecordLengths: number[];
135
+ closeNotify: boolean;
94
136
  }
95
137
  /** Attestation report with structured data */
96
138
  export interface AttestationReport {
@@ -130,6 +172,7 @@ export interface VerificationBundle {
130
172
  }
131
173
  export declare const RequestRedactionRange: MessageFns<RequestRedactionRange>;
132
174
  export declare const ResponseRedactionRange: MessageFns<ResponseRedactionRange>;
175
+ export declare const TLS12CBCSessionBinding: MessageFns<TLS12CBCSessionBinding>;
133
176
  export declare const SignedRedactedDecryptionStream: MessageFns<SignedRedactedDecryptionStream>;
134
177
  export declare const CertificateInfo: MessageFns<CertificateInfo>;
135
178
  export declare const HandshakeSecrets: MessageFns<HandshakeSecrets>;
@@ -137,6 +180,8 @@ export declare const Opening: MessageFns<Opening>;
137
180
  export declare const OPRFOutput: MessageFns<OPRFOutput>;
138
181
  export declare const KOutputPayload: MessageFns<KOutputPayload>;
139
182
  export declare const TOutputPayload: MessageFns<TOutputPayload>;
183
+ export declare const TLS12CBCKOutput: MessageFns<TLS12CBCKOutput>;
184
+ export declare const TLS12CBCTOutput: MessageFns<TLS12CBCTOutput>;
140
185
  export declare const AttestationReport: MessageFns<AttestationReport>;
141
186
  export declare const SignedMessage: MessageFns<SignedMessage>;
142
187
  export declare const OPRFVerificationData: MessageFns<OPRFVerificationData>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Ephemeral HTTP server that answers ACME HTTP-01 challenges. Started right
3
+ * before an order is placed and stopped as soon as the order is finalized,
4
+ * so the attestor does not keep port 80 bound during normal operation.
5
+ */
6
+ export declare class AcmeChallengeServer {
7
+ private readonly tokens;
8
+ private server?;
9
+ add(token: string, keyAuthorization: string): void;
10
+ remove(token: string): void;
11
+ start(port: number): Promise<void>;
12
+ stop(): Promise<void>;
13
+ }
@@ -0,0 +1,29 @@
1
+ import type { AttestationReport } from '../../proto/tee-bundle.ts';
2
+ /**
3
+ * Requests a custom attestation token from the Confidential Space launcher
4
+ * over the unix domain socket. Mirrors reclaim-tee's shared/gcp_attestation.go.
5
+ */
6
+ export declare function generateAttestationJwt(nonces: string[]): Promise<Uint8Array>;
7
+ export interface AttestationContext {
8
+ attestorAddress: string;
9
+ tlsCertSha256Hex: () => string | undefined;
10
+ }
11
+ /**
12
+ * Starts the background attestation refresh loop. The first attestation is
13
+ * generated synchronously so getCachedAttestationJwt() is ready by the time
14
+ * the server begins handling claims.
15
+ */
16
+ export declare function startAttestationRefresh(ctx: AttestationContext): Promise<void>;
17
+ export declare function stopAttestationRefresh(): void;
18
+ /**
19
+ * Returns the currently-cached attestation JWT bytes, or undefined if no
20
+ * attestation has been generated yet or the cache has expired without a
21
+ * successful refresh.
22
+ */
23
+ export declare function getCachedAttestationJwt(): Uint8Array | undefined;
24
+ /**
25
+ * Returns an AttestationReport ready to embed in a claim response, or
26
+ * undefined when no attestation is available (i.e. attestor is not running
27
+ * inside a TEE, or the refresh loop has not produced one yet).
28
+ */
29
+ export declare function makeClaimAttestation(): AttestationReport | undefined;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Brings the attestor up in TEE mode:
3
+ * 1. Pull signing/OPRF secrets from GCP Secret Manager into process.env.
4
+ * 2. Load (or obtain via ACME) the TLS cert and start the renewal loop.
5
+ * 3. Start the attestation refresh loop, with the public key + cert hash
6
+ * as nonces.
7
+ *
8
+ * Must run before #src/server/index.ts is imported, since modules in that
9
+ * tree read PRIVATE_KEY at module load.
10
+ */
11
+ export declare function bootstrapTee(): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import tls from 'tls';
2
+ export interface CertManagerConfig {
3
+ projectId: string;
4
+ domain: string;
5
+ email: string;
6
+ directoryUrl: string;
7
+ httpChallengePort: number;
8
+ }
9
+ export interface ActiveCertificate {
10
+ certPem: string;
11
+ keyPem: string;
12
+ notAfter: Date;
13
+ sha256Hex: string;
14
+ secureContext: tls.SecureContext;
15
+ }
16
+ /**
17
+ * Bootstraps the TLS certificate. Tries Secret Manager first; if absent or
18
+ * expiring within the renewal window, runs ACME against the configured
19
+ * directory URL and persists the result.
20
+ */
21
+ export declare function bootstrapCertificate(cfg: CertManagerConfig): Promise<ActiveCertificate>;
22
+ export declare function startRenewalLoop(cfg: CertManagerConfig): void;
23
+ export declare function stopRenewalLoop(): void;
24
+ export declare function getActiveCertificate(): ActiveCertificate | undefined;
@@ -0,0 +1,23 @@
1
+ import type { LogLevel } from '../../types/index.ts';
2
+ interface CloudLoggingOptions {
3
+ projectId: string;
4
+ logName: string;
5
+ level?: LogLevel;
6
+ }
7
+ /**
8
+ * Replaces the default pino logger with one that forwards every log line
9
+ * to GCP Cloud Logging under the given log name. Idempotent.
10
+ *
11
+ * Probes the Cloud Logging client first by writing a no-op entry; if
12
+ * authentication or transport fails, leaves the default stdout logger in
13
+ * place rather than crashing the process. On Confidential Space VMs the
14
+ * launcher's `tee-container-log-redirect` ships stdout to Cloud Logging
15
+ * anyway, so the worst case is logs appear under
16
+ * `confidential-space-launcher` rather than the configured `logName`.
17
+ *
18
+ * We also install a process-wide `unhandledRejection` filter that
19
+ * swallows errors originating in `@google-cloud/logging`, since the SDK
20
+ * has internal lazy gRPC init that escapes our local `.catch()`.
21
+ */
22
+ export declare function installCloudLogging(opts: CloudLoggingOptions): void;
23
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Fetches the attestor's signing key and OPRF key material from GCP
3
+ * Secret Manager and writes them into process.env, so that the rest of
4
+ * the server (which reads these via getEnvVariable at module load) sees
5
+ * them as if they had been set in the environment.
6
+ *
7
+ * Must be called before any module that reads PRIVATE_KEY / TOPRF_* is
8
+ * imported, otherwise the reads happen before the values are populated.
9
+ */
10
+ export declare function loadSecretsIntoEnv(projectId: string): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export declare function accessLatestSecret(projectId: string, secretId: string): Promise<Uint8Array>;
2
+ export declare function createSecretIfNotExists(projectId: string, secretId: string): Promise<void>;
3
+ export declare function addSecretVersion(projectId: string, secretId: string, payload: Uint8Array): Promise<void>;
@@ -12,4 +12,6 @@ import { type SevSnpEnvelope } from '../../../server/utils/sev-snp/verify.ts';
12
12
  export declare function verifyGcpLeg(env: SevSnpEnvelope, bound: Buffer, now: Date): {
13
13
  app: string;
14
14
  base: string;
15
+ pcrs: Map<number, Buffer>;
16
+ eventLog: Buffer;
15
17
  };
@@ -9,6 +9,7 @@
9
9
  export interface NitroTpmResult {
10
10
  pcr8: Buffer;
11
11
  pcr11: Buffer;
12
+ pcrs: Map<number, Buffer>;
12
13
  userData: Buffer;
13
14
  }
14
15
  /**
@@ -0,0 +1,9 @@
1
+ type Bank = 'sha256' | 'sha384';
2
+ export interface SecureBootEventLogResult {
3
+ eventLogBytes: number;
4
+ verifiedEvents: number;
5
+ postSeparatorUses: number;
6
+ releasePublicKeySha256: string;
7
+ }
8
+ export declare function verifySecureBootEventLog(raw: Uint8Array, quotedPcrs: Map<number, Buffer>, bank: Bank): SecureBootEventLogResult;
9
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -8,6 +8,8 @@
8
8
  */
9
9
  export declare const SEV_TAG_GCP = 1;
10
10
  export declare const SEV_TAG_AWS = 2;
11
+ export declare const SECURE_BOOT_TAG_GCP = 3;
12
+ export declare const SECURE_BOOT_TAG_AWS = 4;
11
13
  export declare const SNP_APP_PREFIX = "snp-app:";
12
14
  export declare const SNP_BASE_PREFIX = "snp-base:";
13
15
  export declare const APP_PCR = 8;
@@ -17,6 +19,8 @@ export interface SevSnpEnvelope {
17
19
  tpm?: Uint8Array;
18
20
  nitrotpm?: Uint8Array;
19
21
  sev?: Uint8Array;
22
+ sev2?: Uint8Array;
23
+ eventlog?: Uint8Array;
20
24
  nonces?: string[];
21
25
  }
22
26
  export interface SevSnpResult {
@@ -37,6 +41,10 @@ export declare function parseSevSnpEnvelope(att: Uint8Array): Promise<{
37
41
  * what makes the carried nonces unforgeable.
38
42
  */
39
43
  export declare function snpNonceCommitment(nonces: string[]): Buffer;
44
+ /** Commits the AMD report to the exact NitroTPM evidence from the same broker. */
45
+ export declare function awsCombinedV2ReportData(bound: Uint8Array, appHash: Uint8Array, nitroTpm: Uint8Array): Buffer;
46
+ /** Only an absent value or an explicit 0 keeps the AWS expansion path active. */
47
+ export declare function requireAwsAttestationV2(value?: string | undefined): boolean;
40
48
  /**
41
49
  * expectedPCR8: the value the loader produces by extending a pristine (all-zero)
42
50
  * PCR 8 once with alg(appHash), i.e. alg(0^algSize || alg(appHash)). GCP uses the
@@ -57,3 +65,14 @@ export declare function extractTeeKeyFromNonces(nonces: string[]): {
57
65
  * `now` defaults to the real clock; tests may pass a time in the leaf window.
58
66
  */
59
67
  export declare function verifyCombinedSevSnp(att: Uint8Array, now?: Date): Promise<SevSnpResult>;
68
+ /**
69
+ * Verifies the additive Secure Boot claim format. The cloud-specific leg is
70
+ * unchanged from SEV2; only after it succeeds do we replay PCR 4/7/11 and pin R.
71
+ */
72
+ export declare function verifyCombinedSecureBoot(att: Uint8Array, now?: Date): Promise<SevSnpResult>;
73
+ /**
74
+ * Restores the distinct Secure Boot tag on legacy-compatible client evidence.
75
+ * Call this only when an authenticated protocol value requires Secure Boot;
76
+ * the legacy tag alone is intentionally not a generation signal.
77
+ */
78
+ export declare function secureBootAttestationFromCompatibleWire(att: Uint8Array): Buffer;
@@ -0,0 +1,3 @@
1
+ import type { KOutputPayload, TOutputPayload, VerificationBundle } from '../../proto/tee-bundle.ts';
2
+ export type TeeProtocolMode = 'split-aead' | 'tls12-cbc';
3
+ export declare function validateTeeTranscriptContract(bundle: VerificationBundle, kPayload: KOutputPayload, tPayload: TOutputPayload): TeeProtocolMode;
@@ -9,6 +9,7 @@
9
9
  import type { KOutputPayload, TOutputPayload } from '../../proto/tee-bundle.ts';
10
10
  import type { OprfVerificationResult } from '../../server/utils/tee-oprf-verification.ts';
11
11
  import type { Logger } from '../../types/general.ts';
12
+ export declare const MAX_TEE_OPRF_MPC_OUTPUTS = 20;
12
13
  /**
13
14
  * Verifies OPRF MPC outputs from TEE_K and TEE_T match
14
15
  * Returns verified outputs for transcript replacement (same format as ZK OPRF)
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import type { SignedMessage } from '../../proto/tee-bundle.ts';
6
6
  import { KOutputPayload, TOutputPayload } from '../../proto/tee-bundle.ts';
7
+ import type { TeeProtocolMode } from '../../server/utils/tee-cbc-contract.ts';
7
8
  import type { Logger } from '../../types/general.ts';
8
9
  export interface TeeBundleData {
9
10
  teekSigned: SignedMessage;
@@ -13,6 +14,7 @@ export interface TeeBundleData {
13
14
  teekPcr0: string;
14
15
  teetPcr0: string;
15
16
  teeSessionId: string;
17
+ protocolMode: TeeProtocolMode;
16
18
  }
17
19
  export interface TeeSignatureVerificationResult {
18
20
  isValid: boolean;
@@ -26,3 +28,4 @@ export interface TeeSignatureVerificationResult {
26
28
  * @returns Validated TEE bundle data
27
29
  */
28
30
  export declare function verifyTeeBundle(bundleBytes: Uint8Array, logger: Logger): Promise<TeeBundleData>;
31
+ export declare function resolveSignedAttestationType(signedType: string, reportType: string): string;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * GCP attestation validation utilities.
3
+ *
4
+ * Validates JWT attestation tokens from GCP Confidential Computing
5
+ * (Confidential Space). Browser-safe: uses `@peculiar/x509` for chain
6
+ * verification and `globalThis.crypto.subtle` for JWT signature
7
+ * verification. Both are available in Node 19+ and modern browsers.
8
+ */
9
+ import type { Logger } from '../types/general.ts';
10
+ export interface GcpValidationResult {
11
+ isValid: boolean;
12
+ errors: string[];
13
+ ethAddress?: Uint8Array;
14
+ userDataType?: string;
15
+ pcr0?: string;
16
+ envVars?: Record<string, string>;
17
+ }
18
+ export declare function validateGcpAttestationAndExtractKey(attestation: Uint8Array | string, logger?: Logger): Promise<GcpValidationResult>;
19
+ /**
20
+ * Extracts the container image digest from a previously-validated GCP
21
+ * attestation token. Re-validates the JWT before reading.
22
+ */
23
+ export declare function extractImageDigestFromGCPAttestation(token: Uint8Array | string, logger?: Logger): Promise<string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reclaimprotocol/attestor-core",
3
- "version": "5.1.3",
3
+ "version": "5.1.4",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "imports": {
@@ -92,8 +92,8 @@
92
92
  "@peculiar/asn1-x509": "^2.6.1",
93
93
  "@peculiar/webcrypto": "^1.5.0",
94
94
  "@peculiar/x509": "^1.14.3",
95
- "@reclaimprotocol/tls": "^0.1.3",
96
- "@reclaimprotocol/zk-symmetric-crypto": "^5.1.3",
95
+ "@reclaimprotocol/tls": "^0.1.4",
96
+ "@reclaimprotocol/zk-symmetric-crypto": "^5.1.6",
97
97
  "ajv": "^8.18.0",
98
98
  "bs58": "^6.0.0",
99
99
  "canonicalize": "^2.1.0",