# `extra-data` — `TPMS_ATTEST.extraData` constant-time match _(no submodules)_ ## Purpose `extraDataMatches` compares a TPM-emitted `extraData` blob (the value the TPM signed alongside the attest body) against the relying-party-recomputed `attToBeSigned` digest per W3C WebAuthn Level 3 §8.3 step 8. The function is intentionally tiny: it short-circuits on length mismatch (length is public, not a secret) and then delegates the content comparison to a caller-injected constant-time equality function. Keeping the constant- time primitive injectable lets `@suaveplan/tpm-struct` stay universal- tier (no `@suaveplan/crypto-utils` runtime dep) while letting consumers wire in whichever hardened equality their crypto stack ships. ## Features - Length short-circuit (length is not a secret). - Pluggable equality function via the `ConstantTimeEqual` type. - Zero-allocation: works directly over the supplied `Uint8Array`s. ## Usage: Basic Example ```ts import { extraDataMatches } from "@suaveplan/tpm-struct/extra-data"; declare const constantTimeEqual: (a: Uint8Array, b: Uint8Array) => boolean; if (extraDataMatches(att.extraData, recomputedDigest, constantTimeEqual)) { // attToBeSigned matched. } ``` ## Usage: Advanced Example ```ts import { constantTimeEqual } from "@suaveplan/crypto-utils"; import { extraDataMatches } from "@suaveplan/tpm-struct/extra-data"; // Compose with the rest of the WebAuthn `tpm`-attestation chain. function verifyExtraDataAndName( att: { extraData: Uint8Array; attested: { name: Uint8Array } }, recomputedAttToBeSigned: Uint8Array, recomputedName: Uint8Array ): { extraDataOk: boolean; nameOk: boolean } { return { extraDataOk: extraDataMatches( att.extraData, recomputedAttToBeSigned, constantTimeEqual ), nameOk: extraDataMatches( att.attested.name, recomputedName, constantTimeEqual ), }; } ``` ## API Reference - **`extraDataMatches(actual: Uint8Array, expected: Uint8Array, equal: ConstantTimeEqual): boolean`** — `true` if and only if `actual.length === expected.length` and `equal(actual, expected)` returns true. Returns `false` on length mismatch without invoking `equal`. - **`ConstantTimeEqual`** — `(a: Uint8Array, b: Uint8Array) => boolean`. Implementations MUST NOT short-circuit on first byte mismatch — the wall-time MUST depend only on the longer input's length. ## Implementation Notes The function deliberately does not own a constant-time-equality fallback. A naive `for` loop short-circuiting on mismatch would leak content equality through timing; a sample implementation that XOR-accumulates every byte is correct but lives in `@suaveplan/crypto-utils`. By keeping the primitive injectable, this module avoids importing a crypto package from a universal parser while still surfacing the right API shape for the WebAuthn step 8 check.