first commit
This commit is contained in:
133
docs/security-stack/security/tpm-struct/README.md
Normal file
133
docs/security-stack/security/tpm-struct/README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# @suaveplan/tpm-struct - Zero-dep, universal TPM 2.0 attestation-structure parser/serialiser. Decodes TPMS_ATTEST (TCG Part 2 §10.12) and TPMT_PUBLIC (§12.2) byte strings, computes canonical TPM names (Part 1 §16), and underpins WebAuthn 'tpm'-format attestation verification.
|
||||
|
||||
## Summary
|
||||
|
||||
Zero-runtime-dep TPM 2.0 attestation-structure parser
|
||||
and serialiser. Decodes `TPMS_ATTEST` (TCG TPM 2.0 Library Part 2
|
||||
§10.12), decodes `TPMT_PUBLIC` (§12.2), and computes canonical TPM 2.0
|
||||
name digests per TCG Part 1 §16. Underpins WebAuthn `tpm`-format
|
||||
attestation verification (W3C WebAuthn L3 §8.3) and every future TPM
|
||||
2.0 attestation context (AIK enrollment, remote attestation, vTPM
|
||||
provisioning) without dragging in a TPM driver, Node-only runtime, or
|
||||
CommonJS legacy bridge.
|
||||
|
||||
The package is buffer-only: it neither imports a hash library nor
|
||||
talks to a TPM device. Callers inject `HashLike` for `computeTpmtPublicName`
|
||||
and `ConstantTimeEqual` for `extraDataMatches`, which keeps the
|
||||
package free of crypto-engine selection while making the right shape
|
||||
available at the WebAuthn step-5/step-8 call site.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [alg](./src/alg/alg.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [alg](./src/alg/alg.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [serialize](./src/attest/serialize.md) — `serializeTpmsAttest` re-emits a parsed `TpmsAttest` value as the TCG-canonical byte string per Library Part 2 §10.12.…
|
||||
- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [errors](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [error-codes](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [object-attributes](./src/public/object-attributes.md) — `decodeObjectAttributes` (and its inverse `encodeObjectAttributes`) walk the 32-bit `TPMA_OBJECT` bitfield documented i…
|
||||
- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [serialize](./src/public/serialize.md) — `serializeTpmtPublic` re-emits a parsed `TpmtPublic` value as the TCG-canonical byte string per Library Part 2 §12.2. I…
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
<!-- end:auto-docs --> - [alg](./src/alg/alg.md) — <!-- begin:auto-docs --> _(no submodules)_- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [serialize](./src/attest/serialize.md) — `serializeTpmsAttest` re-emits a parsed `TpmsAttest` value as the TCG-canonical byte string per Library Part 2 §10.12.…
|
||||
- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [object-attributes](./src/public/object-attributes.md) — `decodeObjectAttributes` (and its inverse `encodeObjectAttributes`) walk the 32-bit `TPMA_OBJECT` bitfield documented i…
|
||||
- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [serialize](./src/public/serialize.md) — `serializeTpmtPublic` re-emits a parsed `TpmtPublic` value as the TCG-canonical byte string per Library Part 2 §12.2. I…
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [alg](./src/alg/alg.md) — <!-- begin:auto-docs --> _(no submodules)_- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [serialize](./src/attest/serialize.md) — `serializeTpmsAttest` re-emits a parsed `TpmsAttest` value as the TCG-canonical byte string per Library Part 2 §10.12.…
|
||||
- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [object-attributes](./src/public/object-attributes.md) — `decodeObjectAttributes` (and its inverse `encodeObjectAttributes`) walk the 32-bit `TPMA_OBJECT` bitfield documented i…
|
||||
- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [serialize](./src/public/serialize.md) — `serializeTpmtPublic` re-emits a parsed `TpmtPublic` value as the TCG-canonical byte string per Library Part 2 §12.2. I…
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [alg](./src/alg/alg.md) — <!-- begin:auto-docs --> _(no submodules)_- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmsAttest` re-emits a parsed…
|
||||
- [serialize](./src/attest/serialize.md) — `serializeTpmsAttest` re-emits a parsed `TpmsAttest` value as the TCG-canonical byte string per Library Part 2 §10.12.…
|
||||
- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [object-attributes](./src/public/object-attributes.md) — `decodeObjectAttributes` (and its inverse `encodeObjectAttributes`) walk the 32-bit `TPMA_OBJECT` bitfield documented i…
|
||||
- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_- serialize — `serializeTpmtPublic` re-emits a parsed…
|
||||
- [serialize](./src/public/serialize.md) — `serializeTpmtPublic` re-emits a parsed `TpmtPublic` value as the TCG-canonical byte string per Library Part 2 §12.2. I…
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [alg](./src/alg/alg.md) — <!-- begin:auto-docs --> _(no submodules)_- [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_ - [attest](./src/attest/attest.md) — <!-- begin:auto-docs --> _(no submodules)_ - [serialize](./src/attest/serialize.md) — `serializeTpmsAttest` re-emits a parsed `TpmsAttest` value as the TCG-canonical byte string per Library Part 2 §10.12.…
|
||||
- [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_ - [buffer](./src/buffer/buffer.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_ - [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_ - [error-codes](./src/errors/error-codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_ - [extra-data](./src/extra-data/extra-data.md) — <!-- begin:auto-docs --> _(no submodules)_- [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_ - [name](./src/name/name.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_ - [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_ - [object-attributes](./src/public/object-attributes.md) — `decodeObjectAttributes` (and its inverse `encodeObjectAttributes`) walk the 32-bit `TPMA_OBJECT` bitfield documented i…
|
||||
- [public](./src/public/public.md) — <!-- begin:auto-docs --> _(no submodules)_ - [serialize](./src/public/serialize.md) — `serializeTpmtPublic` re-emits a parsed `TpmtPublic` value as the TCG-canonical byte string per Library Part 2 §12.2. I…
|
||||
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ - [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/tpm-struct
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { createHash } from "node:crypto";
|
||||
import {
|
||||
parseTpmsAttest,
|
||||
parseTpmtPublic,
|
||||
computeTpmtPublicName,
|
||||
extraDataMatches,
|
||||
} from "@suaveplan/tpm-struct";
|
||||
|
||||
const att = parseTpmsAttest(attestationData); // TPMS_ATTEST
|
||||
const pub = parseTpmtPublic(pubArea); // TPMT_PUBLIC
|
||||
const name = computeTpmtPublicName(pub, { // 0x000b || sha256(...)
|
||||
digest: (b) => new Uint8Array(createHash("sha256").update(b).digest()),
|
||||
});
|
||||
|
||||
if (
|
||||
att.type === "TPM_ST_ATTEST_CERTIFY" &&
|
||||
extraDataMatches(att.attested.name, name, /* injected constantTimeEqual */ null!)
|
||||
) {
|
||||
// pubArea is the public area the TPM certified.
|
||||
}
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
| Module | Purpose |
|
||||
|---|---|
|
||||
| [`buffer`](./src/buffer/buffer.md) | `TpmBufferReader` / `TpmBufferWriter` over §10.1 octet streams. |
|
||||
| [`alg`](./src/alg/alg.md) | `TPM_ALG` / `TPM_ECC_CURVE` frozen registries + symbolic lookup. |
|
||||
| [`public/public`](./src/public/public.md) | `parseTpmtPublic` per §12.2. |
|
||||
| [`public/serialize`](./src/public/serialize.md) | `serializeTpmtPublic` canonical encoder. |
|
||||
| [`public/object-attributes`](./src/public/object-attributes.md) | `TPMA_OBJECT` bitfield decoder (§8.3). |
|
||||
| [`attest/attest`](./src/attest/attest.md) | `parseTpmsAttest` per §10.12. |
|
||||
| [`attest/serialize`](./src/attest/serialize.md) | `serializeTpmsAttest` canonical encoder. |
|
||||
| [`name/name`](./src/name/name.md) | `computeTpmtPublicName` per Part 1 §16. |
|
||||
| [`extra-data/extra-data`](./src/extra-data/extra-data.md) | WebAuthn step-8 `extraData` match. |
|
||||
| [`schemas/schemas`](./src/schemas/schemas.md) | Zod boundary schemas. |
|
||||
| [`errors/error-codes`](./src/errors/error-codes.md) | `TPM_STRUCT_CODES` + `TpmStructError`. |
|
||||
| [`observability/metrics`](./src/observability/metrics.md) | OTel histograms + counters. |
|
||||
| [`diagnostic/diagnostic`](./src/diagnostic/diagnostic.md) | Debug-only human-readable dumper. |
|
||||
|
||||
## Subpath exports
|
||||
|
||||
`.`, `./buffer`, `./alg`, `./public`, `./attest`, `./name`,
|
||||
`./extra-data`, `./schemas`, `./errors`, `./diagnostic`.
|
||||
|
||||
## Dependencies
|
||||
|
||||
`@suaveplan/error`, `@suaveplan/types`, `@opentelemetry/api`, `tslib`,
|
||||
`zod`. No `node:*` imports; no external TPM tooling.
|
||||
|
||||
## License
|
||||
|
||||
MIT.
|
||||
|
||||
Reference in New Issue
Block a user