Repository navigation
docs: key vendor backend capability matrix, and refuse an unsafe rewrap (CIP-5313) - #1541
Conversation
🦋 Changeset detectedLatest commit: 24478d2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 19 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true |
62cbabe to
bae2dfb
Compare
7ebb0fd to
5a73cdc
Compare
bae2dfb to
81f6647
Compare
d20b25a to
8367103
Compare
81f6647 to
12675c7
Compare
8367103 to
0605831
Compare
12675c7 to
cfa8f0d
Compare
0605831 to
0c85849
Compare
Add ADR-0009 (two key modes), ADR-0010 (v2 leaf with backend and mode) and ADR-0011 (hand-written vendor clients, signed in the guest). Widen the Keyset term and add the key backend terms to CONTEXT.md.
Add the seams a key vendor backend needs:
- KeyLifetime and LoadedIndexKey, returned by the new provided method
IndexKeySource::load_index_key_with_lifetime. The default is
UntilEvicted, the ZeroKMS behaviour.
- Error::Backend { vendor, kind, source } with BackendErrorKind, and
Error::ZeroKmsOnly { vendor, feature }.
- ZeroKmsFeature, ZeroKmsExtensions and refuse_zerokms_extensions, so a
key vendor backend refuses a context, a decryption policy or an
unverified context and never ignores it.
- IndexKey::from_key_bytes, a public constructor from raw key material.
The Go guest maps the two new error variants to statuses.
BREAKING CHANGE: stack_kms::Error has two new variants. An exhaustive
match on it must handle them.
…304) The cipher loads index keys with load_index_key_with_lifetime. A key for one settle only is never cached, a key with a TTL is evicted when the TTL ends, and a ZeroKMS key stays until evicted. init refuses a default keyset whose key the cipher may not keep (Error::DefaultKeysetLifetime). A key vendor backend's NotFound now counts as keyset not found, and Descriptor::MAX_LEN no longer reads a ZeroKMS constant.
…(CIP-5305) Add KeyBackend (ZeroKMS or a key vendor backend), KeyVendor and KeyMode. KeyVendor and KeyMode have stable bytes for the v2 sealed leaf; 0 is invalid for both. DataKeySource::key_backend says which backend a source is, and defaults to ZeroKMS.
…backend (CIP-5305) A v2 leaf is 0x02 ‖ backend ‖ mode ‖ keyset_id ‖ iv ‖ tag_len ‖ tag ‖ ct. The leaf AAD binds the three header bytes. A v1 leaf, its AAD and its serde form do not change, and ZeroKMS still writes v1. A cipher refuses a leaf that names another key backend than its own with Error::ForeignBackend, before any key call. A key vendor backend cannot seal yet (Error::SealUnsupported); CIP-5306 wires that path. Add a v1 known-answer test, v2 layout pins, header-byte tamper tests, v2 fuzz seeds, an eql-bindings pass-through test, and the Go guest status for ForeignBackend.
The backend supports Azure Key Vault and Managed HSM. It binds the associated data, versions the wrapped keys and supports Entra ID credentials.
Add hand-written Key Vault fixtures, a test-only RSA key and a live test. Run the contract suite over a Key Vault emulator for RSA and oct-HSM keys.
Check the WASI build. Stage the crate for crates.io.
…CIP-5311) The feature is on by default. A build without it has no RSA code.
The guest routes keysets between ZeroKMS and at most one key vendor backend (KeyRouter over GuestVendor: AWS KMS, Google Cloud KMS, Azure Key Vault, Vault Transit or a static key). The vendor clients sign in the guest. Their HTTP requests, the short-lived credentials they sign with and their retry backoff all go to the host through the step loop: a step request is now an HTTP request, a credential request (vendor and scope) or a wait. The guest blocks on none of them and imports nothing new; token_get stays its one import. The Go host adds WithKeyVendor and WithKeysetRecords, a credential source for each vendor kind with no vendor SDK dependency, and the capability matrix in the package docs. It answers a credential request from the source outside the client's lock, once per operation, vendor and scope, and attaches the source's error to the call's. It sits out a wait under the caller's context, cut to 30 seconds. The key vendor backend keys join the guest's config frame, and the deterministic test build reads them beside its seed.
Add WithDefaultKeyset, WithRootKeyTTL and ErrNoZeroKMS. With WithKeyVendor and no WithCredentials, NewClient resolves no ZeroKMS credentials. The guest routes the default keyset to the vendor (KeyRouter::with_vendor_default) and refuses every ZeroKMS request with the new STATUS_NO_ZEROKMS. # Conflicts: # languages/golang/encrypt/client.go # languages/golang/encrypt/guest/src/abi.rs # languages/golang/encrypt/guest/src/config.rs # languages/golang/encrypt/transport.go # languages/golang/internal/guest/errors.go # languages/golang/internal/guest/status.go # packages/stack-guest-abi/src/status.rs
StaticKey had no String, GoString or LogValue, so a %+v or a slog of the value printed the root key. Add the three methods, as AWSCredentials and AccessToken have, and a test for each output.
…et records (CIP-5312)
Link it from stack-kms and from each vendor crate.
Point to the full matrix in stack-kms-vendor.
Tell what stash keyset rewrap does to wrapped-mode values.
Also list the vendor crates that the auth binding compiles in.
…y (CIP-5313) A rewrap to another vendor key made the stored values unreadable.
0c85849 to
24478d2
Compare
18293ff to
c7346e2
Compare
|
Closed by the scope reduction. The capability matrix is now in the The plan is |
Top layer of the CIP-5203 stack. Implements CIP-5313.
stack-kms-vendorcrate docs, linked fromstack-kmsand every vendor crate. The Go matrix is corrected to match.skills/stash-zerokmssection, thestash-clirewrap text, the CLI READMEstash keysetsection, AGENTS.md and SECURITY.md.RewrapToAnotherKey, CLI coderewrap_refused). A new version of the same key, and any rewrap in derived mode, are still allowed.KeyVendorBackend::same_keydecides "same key" for each vendor.Read first: "## Summary for review" at the end of
docs/plans/2026-11-05-key-vendor-backends-decisions.md.