Files
skills/docs/security-stack/security/tpm-struct/src/buffer/buffer.md
2026-05-29 08:20:56 +01:00

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 bigint so 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) carrying cursor and requested on 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 a Uint8Array. Out-of-range cursor raises TPM_STRUCT.TRUNCATED.
  • readUint8 / readUint16Be / readUint32Be — return number.
  • readUint64Be() — returns bigint.
  • readBytes(n) — returns a fresh Uint8Array copy (never aliases).
  • readTpm2b() / readTpm2bWithSize() — TCG TPM2B_* 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 fresh Uint8Array.

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.