]> git.ipfire.org Git - thirdparty/openssl.git/commit
ml_kem: return an error on catastrophic failure in decap
authorJakub Zelenka <jakub.zelenka@openssl.foundation>
Tue, 9 Jun 2026 19:07:39 +0000 (21:07 +0200)
committerTomas Mraz <tomas@openssl.foundation>
Mon, 15 Jun 2026 13:58:27 +0000 (15:58 +0200)
commite2bd9f8c28c0405caf9b85b61a1807f9db2a1026
tree51aff1962dc540a91994b08a7748ff88d2fc3804
parentc9808c5c4c548ca9ed30d53d1bafe4ae6113e852
ml_kem: return an error on catastrophic failure in decap

ML-KEM decapsulation applies implicit rejection by copying the failure
key into the shared secret when the FO re-encryption check fails. This
is correct for a syntactically valid but incorrect ciphertext, and must
stay constant-time and ciphertext-dependent.

However, the same path was also taken when hash_kr() or encrypt_cpa()
failed outright, for example on a memory allocation failure inside
EVP_DigestInit_ex(). In that case decap() copied the failure key and
still returned success, so the caller derived a wrong shared secret with
no error reported. For QUIC this produces a handshake that cannot
converge: the derived keys diverge from the peer, packets fail to
decrypt, and the connection stalls until it times out, with no
diagnostic pointing at the real cause.

These primitive failures are not dependent on the ciphertext, so
reporting them as a hard error does not create a chosen-ciphertext
oracle and does not weaken the constant-time implicit rejection that
happens later via CRYPTO_memcmp() and constant_time_select_8(). Treat
them the same way the existing kdf() failure is already treated, by
raising an error and returning 0.

Also fix the comment, which referred to hash_g() where the code actually
calls hash_kr().

Reviewed-by: Bob Beck <beck@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
MergeDate: Mon Jun 15 13:58:32 2026
(Merged from https://github.com/openssl/openssl/pull/31432)
crypto/ml_kem/ml_kem.c
pkcs11-provider
test/ml_kem_internal_test.c