Documentation
¶
Overview ¶
Asset: keysource Purpose: Interface and wrapped-blob format for retrieving unseal key shares. Threats: Defines an AEAD envelope that binds every wrapped share to a specific configured node context and share index, preventing accidental relabeling and index substitution. The node label is not hardware identity. Does NOT protect a share once unwrapped in memory (see secure.Wipe) and does NOT prevent an attacker with live HSM access from unwrapping legitimately. Deps: none (stdlib only) Example: src, _ := keysource.OpenPKCS11(cfg); share, _ := src.Unwrap(ctx, blob, aad) Status: tested License: MIT Provenance: original
Asset: keysource-pkcs11 Purpose: HSM-backed key source — unwraps unseal shares with an AES-256-GCM key that never leaves the token. Threats: Ensures unseal key shares are unrecoverable from stolen disks, backups, or filesystem snapshots: the wrapped blobs are inert without the token, and the wrapping key is non-extractable. Binds each share to configured node context+index via GCM AAD, preventing accidental relabeling. Gives the HSM an audit point and a revocation lever (destroy the key). Does NOT defend against an attacker executing code on this host while the session is open — they can ask the HSM to unwrap exactly as the daemon does. Auto-unseal inherently trades some of Vault's sealed-at-rest guarantee for availability. Deps: github.com/miekg/pkcs11 Example: src, err := keysource.OpenPKCS11(keysource.PKCS11Options{...}); defer src.Close() Status: tested — PKCS#11 v2.40 AES-GCM interface, exercised against SoftHSM 2.6/2.7 by the integration test and scripts/e2e.sh; NOT yet exercised against production hardware, so run `autohsm selftest` on the real token before trusting a deployment. License: MIT Provenance: original
Asset: keysource-software Purpose: AES-256-GCM software key source — development and test only, never production. Threats: Exercises the exact envelope and AAD binding the HSM path uses, so the authentication properties can be tested without a token present. Provides NO hardware protection: the wrapping key lives in process memory and (typically) in an environment variable, so anyone who can read the host can unwrap every share. It is gated behind an explicit opt-in in config for exactly this reason. Deps: none (stdlib only) Example: src, _ := keysource.NewSoftware(key); share, _ := src.Unwrap(ctx, blob, aad) Status: tested License: MIT Provenance: original
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrHSMMisconfigured = errors.New("HSM configuration or key is unusable")
ErrHSMMisconfigured reports a failure that retrying cannot fix: the module cannot be loaded, the token lacks AES-GCM, the key is missing, ambiguous or unsafe, or the PIN source is unusable. It is terminal.
ErrHSMUnavailable reports that the token or its session is gone (removed, unreachable, session invalidated) and could not be re-established. It is transient: a later call retries the connection.
var ErrPINRejected = errors.New("HSM rejected the PIN")
ErrPINRejected reports that the token refused the PIN (incorrect, locked, expired, or invalid). It is terminal: the source never logs in again after seeing it, because repeated wrong-PIN attempts count down a hardware token's retry counter and can lock or zeroise it.
Functions ¶
func AAD ¶
AAD builds the additional authenticated data binding a share to one node and index. Changing node or index changes the AAD, so the AEAD tag check fails. NodeID is a configuration label, not proof that code runs on a physical host.
func MarshalEnvelope ¶
MarshalEnvelope renders an envelope to its on-disk text form.
func Wrap ¶
Wrap produces an envelope using the token's key. Exposed via the CLI so that provisioning never requires the wrapping key to leave the HSM.
func WrapSoftware ¶
WrapSoftware produces an envelope for provisioning in development. The nonce comes from crypto/rand: never a counter, never time-derived.
Types ¶
type Envelope ¶
Envelope is the on-disk representation of a wrapped share:
autohsm-v1.<base64(nonce)>.<base64(ciphertext||tag)>
It carries no secret material of its own; without the HSM key it is inert.
func ParseEnvelope ¶
ParseEnvelope parses the on-disk form, failing closed on anything malformed.
type HealthChecker ¶
HealthChecker is implemented by sources whose backing device can go away (an HSM). Health re-establishes a lost session when it can and reports whether the source is usable.
type PKCS11Options ¶
type PKCS11Options struct {
ModulePath string
TokenLabel string // optional; if empty, the first token with the key is used
KeyLabel string
// ReadPIN supplies the user PIN for every login: the initial one and each
// re-login after a lost session. The source wipes the returned slice
// immediately after C_Login, so the PIN is not held between logins.
ReadPIN func() ([]byte, error)
// only startup failure is ErrHSMUnavailable (token absent, module cannot
// initialise, session cannot open). The first Health/Unwrap call then
// reconnects, so a daemon can start before its HSM and use the same
// backoff-and-alarm path as a mid-run outage. PIN and configuration
// failures are still returned.
DeferUnavailable bool
}
PKCS11Options describes how to reach the token and which key to use.
type Source ¶
type Source interface {
// Unwrap decrypts blob, authenticating it against aad. It must return an
// error (never partial or unauthenticated plaintext) if authentication fails.
Unwrap(ctx context.Context, blob []byte, aad []byte) ([]byte, error)
// Close releases any HSM session.
Close() error
}
Source unwraps a stored share into plaintext key material.
Implementations must never log, cache, or copy the plaintext beyond what the caller receives. Callers must wipe the returned buffer.
func NewSoftware ¶
NewSoftware builds a development key source from a 32-byte key.
func OpenPKCS11 ¶
func OpenPKCS11(opts PKCS11Options) (Source, error)
OpenPKCS11 initialises the module, logs in, and locates the wrapping key. Every failure is classified as ErrPINRejected, ErrHSMMisconfigured (both terminal) or ErrHSMUnavailable (retryable). There is deliberately no fallback to software.