Skip to content

hpke: set the scheme on hybrid KEM keys - #706

Open
stanleys12 wants to merge 1 commit into
cloudflare:mainfrom
stanleys12:osc/hpke-hybridkem-hybrid-kem-keys-never-set-cbae
Open

stanleys12 wants to merge 1 commit into
cloudflare:mainfrom
stanleys12:osc/hpke-hybridkem-hybrid-kem-keys-never-set-cbae

Conversation

@stanleys12

@stanleys12 stanleys12 commented Sep 27, 2026 •

Copy link
Copy Markdown

hybridKEMPrivKey and hybridKEMPubKey both declare a scheme kem.Scheme field that their Scheme() methods return, but none of the three places that build those structs ever assigned it: DeriveKeyPair, UnmarshalBinaryPrivateKey and UnmarshalBinaryPublicKey all used struct literals without a scheme: entry. The field was therefore always a nil interface, and (*hybridKEMPrivKey).Public() propagated the same nil value into the public key it returns.

The practical effect is that Scheme() returns nil for every key produced by KEM_X25519_KYBER768_DRAFT00, and calling any method on that result panics with a nil pointer dereference. Scheme() is part of the kem.PublicKey / kem.PrivateKey interface contract documented in kem/kem.go, so algorithm-agnostic code written against those interfaces hits this on ordinary use.

Changes

  • hpke/hybridkem.go: set scheme: h at the three construction sites, the same way xkem.go and shortkem.go populate the field on their key types. Public() needs no change since it already forwards k.scheme.
  • hpke/kem_test.go: add TestKemKeysScheme, which asserts Scheme().Name() matches the originating scheme for the private key, the public key, the key returned by Public(), and both keys after a MarshalBinary / Unmarshal round trip. The KEM id list is hoisted into a package-level kemIDs var so both tests share it, and the generate-key-pair setup is factored into genKeyPair.

The list stays the same six KEMs TestKemKeysExactLength already covered; KEM_XWING is left out because it was not in that list and its keys come from kem/xwing, which already sets the field.

Testing

TestKemKeysScheme panics on X25519_KYBER768 before the fix and passes after. go test ./... passes for the whole repository.

AI assistance (Claude) was used to draft this change; go test ./hpke/... was run locally with and without the fix.


Devin Review

DeriveKeyPair and the two unmarshalers left the scheme field of
hybridKEMPrivKey and hybridKEMPubKey nil, so Scheme() returned a nil
kem.Scheme and calling any method on it panicked.

Co-Authored-By: Claude Opus 5 <[email protected]>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

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.

1 participant