Files
Kyle Isom 115f23a3ea Add Nix flake for mciasctl and mciasgrpcctl
Vendor dependencies and expose control program binaries via
nix build. Uses nixpkgs-unstable for Go 1.26 support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 21:01:21 -07:00

84 lines
2.0 KiB
Go

package tpm2
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
// TPM2B is a helper type for all sized TPM structures. It can be instantiated with either a raw byte buffer or the actual struct.
type TPM2B[T Marshallable, P interface {
*T
Unmarshallable
}] struct {
contents *T
buffer []byte
}
// New2B creates a new TPM2B containing the given contents.
func New2B[T Marshallable, P interface {
*T
Unmarshallable
}](t T) TPM2B[T, P] {
return TPM2B[T, P]{contents: &t}
}
// BytesAs2B creates a new TPM2B containing the given byte array.
func BytesAs2B[T Marshallable, P interface {
*T
Unmarshallable
}](b []byte) TPM2B[T, P] {
return TPM2B[T, P]{buffer: b}
}
// Contents returns the structured contents of the TPM2B.
// It can fail if the TPM2B was instantiated with an invalid byte buffer.
func (value *TPM2B[T, P]) Contents() (*T, error) {
if value.contents != nil {
return value.contents, nil
}
if value.buffer == nil {
return nil, fmt.Errorf("TPMB had no contents or buffer")
}
contents, err := Unmarshal[T, P](value.buffer)
if err != nil {
return nil, err
}
// Cache the result
value.contents = (*T)(contents)
return value.contents, nil
}
// Bytes returns the inner contents of the TPM2B as a byte array, not including the length field.
func (value *TPM2B[T, P]) Bytes() []byte {
if value.buffer != nil {
return value.buffer
}
if value.contents == nil {
return []byte{}
}
// Cache the result
value.buffer = Marshal(*value.contents)
return value.buffer
}
// marshal implements the tpm2.Marshallable interface.
func (value TPM2B[T, P]) marshal(buf *bytes.Buffer) {
b := value.Bytes()
binary.Write(buf, binary.BigEndian, uint16(len(b)))
buf.Write(b)
}
// unmarshal implements the tpm2.Unmarshallable interface.
// Note: the structure contents are not validated during unmarshalling.
func (value *TPM2B[T, P]) unmarshal(buf *bytes.Buffer) error {
var size uint16
binary.Read(buf, binary.BigEndian, &size)
value.contents = nil
value.buffer = make([]byte, size)
_, err := io.ReadAtLeast(buf, value.buffer, int(size))
return err
}