[keymanager/wsd] Add /keys:decaps KOL API with DecapAndSeal + Open orchestration#650
[keymanager/wsd] Add /keys:decaps KOL API with DecapAndSeal + Open orchestration#650atulpatildbz wants to merge 10 commits intogoogle:mainfrom
Conversation
NilanjanDaw
left a comment
There was a problem hiding this comment.
Thanks for the PR. Over-all comment: I think we need to align the message formats for the APIs. Lets define them in a separate proto file, so that they can be easily reviewed.
| // Use a sentinel byte so the pointer is always valid. | ||
| var aadSentinel [1]byte | ||
| aadPtr := (*C.uint8_t)(unsafe.Pointer(&aadSentinel[0])) | ||
| aadLen := C.size_t(0) | ||
| if len(aad) > 0 { | ||
| aadPtr = (*C.uint8_t)(unsafe.Pointer(&aad[0])) | ||
| aadLen = C.size_t(len(aad)) | ||
| } |
There was a problem hiding this comment.
Should we add a AAD context for the HPKE seal/open operation?
There was a problem hiding this comment.
Good point. I added an explicit AAD context for the decaps flow and pass it through both KPS DecapAndSeal and WSD Open: "wsd:keys:decaps:v1::". Addressed in commit 02d8655.
| return | ||
| } | ||
|
|
||
| encapsulatedKey, err := base64.StdEncoding.DecodeString(req.EncapsulatedKey) |
There was a problem hiding this comment.
I think we need to align the message format and the params a bit. The encapsulatedKey is expected to be raw bytes and packed as below
message DecapsRequest {
KeyHandle key_handle = 1;
KemCiphertext ciphertext = 2;
}
// The results of an Encaps operation.
message KemCiphertext {
KemAlgorithm algorithm = 1;
bytes ciphertext = 2; // `Nenc` bytes long.
}
| resp := DecapsResponse{ | ||
| SharedSecret: base64.StdEncoding.EncodeToString(plaintext), | ||
| } |
There was a problem hiding this comment.
Response should be encoded as follows
// The results of a Decaps operation.
message KemSharedSecret {
KemAlgorithm algorithm = 1;
bytes secret = 2; // `Nsecret` bytes long.
}
There was a problem hiding this comment.
Updated response encoding to KemSharedSecret shape: sharedSecret{ algorithm, secret }. Implemented in commit 02d8655 (including test updates).
Thanks for the review. I aligned the API message formats and added a dedicated proto file: |
Introduces `key_manager_decap_and_seal`, a new FFI function in `key_custody_core` that enables decapsulating a shared secret and immediately resealing it with a binding public key. Key Changes: - New FFI: Added `key_manager_decap_and_seal` to handle the transition of a shared secret from a client-provided encapsulation to a sealed form bound to a specific receiver. - Security: Integrated `zeroize` to ensure the intermediate shared secret is wiped from memory after the resealing operation. - Error Handling: Implemented robust error reporting for invalid inputs, missing keys, and cryptographic failures. - Testing: Added a comprehensive unit test `test_decap_and_seal_success` that simulates a client-to-service flow and verifies the recovered secret.
BoringSSL does not currently expose a way to initialize a RecipientContext directly from a pre-calculated shared secret. This change adds a helper to km_common that manually implements the HPKE KeySchedule to derive the AEAD key and nonce. Changes: - Implement and HPKE KDF helpers in km_common. - Mark these helpers as available only for tests or via the new feature. - Enable in kps_key_custody_core dev-dependencies. - Update to verify decryption using the recovered secret.
This change adds the FFI function to the workload service's key custody core. This function allows the Workload Service to decrypt secrets using a previously generated binding key. Key features: - Look up the Binding Private Key from the registry (isolated in its own memfd_secret page via Vault). - Perform an HPKE open operation to decrypt the provided payload. - Aggressively sanitize sensitive material by zeroing out decrypted plaintext buffers after copying to the output. - Add comprehensive unit tests covering success, invalid UUID, and insufficient buffer size scenarios. - Fix unused import warnings in km_common related to test-only crypto helpers.
This change introduces automated C header generation using binding and fixes a critical ABI mismatch in the key custody FFI layer. Changes: 1. FFI Header Generation: - Added keymanager/generate_ffi_headers.sh script to generate C headers for all key custody components. - Added cbindgen.toml configurations for km_common, kps_key_custody_core, and ws_key_custody_core. - Exposed km_common::ffi with stable C-ABI structs and constants to ensure compatibility. 2. FFI ABI Safety Fix: - Problem: Previous FFI functions accepted HpkeAlgorithm (Protobuf-generated repr(Rust) struct) by value. This caused undefined behavior as C callers expected a C-compatible layout. - Fix: Updated key_manager_generate_kem_keypair and key_manager_generate_binding_keypair to accept KmHpkeAlgorithm, a dedicated repr(C) struct. - Mechanism: Implemented safe conversion (impl From<KmHpkeAlgorithm> for HpkeAlgorithm) to bridge the FFI boundary safely. - Verification: Added FFI-specific tests covering KmHpkeAlgorithm usage.
- Implement binding and KEM key generation endpoints in Workload Service.
- Add Key Protection Service client integration.
- Adapt Go CGO wrappers to match new Rust FFI signatures (KmHpkeAlgorithm, usize).
- Add component integration tests (Go Service -> Rust Core) to verify FFI flow.
Updates the EnumerateKEMKeys API to use snake_case JSON tags and string serialization for enums (KemAlgorithm, KeyProtectionMechanism) to align with the defined API contract.
- Update GenerateKemRequest and GenerateKemResponse JSON tags to use snake_case. - Update KemAlgorithm enum string representation to remove KEM_ALGORITHM_ prefix. - Update tests to reflect these changes.
bc9f760 to
acab338
Compare
This change implements the Decap and Seal flow in the Workload Service. It includes: - POST /v1/keys:decap endpoint - DecapAndSeal (KPS) and Open (WSD) orchestration - AAD binding for decapsulation - DecapsRequest and DecapsResponse proto definitions - FFI integration for Decap and Seal
acab338 to
4f935f5
Compare
Implements the Go orchestration layer (KOL) for
POST /v1/keys:decap. This key exchange endpoint allows workloads to recover a shared secret from a KEM encapsulation.Flow:
{key_handle, ciphertext: {algorithm, ciphertext}}to WSD/v1/keys:generate_kem)DecapAndSeal— decapsulates the shared secret using the KEM private key, reseals it with the binding public keyOpen— unseals the shared secret using the binding private keyChanges:
POST /v1/keys:decap(aligned with API contract)snake_casefor JSON fields inDecapsRequestandDecapsResponsekey_manager_decap_and_seal(KPS) andkey_manager_open(WSD) declarationsDecapAndSeal()andOpen()Go wrappers for the Rust FFI functionsServicewithDecapAndSealmethodDecapSealer/Openerinterfaces,handleDecapshandlerTestHandleDecapsSuccessin and Rust unit testsDependencies
This PR is built on top of:
PR #652 ends at commit
2030fa6.What to review
Please review commits from 4f935f5 onwards (after base commit 2030fa6).
The entire Decap implementation is squashed into this single commit:
All commits prior to
4f935f5are from PR #652 and PR #649 (already under separate review).