Skip to content

Quantum Observer

Researcher Recovers Most of a Reused ML-KEM Private Key Through Patched wolfSSL Flaws

wolfSSL's optimized ML-KEM code for two processor families compared only part of each incoming ciphertext. In tests on a reused key, Bhabani Sankar Das recovered 98.0% to 98.5% of its secret coefficients. Version 5.9.2 fixes both flaws.

Illustration: Repeated rubbings of one relief plate yield a yellow reconstruction with a narrow blank sliver.
Illustration: Quantum Observer (AI-generated)

Researcher Bhabani Sankar Das recovered most of an ML-KEM private key in tests on shipped wolfSSL binaries by exploiting two flaws in how the library checks incoming encrypted messages, or ciphertexts. Das described the attack in a preprint that the IACR Cryptology ePrint Archive posted on August 15, 2026.

wolfSSL had already fixed both flaws in version 5.9.2, dated June 23, 2026. According to Das, the attack needs a reused private key, so TLS 1.3 connections that create a fresh key for every handshake are not open to key recovery this way.

ML-KEM, formerly CRYSTALS-Kyber, is the post-quantum key-encapsulation mechanism, or KEM, that NIST standardized in FIPS 203 in August 2024. Two parties use a KEM to agree on a shared secret. After the sender uses the recipient’s public key to wrap a fresh secret in a ciphertext, the recipient recovers the secret with the private key in a step called decapsulation.

The flawed check

ML-KEM includes a step called the Fujisaki–Okamoto, or FO, transform to resist chosen-ciphertext attacks, in which an attacker submits crafted ciphertexts and studies the responses. Under the FO transform, the recipient decrypts a ciphertext, re-encrypts the recovered message, and confirms that the result matches the received ciphertext byte for byte. On any mismatch, the recipient returns a pseudorandom value instead of the real secret, a design known as implicit rejection.

Das wrote that ML-KEM “is IND-CCA2 secure only because of one check inside decapsulation.” IND-CCA2, short for indistinguishability under adaptive chosen-ciphertext attack, is the formal name for security against such attacks.

Das also wrote that wolfSSL implemented the check in hand-written assembly using SIMD instructions, which process many bytes in one step. The two flawed versions were written for x86-64 processors with AVX2 instructions and for 64-bit ARM processors with NEON instructions.

On the AVX2 path, wolfSSL’s code compared only 1,536 of the 1,568 bytes of an ML-KEM-1024 ciphertext and left the last 32 unchecked, wolfSSL wrote in its record for CVE-2026-10097. On the NEON path, the code compared roughly half of the ciphertext, Das wrote. In its record for CVE-2026-6330, wolfSSL wrote that the comparison “only compares half of the input.”

wolfSSL listed versions 5.7.0 through 5.9.1 as affected by the AVX2 flaw and versions 5.7.4 through 5.9.1 as affected by the NEON flaw. In CVE records published on June 25, the company rated the AVX2 flaw High, at 8.3 on the 10-point CVSS 4.0 severity scale, and the NEON flaw Medium, at 6.3. In its 5.9.2 release notes, wolfSSL listed both flaws as medium severity.

The company credited Nicholas Carlini of Anthropic with reporting the NEON flaw. In the preprint, Das thanked Carlini “for the independent discovery and report.” The company credited the AVX2 report to 007bsd, the handle that Das uses for the attack code and the preprint’s contact address.

Key recovery

In the preprint, Das wrote that both bugs “were documented as a weakening of IND-CCA2 security” and argued that an attacker can use them to recover the private key. In the AVX2 record, wolfSSL had already reported a proof of concept that recovered a full ML-KEM-1024 private key with approximately 98% success, using roughly 350 chosen ciphertexts.

ML-KEM keys and ciphertexts contain small random errors, called noise. Das wrote that the bytes the check skips “carry the tail of the decryption noise, and that noise is an exact linear function of the secret key.”

Against the shipped binaries, Das recovered 98.0% of the 2,048 secret coefficients of an ML-KEM-1024 key with 400 ciphertexts on the AVX2 path and 98.5% with 600 on the NEON path, according to the preprint. Das wrote that an attacker who used more ciphertexts would recover the full key. In a verified reference model, Das reported recovering all 2,048 coefficients with about 1,300 ciphertexts.

Das put the attack’s cost at 100,000 to 1 million decapsulation queries, against a few thousand for key-mismatch attacks, and described the preprint’s contribution as “reach rather than efficiency.” In the attack repository, Das wrote that the AVX2 tests ran natively on x86-64 hardware and the NEON tests in an emulator.

Exposure

In the repository, Das wrote that an attacker must be able to send crafted ciphertexts to a system that reuses its ML-KEM key and to see whether decapsulation returns the real secret or the rejection value. Das gave HPKE recipients, KEMTLS, and pinned or embedded keys as examples of reuse.

HPKE, or hybrid public key encryption, is a scheme for encrypting data to a recipient’s long-term public key. KEMTLS is a proposed TLS variant that authenticates servers with KEM keys instead of digital signatures. In the preprint, Das argued that the flaws could leak keys through such protocols but wrote, “we do not demonstrate it.”

Das tested the attacks with programs built around the shipped code, according to the repository. Each program used one reused key and exported it so the recovered values could be checked. Das wrote that a TLS 1.3 key share generated fresh for each handshake is not key-recoverable this way.

wolfSSL describes its library as targeted at standard, embedded, and real-time operating system environments and says its products secure more than 5 billion applications and devices.

The fix

wolfSSL fixed the NEON flaw in pull request 10192 and the AVX2 flaw in pull request 10430. Systems that run ML-KEM on the AVX2 path in wolfSSL 5.7.0 through 5.9.1, or on the NEON path in 5.7.4 through 5.9.1, keep the incomplete check until their operators upgrade to version 5.9.2 or later. Das concluded that “an incomplete FO comparison is a key-recovery vulnerability, and should be triaged as one.”

Update, November 12, 2026: On August 22, Das published test vectors, sample inputs that developers can use to check whether an ML-KEM implementation compares every byte of the ciphertext. A pull request from the 007bsd account adding similar vectors to Wycheproof, a public collection of cryptographic test vectors, was merged on September 2.