Repository navigation
Let a warden sign a new policy for an enclave-sealed key - #1125
Conversation
A sealed enclave policy could not change without sealing the key again from its plaintext outside the enclave. A key can now be sealed with a warden: encrypt_for_enclave_with_warden puts the warden's BIP340 public key and an epoch, starting at 0, in the sealed body and in the hash the blob is bound to, under a new domain so a blob with a warden and one without can never pass for each other. Blobs sealed without a warden open as before and keep their policy. UpdateSealedPolicy carries a blob, a new policy and the warden's signature over the whole blob and the new policy's hash at the next epoch. The enclave checks both, seals the key again inside the enclave under the blob's own data key, with a nonce derived from that key and the new body so the same move always gives the same blob, and returns it as SealedKey. The running enclave keeps its policy, since blobs sealed alike share a hash whatever key they hold; the new policy applies after a restart imports the new blob. This is not rollback protection: the old blob still opens to its old policy, so the loosest policy a warden ever signed bounds the key. docs/ENCLAVE.md says so. Both crates pin the new wire digest and a known answer for the warden hashes.
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Warden-bound blob format keep-enclave/host/src/kms.rs, keep-enclave/enclave/src/kms.rs |
Host and enclave KMS code add warden keys and epochs to sealed blobs, bind policy hashes to that metadata, and parse both warden-bound and existing policy-only blobs. Tests add hash vectors and cover sealing and opening. |
Enclave policy update flow keep-enclave/enclave/src/kms.rs, keep-enclave/enclave/src/vsock_server.rs, keep-enclave/host/src/protocol.rs |
The protocol adds update request and sealed-key response variants. The enclave checks the policy, warden signature, and epoch before resealing the wallet. Tests cover successful updates and rejected inputs; wire-format samples and digests are updated. |
Host API and usage documentation keep-enclave/host/src/client.rs, keep-enclave/host/src/mock.rs, keep-enclave/host/src/lib.rs, docs/ENCLAVE.md |
The host client sends update requests and returns resealed blobs. The mock returns an internal error for updates. Public exports and documentation include the warden helpers and update procedure. |
Priority:
Estimated code review effort: 4 (Complex) | ~45 minutes
Change: Feature
Sequence Diagram(s)
sequenceDiagram
participant EnclaveClient
participant EnclaveRequest
participant vsock_server
participant EnclaveKms
EnclaveClient->>EnclaveRequest: Send UpdateSealedPolicy with blob, policy, and signature
EnclaveRequest->>vsock_server: Dispatch update request
vsock_server->>EnclaveKms: Verify signature and reseal wallet
EnclaveKms-->>vsock_server: Return updated encrypted wallet
vsock_server-->>EnclaveClient: Return SealedKey
Possibly related PRs
- privkeyio/keep#1110: Introduced policy-bound
EncryptedWalletblobs and a policy-returning decrypt API, which this change extends with warden and epoch metadata. - privkeyio/keep#1123: Uses the same
EncryptedWalletpolicy-opening path that this change extends with optional warden metadata.
Suggested reviewers: wksantiago
Merge Risk: 
Minimal · up to d7d51
-
No actionable issue remains from this review; the policy-update change is mergeable after normal checks.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 22 functions across 7 files. (1 skipped: 1 unsupported.)
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
I’m a rabbit with a policy to renew,
I hop with a signed blob, epoch two.
The enclave checks the seal,
Then sends the key anew.
I nibble clover, pleased and true.
Comment @coderabbitai help to get the list of available commands.
Summary
Lets a warden sign a new policy for an enclave-sealed key, without the key leaving the enclave.
EnvelopeEncryption::encrypt_for_enclave_with_wardenseals a key with a warden's BIP340 public key and epoch 0, both bound into the blob's policy hash under a new domain (keep-enclave-policy-v2). Blobs sealed without a warden open as before and keep their policy.UpdateSealedPolicyrequest andSealedKeyresponse, both appended last. The enclave checks the warden's signature over the whole old blob and the new policy's hash at the next epoch, then seals the key again under the blob's own data key, with a nonce derived from that key and the new body.Warden,sealed_policy_hash,policy_update_message,EnclaveClient::update_sealed_policy. The mock refuses the request.docs/ENCLAVE.mdexplains the flow and that this is not rollback protection: the old blob still opens to its old policy.Testing
keep-enclave-hosttestsSummary by CodeRabbit