Skip to content

Comments

[keymanager/wsd] Add Go orchestration layer (KOL) for WSD key generation#652

Merged
atulpatildbz merged 14 commits intogoogle:mainfrom
atulpatildbz:wsd_generate_key_go
Feb 19, 2026
Merged

[keymanager/wsd] Add Go orchestration layer (KOL) for WSD key generation#652
atulpatildbz merged 14 commits intogoogle:mainfrom
atulpatildbz:wsd_generate_key_go

Conversation

@atulpatildbz
Copy link
Collaborator

@atulpatildbz atulpatildbz commented Feb 9, 2026

Summary

Implement the Go Key Orchestration Layer (KOL) for the Workload Service Daemon (WSD)
Expose POST /v1/keys:generate_kem endpoint that orchestrates the full key generation flow:

  • WSD KOL calls WSD KCC (Rust FFI) to generate a binding keypair
  • WSD KOL passes the binding public key to KPS KOL (direct Go method call)
  • KPS KOL calls KPS KCC (Rust FFI) to generate a KEM keypair
  • WSD KOL stores the KEM UUID → Binding UUID mapping
  • Returns the KEM UUID to the workload

Extend Go CGO wrappers to match updated Rust FFI signatures (KmHpkeAlgorithm, usize)
Align request/response format with API spec (JSON body with algorithm, key_protection_mechanism, lifespan)

Dependencies

This PR is created on top of #655

Commits to Review

a8545e1 onwards ("feat(keymanager): orchestrate Key Generation in Go"), which contains all orchestration logic and CGO adaptations.

Details

  • CGO bridges (wskcc, kpskcc): Go wrappers calling Rust FFI via CGO, returning (uuid.UUID, []byte, error)
  • KPS KOL (key_protection_service/service.go): KEMKeyGenerator interface wrapping KPS KCC FFI
  • WSD KOL (workload_service/server.go): HTTP server with /v1/keys:generate_kem, kemToBindingMap, dependency-injected interfaces
  • Request validation: algorithm (DHKEM_X25519 only), key_protection_mechanism (KEY_PROTECTION_VM only), lifespan > 0

Verification

Component Integration Tests:

go test -tags integration ./... passed.

Verifies full flow from Go Service layer -> CGO -> Rust Core FFI.
Covers:

  • Binding Key Gen (WSD)
  • KEM Key Gen (KPS)
  • End-to-End Orchestration (WSD -> KPS)

Manual Verification :

1647b5e : Created a manual test binary that initializes the WSD server with Rust FFI bindings and exposed the generate_kem endpoint for verification via curl.

> go run keymanager/cmd/wsd_manual_test/main.go

> curl --unix-socket /tmp/wsd.sock http://unix/v1/keys:generate_kem \
  -H "Content-Type: application/json" \
  -d '{"algorithm":"DHKEM_X25519_HKDF_SHA256", "key_protection_mechanism":"KEY_PROTECTION_VM", "lifespan":"3600s"}'

{"key_handle":{"handle":"4cbe1d70-d637-44f9-aa53-a08d5ba445e0"}}

Copy link
Collaborator

@NilanjanDaw NilanjanDaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Some initial comments.

atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 9, 2026
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 10, 2026
@atulpatildbz atulpatildbz force-pushed the wsd_generate_key_go branch 2 times, most recently from e333851 to 4d0831d Compare February 10, 2026 17:24
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 10, 2026
Generate FFI headers for km_common, workload_service key custody core, and key_protection_service key custody core using cbindgen.

Headers were generated from source with:

  CBINDGEN_BIN=cbindgen ./keymanager/generate_ffi_headers.sh

Generation output was then compared against the headers in PR google#652 for parity.
@atulpatildbz atulpatildbz marked this pull request as draft February 10, 2026 18:02
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 14, 2026
@atulpatildbz atulpatildbz force-pushed the wsd_generate_key_go branch 3 times, most recently from bba524b to 426856a Compare February 15, 2026 05:15
@atulpatildbz atulpatildbz marked this pull request as ready for review February 15, 2026 05:19
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 15, 2026
This change functions as the Go-side implementation for the Decap and Seal flow.
It is based on PR google#652 (Key Gen) and PR google#649 (FFI Decap).

Base Commit: 2030fa6 (Align Key Generation API with contract)

Squashed Commits:
- Fix compilation and tests for wsd_decaps_go (API alignment to /v1/keys:decap)
- keymanager/wsd: align decaps payloads with proto messages
- keymanager/wsd: define decaps API proto schema
- [keymanager/wsd] Add /keys:decaps endpoint with DecapAndSeal + Open orchestration

Key Features:
- endpoint: POST /v1/keys:decap
- Request: DecapsRequest (snake_case)
- Response: DecapsResponse (snake_case)
- Flows: DecapAndSeal (KPS) -> Open (WSD)
@atulpatildbz atulpatildbz force-pushed the wsd_generate_key_go branch 2 times, most recently from 696b9db to a8545e1 Compare February 15, 2026 11:25
}

let mut config = prost_build::Config::new();
config.type_attribute("HpkeAlgorithm", "#[repr(C)]");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you removed the type_attribute injection in build.rs. Is this because cbindgen couldn't pick up the generated struct from OUT_DIR?

extern "C" {
#endif // __cplusplus

int32_t key_manager_generate_kem_keypair(KmHpkeAlgorithm algo,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove the km prefixes from the algorithm definitions, seems a bit weird to have them

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm trying to remove KmHpkeAlgorithm altogether and reuse HpkeAlgorithm. as discussed here

Keeping this thread open until that is done

Comment on lines 133 to 136
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Golang support function decorators? I am wondering if there is a way to handle the list of supported HTTP methods in a cleaner way.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

@atulpatildbz atulpatildbz Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't actually see a problem with this. i had referred to the teeserver implementation https://github.com/google/go-tpm-tools/blob/main/launcher/teeserver/tee_server.go#L142

But makes sense to follow Go 1.22's routing. handled here


// Validate algorithm: only DHKEM_X25519_HKDF_SHA256 supported.
if req.Algorithm != KemAlgorithmDHKEMX25519HKDFSHA256 {
http.Error(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Should we declare a global error handler? Probably would make it easier to handle and return standard HTTP error codes.

Copy link
Collaborator Author

@atulpatildbz atulpatildbz Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handled it using a helper function. here

w,
fmt.Sprintf(
"unsupported algorithm: only DHKEM_X25519_HKDF_SHA256 (%d) is supported",
KemAlgorithmDHKEMX25519HKDFSHA256,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a list of supported algorithms coming from algorithms.proto

Copy link
Collaborator Author

@atulpatildbz atulpatildbz Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense. handled here

}

// Validate keyProtectionMechanism: only KEY_PROTECTION_VM supported.
if req.KeyProtectionMechanism != KeyProtectionMechanismVM {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if there is a better way to sanitize the request params. Can something like https://github.com/bufbuild/protovalidate-go for this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since GenerateKemRequest is a manually defined Go struct (not a generated Protobuf message), protovalidate-go cannot be used directly on it as it requires proto.Message instances

atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 17, 2026
Update the /v1/keys:generate_kem API to accept strictly numeric values
(seconds) for the 'lifespan' field.
Previously it accepted string values like '300s', which is now removed
to simplify the API contract.

as per comment:
google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 17, 2026
Evaluate support for KEM algorithms and Key Protection Mechanisms using
IsSupported() methods on the enums instead of hardcoded checks. This
simplifies adding new supported algorithms in the future.

comment:
google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 17, 2026
This change introduces a helper function 'writeError' in server.go to ensure all error responses are returned as JSON, consistent with the API's Content-Type. This addresses the review comment: google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 18, 2026
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 18, 2026
This change introduces a helper function 'writeError' in server.go to ensure all error responses are returned as JSON, consistent with the API's Content-Type. This addresses the review comment: google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 18, 2026
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 18, 2026
…afety

- keymanager/go.mod: Removed explicit toolchain pin and aligned module to go 1.22.
- keymanager/ws/include/ws_key_custody_core.h: Updated WSD header to include shared generated km_algorithms.h.
- keymanager/ws/server.go: Replaced hardcoded algorithm checks with typed proto_enums validation.
- keymanager/ws/server.go: Refactored request fields to use explicitly typed enum definitions.
- keymanager/ws/server.go: Implemented parsing of duration strings in JSON requests.
- keymanager/ws/server.go: Updated routing to follow Go 1.22 patterns.
- keymanager/ws/ws_key_custody_core_cgo.go: Parameterized algorithm selection to use request values instead of hardcoding.
- keymanager/kps/kps_key_custody_core_cgo.go: Updated CGO to use shared generated FFI constants from km_common.
- keymanager/kps/kps_key_custody_core_cgo.go: Updated CGO LDFLAGS to link against both debug and release Rust targets.
- keymanager/go.sum: Checked in go.sum for reproducible builds.
- keymanager/km_common/build.rs: Verified type_attribute injection for HpkeAlgorithm.
- keymanager/ws/lib.rs: Updated Rust FFI to accept serialized HpkeAlgorithm bytes explicitly.
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 19, 2026
Update the /v1/keys:generate_kem API to accept strictly numeric values
(seconds) for the 'lifespan' field.
Previously it accepted string values like '300s', which is now removed
to simplify the API contract.

as per comment:
google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 19, 2026
Evaluate support for KEM algorithms and Key Protection Mechanisms using
IsSupported() methods on the enums instead of hardcoded checks. This
simplifies adding new supported algorithms in the future.

comment:
google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 19, 2026
This change introduces a helper function 'writeError' in server.go to ensure all error responses are returned as JSON, consistent with the API's Content-Type. This addresses the review comment: google#652 (comment)
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 19, 2026
atulpatildbz added a commit to atulpatildbz/go-tpm-tools that referenced this pull request Feb 19, 2026
…afety

- keymanager/go.mod: Removed explicit toolchain pin and aligned module to go 1.22.
- keymanager/ws/include/ws_key_custody_core.h: Updated WSD header to include shared generated km_algorithms.h.
- keymanager/ws/server.go: Replaced hardcoded algorithm checks with typed proto_enums validation.
- keymanager/ws/server.go: Refactored request fields to use explicitly typed enum definitions.
- keymanager/ws/server.go: Implemented parsing of duration strings in JSON requests.
- keymanager/ws/server.go: Updated routing to follow Go 1.22 patterns.
- keymanager/ws/ws_key_custody_core_cgo.go: Parameterized algorithm selection to use request values instead of hardcoding.
- keymanager/kps/kps_key_custody_core_cgo.go: Updated CGO to use shared generated FFI constants from km_common.
- keymanager/kps/kps_key_custody_core_cgo.go: Updated CGO LDFLAGS to link against both debug and release Rust targets.
- keymanager/go.sum: Checked in go.sum for reproducible builds.
- keymanager/km_common/build.rs: Verified type_attribute injection for HpkeAlgorithm.
- keymanager/ws/lib.rs: Updated Rust FFI to accept serialized HpkeAlgorithm bytes explicitly.
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.
This commit implements the Go orchestration layer changes for key generation.
It aligns the Key Generation API with the contract.
Update the /v1/keys:generate_kem API to accept strictly numeric values
(seconds) for the 'lifespan' field.
Previously it accepted string values like '300s', which is now removed
to simplify the API contract.

as per comment:
google#652 (comment)
Use http.ServeMux features to strictly enforce POST method for /v1/keys:generate_kem, removing manual checks in the handler.
Evaluate support for KEM algorithms and Key Protection Mechanisms using
IsSupported() methods on the enums instead of hardcoded checks. This
simplifies adding new supported algorithms in the future.

comment:
google#652 (comment)
This change introduces a helper function 'writeError' in server.go to ensure all error responses are returned as JSON, consistent with the API's Content-Type. This addresses the review comment: google#652 (comment)
- Replaced KmHpkeAlgorithm struct with serialized HpkeAlgorithm protobuf bytes in FFI.
- Added prost dependency to kps and ws crates for decoding.
- Removed keymanager/km_common/src/ffi.rs and include/km_algorithms.h to avoid duplication.
- Regenerated C headers for kps and ws components.
- Verified with cargo test.
This change updates the Go FFI bindings to match the recent Rust changes
where KmHpkeAlgorithm C-struct was replaced with a serialized HpkeAlgorithm
proto.
…afety

- keymanager/go.mod: Removed explicit toolchain pin and aligned module to go 1.22.
- keymanager/ws/include/ws_key_custody_core.h: Updated WSD header to include shared generated km_algorithms.h.
- keymanager/ws/server.go: Replaced hardcoded algorithm checks with typed proto_enums validation.
- keymanager/ws/server.go: Refactored request fields to use explicitly typed enum definitions.
- keymanager/ws/server.go: Implemented parsing of duration strings in JSON requests.
- keymanager/ws/server.go: Updated routing to follow Go 1.22 patterns.
- keymanager/ws/ws_key_custody_core_cgo.go: Parameterized algorithm selection to use request values instead of hardcoding.
- keymanager/kps/kps_key_custody_core_cgo.go: Updated CGO to use shared generated FFI constants from km_common.
- keymanager/kps/kps_key_custody_core_cgo.go: Updated CGO LDFLAGS to link against both debug and release Rust targets.
- keymanager/go.sum: Checked in go.sum for reproducible builds.
- keymanager/km_common/build.rs: Verified type_attribute injection for HpkeAlgorithm.
- keymanager/ws/lib.rs: Updated Rust FFI to accept serialized HpkeAlgorithm bytes explicitly.
Centralizes the algorithm mapping logic by moving it from a private helper in server.go to a public method ToHpkeAlgorithm on the KemAlgorithm type in proto_enums.go.

This change simplifies future introspection APIs (e.g., getCapabilities) by providing a single source of truth for algorithm configuration without needing to instantiate backend services or duplicate logic. It ensures that the API layer can validate and describe supported algorithms consistently.
@atulpatildbz
Copy link
Collaborator Author

/gcbrun

@atulpatildbz atulpatildbz merged commit 8c93731 into google:main Feb 19, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants