CVE-2026-115408: ML-KEM key-pair lookup can bind an unrelated or attacker-planted public key, exposing encapsulated shared secrets
In github.com/eclipse-keypont/crypto11/v2 versions >= 2.0.0-rc3, <= 2.0.0-rc8, the ML-KEM key-pair lookup functions (FindMLKEMKeyPair, FindMLKEMKeyPairs, FindMLKEMKeyPairsWithAttributes) locate the public half of an ML-KEM key pair by CKAID/CKALABEL and never verify it against the private key. In addition, the "ID only" fallback search runs even when the private key has no CKAID, so the search template reduces to the public-key class and the ML-KEM key type and the first ML-KEM public key on the token is returned. Encapsulate() on the resulting key pair encrypts the fresh shared secret to that key, so its owner — not the holder of the private key the caller looked up — can recover the secret. An attacker who can open an unauthenticated session on the token and plant a public CKKMLKEM object carrying the victim's CKAID/CKALABEL receives the shared secrets for encapsulations performed through the substituted key pair, compromising the confidentiality of those secrets and of everything protected by keys derived from them. The v1 module paths have no ML-KEM support and are not affected.
Event History
Frequently Asked Questions
Which deployments are affected?
Only github.com/eclipse-keypont/crypto11/v2 versions from 2.0.0-rc3 through 2.0.0-rc8 are affected, and only where the ML-KEM key-pair lookup functions are used. The v1 module paths do not support ML-KEM and are not affected.
What access does an attacker need to exploit this?
An attacker needs to be able to open an unauthenticated session on the token and create a CKK_ML_KEM public-key object. They can assign it the victim private key's CKA_ID or CKA_LABEL, causing lookup to pair it with the victim private key.
Is an ML-KEM private key without a CKA_ID also at risk?
Yes. The ID-only fallback is performed even when the private key has no CKA_ID, reducing the public-key search to the ML-KEM object class and key type; the first ML-KEM public key on the token can then be selected.
What is exposed if lookup selects a substituted public key?
Encapsulate() encrypts the newly generated shared secret to the selected public key. Its owner can recover that secret, as well as data or keys protected using material derived from it.