Documentation
¶
Overview ¶
Package securestore provides a platform-agnostic seam for holding the private key behind a TLS client certificate. The calling code (the cert-auth flow in internal/auth) never branches on platform: it asks Open for a backend, then Generate/Import/Load a crypto.Signer plus an opaque handle it can persist alongside the certificate.
Two backends ship today:
- "file" — a software key stored as a PKCS#8 PEM handle. Used for the plain "mtls" auth method and on any platform without hardware support. The key bytes live in the handle, so the caller writes them at 0600.
- "tpm" — (Linux/Windows only) the key is sealed under the TPM's Storage Root Key. The handle is the marshalled go-tpm-tools SealedBytes proto and carries no usable key material off the originating chip.
macOS Secure Enclave support is a future backend: Open("tpm") returns ErrUnsupported there until the binary is code-signed with the required entitlements. The interface is designed so that lands without changing any caller.
The whole package is CGO-free; the TPM backend talks to /dev/tpmrm0 (Linux) or TBS (Windows) through pure-Go go-tpm/go-tpm-tools.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrUnsupported = errors.New("securestore: backend not supported on this platform")
ErrUnsupported is returned by Open when the requested backend is not available on the current platform/build (e.g. "tpm" on unsigned macOS, or a host with no TPM device). Callers surface this as a clear error and must never silently fall back to a weaker backend.
Functions ¶
func HardwareAvailable ¶
func HardwareAvailable() error
HardwareAvailable reports whether the platform hardware backend can be opened on this host (nil) or why it cannot (ErrUnsupported, wrapped). It is a cheap preflight used to fail a "+tpm" auth method fast and clearly when no TPM is present, rather than authenticating and then silently failing to persist the sealed token.
func ModeForMethod ¶
ModeForMethod maps a dotvault auth method to a securestore backend mode. "mtls+tpm" wants hardware; everything else (including plain "mtls") uses the file backend.
func SealData ¶
SealData seals data under the platform hardware backend (TPM on Linux/Windows), opening and closing the device around the operation. It returns ErrUnsupported on a host with no hardware backend — callers MUST treat that as a hard error and never fall back to storing data in plaintext. The sealed blob is machine-bound: only UnsealData on the originating chip can recover it.
func UnsealData ¶
UnsealData reverses SealData, opening and closing the hardware backend around the operation. ErrUnsupported (no hardware) or an unseal error (wrong machine, cleared TPM) are both surfaced to the caller.
Types ¶
type Capabilities ¶
type Capabilities struct {
// Name is the backend identifier ("file", "tpm", "secure-enclave").
Name string
// HardwareBound is true when the private key is bound to hardware and
// cannot be loaded on another machine (TPM/Enclave), false when it is a
// portable software key (file).
HardwareBound bool
}
Capabilities describes a backend.
type DataSealer ¶
type DataSealer interface {
// SealData seals data and returns an opaque handle. The handle is
// machine-bound: it can only be unsealed by UnsealData on the originating
// chip.
SealData(data []byte) ([]byte, error)
// UnsealData reverses SealData.
UnsealData(handle []byte) ([]byte, error)
}
DataSealer is an optional capability for hardware backends that can seal an arbitrary small blob (e.g. a Vault token) under the same hardware root of trust that protects a key. The "file" backend deliberately does NOT implement it: sealing data under a software key kept on the same disk gives no at-rest protection, so data sealing is a hardware-only (TPM) feature.
type Storage ¶
type Storage interface {
// Capabilities reports backend identity and whether it hardware-binds.
Capabilities() Capabilities
// Generate creates a new private key of the given type and returns a
// crypto.Signer plus an opaque handle that Load can later use to
// reconstruct the signer. sealToPCRs binds the key to the current PCR
// (boot) state where the backend supports it; it is ignored by backends
// that do not.
Generate(kt KeyType, sealToPCRs bool) (crypto.Signer, []byte, error)
// Import takes an existing software private key (the BYO path) and
// returns a crypto.Signer plus a handle, sealing it into hardware where
// supported.
Import(key crypto.PrivateKey, sealToPCRs bool) (crypto.Signer, []byte, error)
// Load reconstructs a crypto.Signer from a handle previously returned by
// Generate or Import.
Load(handle []byte) (crypto.Signer, error)
// Close releases any resources (e.g. the TPM device handle).
Close() error
}
Storage holds the private key behind a client certificate. Implementations are not required to be safe for concurrent use; the cert-auth flow loads a signer once and assembles a tls.Certificate from it.