/** * TPM 2.0 quote verifier — the core judgment function this package * exports. * * Flow (matches the TCG verification recipe for TPM2_Quote, plus the * motebit-specific identity-key binding step): * * 1. Split the receipt into (tpmsAttestBase64, signatureBase64, * akCertDerBase64, intermediateCertsDerBase64Joined). * 2. Parse the TPMS_ATTEST bytes. Assert magic = TPM_GENERATED_VALUE * and type = TPM_ST_ATTEST_QUOTE. * 3. Parse the AK leaf + any intermediates as X.509. Walk the chain * from AK leaf → intermediate → vendor root. Every non-leaf must * carry `basicConstraints.cA === true`. Every signature must * verify under its issuer's public key. Every validity window * must include `now`. The terminal cert's DER must byte-equal * ONE of the pinned vendor roots. * 4. Verify the AK signature over SHA-256(TPMS_ATTEST_BYTES) using * the AK certificate's public key. * 5. Re-derive `extraData` from the JCS-canonical body * {attested_at, device_id, identity_public_key, motebit_id, * platform: "tpm", version: "1"} — SHA-256 of the canonical body * — and byte-compare against the transmitted `extraData`. This is * the cross-stack binding — without it every other step would * prove only that *some* TPM-enrolled device did something, not * that the Ed25519 key the credential subject claims is bound * to that device. * * The TPM's own EK certificate provisioning path is NOT verified here * — that would require contacting the vendor's EK provisioning service * and is out of scope for v1. The outer chain + extraData binding is * enough for third-party self-verification of TPM-attested identity. */ import type { HardwareAttestationClaim } from "@motebit/protocol"; export interface TpmVerifyOptions { /** * Ed25519 identity key (lowercase hex) the motebit VC claims. The * TPM quote's extraData MUST bind this key. */ readonly expectedIdentityPublicKeyHex: string; /** * motebit_id from the credential subject. Participates in the JCS * body the Rust bridge hashes into extraData; re-derived here and * byte-compared against the transmitted extraData so a malicious * native client cannot substitute a different body. */ readonly expectedMotebitId?: string; /** * device_id from the credential subject. Same binding role as * `expectedMotebitId`. */ readonly expectedDeviceId?: string; /** * `attested_at` (unix ms) from the credential subject. Same binding * role as `expectedMotebitId`. */ readonly expectedAttestedAt?: number; /** * Override the pinned vendor roots. Tests fabricate their own root * so chain verification exercises the same code path without needing * real vendor-signed leaves. Defaults to `DEFAULT_PINNED_TPM_ROOTS`. */ readonly rootPems?: readonly string[]; /** * Clock for chain-validity checks. Defaults to `Date.now`. Tests * inject a fixed clock to keep certificate validity windows * deterministic. */ readonly now?: () => number; } export interface TpmVerifyError { readonly message: string; } export interface TpmVerifyResult { readonly valid: boolean; readonly cert_chain_valid: boolean; readonly quote_signature_valid: boolean; readonly quote_shape_valid: boolean; readonly identity_bound: boolean; readonly errors: readonly TpmVerifyError[]; } /** * TPM 2.0 quote verifier. * * Pure. No network. No filesystem. Deterministic given `now()`. * * `claim` is the `HardwareAttestationClaim` as carried inside the * motebit AgentTrustCredential. For TPM, the `attestation_receipt` * field is expected to be four base64url segments separated by `.`: * * `{tpmsAttestB64}.{signatureB64}.{akCertDerB64}.{intermediatesJoinedB64}` * * `intermediatesJoinedB64` may itself be an empty segment (`""`) when * the AK cert chains directly to a pinned root, or a `,`-joined * concatenation of base64url-encoded DER intermediates in leaf- * proximal-first order otherwise. */ export declare function verifyTpmQuote(claim: HardwareAttestationClaim, opts: TpmVerifyOptions): Promise; //# sourceMappingURL=verify.d.ts.map