3.6 KiB
buffer — TPM 2.0 octet-stream reader and writer
(no submodules)
Purpose
The buffer module provides the lowest layer of @suaveplan/tpm-struct: a
strictly-bounded, big-endian byte reader (TpmBufferReader) and a matching
growing-array writer (TpmBufferWriter) shaped to the TCG TPM 2.0 Library
Part 2 §10.1 octet-stream conventions. Every higher-level parser in the
package (the TPMS_ATTEST decoder, the TPMT_PUBLIC decoder, the name
serialiser) builds on these primitives, which is why they receive their
own subpath export. Keeping bounds enforcement, big-endian semantics, and
the TPM2B_* size-prefix protocol in one place means the rest of the
package can be written as straight-line code without per-field bounds
checks or accidental little-endian reads.
Features
- Big-endian readers for UINT8/16/32/64 (the 64-bit form returns a
bigintso it never silently truncates). TPM2B_*size-prefix reader and writer (UINT16 length + payload).- Cursor-stable error path: out-of-bounds reads raise
TpmStructError(TPM_STRUCT.TRUNCATED)carryingcursorandrequestedon the cause chain so log adapters can format the failure. assertEnd()rejects trailing bytes — guards against silent length drift between the wire format and consumers.- Constant-time-safe
peek(n)(no advancing, never throws on clip). - Growing writer with geometric reallocation hint via
initialCapacity.
Usage: Basic Example
import { TpmBufferReader } from "@suaveplan/tpm-struct/buffer";
const reader = new TpmBufferReader(new Uint8Array([0x00, 0x04, 0xde, 0xad, 0xbe, 0xef]));
const payload = reader.readTpm2b(); // Uint8Array[0xde, 0xad, 0xbe, 0xef]
reader.assertEnd();
Usage: Advanced Example
import { TpmBufferReader, TpmBufferWriter } from "@suaveplan/tpm-struct/buffer";
// Encode then decode an arbitrary TPMS_CLOCK_INFO substructure.
const w = new TpmBufferWriter({ initialCapacity: 17 });
w.writeUint64Be(100n); // clock
w.writeUint32Be(5); // resetCount
w.writeUint32Be(3); // restartCount
w.writeUint8(1); // safe = true
const bytes = w.toUint8Array();
const r = new TpmBufferReader(bytes);
const clock = r.readUint64Be();
const reset = r.readUint32Be();
const restart = r.readUint32Be();
const safe = r.readUint8() !== 0;
r.assertEnd();
API Reference
new TpmBufferReader(bytes, { cursor? })— construct over aUint8Array. Out-of-rangecursorraisesTPM_STRUCT.TRUNCATED.readUint8 / readUint16Be / readUint32Be— returnnumber.readUint64Be()— returnsbigint.readBytes(n)— returns a freshUint8Arraycopy (never aliases).readTpm2b()/readTpm2bWithSize()— TCGTPM2B_*size-prefix.peek(n)/remaining()/cursor()/assertEnd()— read-only introspection.new TpmBufferWriter({ initialCapacity? })— growing writer.writeUint8 / 16Be / 32Be / 64Be / Bytes / Tpm2b— mirror writes.toUint8Array()— finalise into a freshUint8Array.
Implementation Notes
The reader holds a single DataView over the supplied Uint8Array's
backing buffer and advances a private cursor by the exact bytes consumed.
readTpm2b rewinds the cursor to the start of the size prefix on a
short-read failure so callers can produce diagnostic dumps from the
failing position. The writer grows its backing array by powers of two
starting at initialCapacity (default 256) and reuses the same buffer
across writes. Numeric range checks reject out-of-range writes at the
boundary — this is cheaper than letting DataView truncate silently.