CVE-2026-6330(NEON)および CVE-2026-10097(AVX2)。wolfSSL 5.9.2 で修正済み。
完全な技術解説は
Cryptology ePrint Archive, Paper 2026/1682
として公開されています(ローカルコピーは paper/ にあります)。下記の引用を参照してください。
ML-KEM(Kyber、FIPS 203)が 選択暗号文攻撃 に耐性を持つのは、カプセル化解除の内部にある1つのチェックのおかげです。受信者は、たった今復号したメッセージを再暗号化し、その結果が入力暗号文と完全に一致する場合にのみ、本物の共有秘密を返します。不一致が生じれば暗黙的な拒否が発動し、代わりに擬似乱数値が返されます。このチェックは Fujisaki-Okamoto 変換であり、 IND-CCA2 スキームを、その下にある可鍛性のある IND-CPA スキームから切り離す唯一の関門です。
wolfSSL はこの比較を手書きの SIMD アセンブリで実装していましたが、2つのバックエンドにおいて暗号文の一部のみを比較していました。ARM64 NEON では約半分を比較しており、これを Nicholas Carlini (Wikipedia)が発見し報告しました (CVE-2026-6330)。x86-64 AVX2 では、ML-KEM-1024 の 1568 バイトのうち 1536 バイトを比較していました (CVE-2026-10097)。
どちらのバックエンドでも、改ざんされた暗号文が本物として受理され、これは IND-CCA2 セキュリティの弱体化として報告されました。本解説では、この欠陥が両バックエンドにおいてさらに深刻であることを示します。チェックがスキップするバイトはカプセル化解除の復号ノイズを漏洩し、そのノイズは秘密鍵の線形関数であるため、鍵は
最小二乗回帰によって復元できます。これは格子問題ではなく、古典的な鍵不一致攻撃でもありません。AVX2 バックエンドでは、この欠陥が u のすべてを検証するため、それらの攻撃に必要な選択 u 暗号文は拒否されます。代わりに、復号ノイズの回帰によって、チェックされていない v 係数から鍵を復元します。ML-KEM-1024 の完全な秘密鍵が、AVX2 および NEON の両バックエンドにおいて、稼働中の脆弱なバイナリに対してエンドツーエンドで復元されます。
この攻撃には再利用された ML-KEM 鍵が必要です。HPKE の受信者、KEMTLS、あるいはピン留めや埋め込みされた鍵などです。エフェメラルなハイブリッド TLS 1.3 の鍵共有はハンドシェイクごとに新しい鍵を使用するため、この方法では鍵を復元できません。そこでは欠陥は識別攻撃による破綻にとどまります。両方の欠陥は修正済みかつ公開されており、これは開示後の解説記事です。
| NEON(CVE-2026-6330) | AVX2(CVE-2026-10097) | |
|---|---|---|
| バックエンド | ARM64 NEON | x86-64 AVX2 |
| 欠陥 | 暗号文の約半分を比較 | 1568 バイトのうち 1536 バイトを比較 |
| バグ報告者 | Nicholas Carlini(Anthropic) | 007bsd |
| CVE 深刻度 | 中(CVSS 4.0 6.3、CWE-327) | 高(CVSS 4.0 8.3、CWE-697) |
| 鍵復元、モデル | 完全(約500 ct) | 完全(約1300 ct) |
| 鍵復元、稼働バイナリ | 98.5% @ 600 ct(QEMU エミュレート) | 98.1% @ 350 ct(ネイティブ) |
| 修正 | PR #10192 | PR #10430 |
"live" は実際のバイナリ上で実証された結果です。NEON はより多くの暗号文を必要とします(600 対 350)。これは係数ごとの測定ノイズがはるかに大きい(約 4 倍)ためです。"model" は回帰が完全な鍵(全 2048 係数、100%)を復元することを確認するノイズフリーのチェックです。その暗号文数はノイズではなく各暗号文が生成する方程式の数によって決まるため、live の数値とは比較できず、攻撃の難易度を反映するものでもありません。
両方の欠陥は同じ wolfSSL リリース期間内に独立して発見され、5.9.2 でまとめて修正されました(両方の CVE エントリについては wolfSSL のセキュリティ脆弱性ページを参照)。Carlini の NEON バグは IND-CCA2 の弱体化として文書化され、AVX2 のバグは鍵復元として CVE が割り当てられています。このリポジトリの復号ノイズ回帰攻撃は両方で鍵を復元します。バックエンド固有の詳細は neon-cve-2026-6330/ と avx2-cve-2026-10097/ にあります。
wolfSSL の ML-KEM 暗黙的拒否チェックにおける不完全な比較で、2 つの SIMD アセンブリバックエンドに存在します。暗号文の全バイトではなく一部のみを比較していたため、正しい実装では拒否される暗号文をカプセル化解除が受け入れてしまいます。チェックされないバイトにより、カプセル化解除が復号ノイズのオラクルとなり、鍵が再利用される場合に秘密鍵を復元するのに十分となります。
脆弱な SIMD アセンブリを含むビルドで wolfSSL と ML-KEM を使用した場合に影響を受けます:5.7.0-5.9.1 の AVX2(x86-64)、または 5.7.4-5.9.1 の ARM64 NEON です。鍵復元攻撃にはさらに、HPKE の受信者、KEMTLS、あるいは固定または埋め込み鍵のように、ML-KEM 秘密鍵がカプセル化解除をまたいで再利用される必要があります。エフェメラルなハイブリッド TLS 1.3 鍵共有はハンドシェイクごとに新しい鍵を使用するため鍵復元はできません。そこではこの欠陥は識別攻撃による破断にとどまります。修正は wolfSSL 5.9.2 にあります。
細工したカプセル化解除クエリを送信し、それぞれに対して本物の秘密値が返るか拒否値が返るかを観測することで、どちらのバックエンドでも ML-KEM-1024 の秘密鍵全体を復元できます。実際のバイナリに対しては、約 10^5 から 10^6 回のカプセル化解除クエリで鍵を復元しました。
チェックされない領域の暗号文係数を 1 つ取ります。その平文ビットは丸めによって決まります:m'_j = Compress_1(v_j - (s^T u)_j)。これらのバイトが比較されないため、v_j の圧縮値を掃引し、変化する唯一のカプセル化解除出力を観測することで丸め境界を特定でき、その境界位置から復号ノイズ δ_j を約 ±q/64 の精度で測定できます。秘密 (s, e) と攻撃者が選択した暗号化ランダム性に関して言えば:
δ_j = ( e^T y - s^T(e1 + c_u) + e2 + c_v )_j (verified exact; small; never wraps mod q)
これは2048個の係数からなる秘密 (s, e) に関する線形方程式であり、係数は攻撃者が知っている。各暗号文は、未チェックの係数ごとに1つのそのような方程式を与える。十分な数の暗号文を積み重ねて正規方程式を解くことで鍵全体が復元され、最後のいくつかの係数は公開鍵の関係 e = t - A·s ∈ CBD(η) によって固定される。これは通常の最小二乗法であり、
格子問題ではない。
2つのバックエンドは漏洩量が異なる。NEONは暗号文の約50%を未チェックのまま残す(3つのバンドにまたがる125個の係数)のに対し、AVX2は約2%(1つのバンドに51個の係数)である。NEONは未チェックのバイトが連続しておらず、係数ごとの測定もよりノイズが多いため、依然としてより多くの暗号文を必要とする。したがって、ここではより多く漏洩することが復元を容易にするわけではない。
平文チェック攻撃や鍵不一致攻撃(Ravi et al. 2020、Qin et al. 2021、Băetu et al. 2019)は、攻撃者が選択した疎な u を持つ暗号文を送信してクエリごとに1つの秘密係数を分離することで、数千回のクエリで鍵を復元する。AVX2の欠陥はそれらすべてを拒否する。v の32バイトのみをスキップし、u 全体を検証するため、実際のバイナリ上では疎な u を持つ暗号文は拒否され、単一の u ビットを反転させると30回中30回拒否される。NEONの欠陥はより広範で、u の約半分も未チェックのまま残すため、その論拠はAVX2固有のものである。しかし、この攻撃はそれに依存していない。復号ノイズ回帰は両方のバックエンドで未チェックの v 係数から鍵を復元し、各バグがそのまま残すチェックの部分をすり抜ける。
したがって、関連する前例はそれらの鍵不一致攻撃ではなく、復号失敗攻撃(D'Anvers et al. 2019、ref 6)である。それらは同じ復号ノイズ項(秘密の線形関数)を悪用するが、その項が復号境界を越えて復号失敗を引き起こすという稀な事象を通じてのみ行うため、そこでの復元は統計的であり、はるかに多くの暗号文を必要とする。一方、不完全な比較はその同じ項を約±q/64まで直接測定可能にするため、失敗は不要であり、攻撃は上記の通常の最小二乗回帰に帰着する。
両方のバックエンドに対する忠実な参照モデル(kyber-py)では、上記の恒等式が厳密に検証され、回帰によって2048個の秘密係数すべてが復元される。修正前の実際のwolfSSLバイナリに対して、再利用されたエクスポート済み鍵を攻撃する際、各ハーネスは数値を報告する前にオラクルがエクスポートした正解鍵に対する自己チェックを実行する:
(s, e) の98.0%に到達。秘密 s のみでは350 ctで1005/1024 = 98.1%であり、これはCVEに記録された数値である。(s, e) の2018/2048 = 98.5%に到達し、ソルバーの誤差は単調に厳密値へ収束する。復元された鍵はオラクルがエクスポートしたwolfSSL生成の鍵ペアであり、攻撃はそのモデルではなく出荷形態のSIMDアセンブリに対して実行される。完全なトランスクリプト:
avx2-cve-2026-10097/live_recover_avx2.out、
neon-cve-2026-6330/live_recover_neon.out。
wolfSSL 5.9.2以降にアップグレードすること(AVX2についてはPR #10430、NEONについてはPR #10192)。
高、ただし壊滅的ではない。再利用された鍵、accept/reject オラクル、そして大規模だが実用的な数のクエリが必要である。これはサイドチャネルではない。タイミングや電力の測定はなく、比較におけるロジックバグのみである。正しい実装や ML-KEM 標準自体には影響しない。比較として、liboqs の ML-KEM デカプセル化におけるコンパイラ起因のタイミングリーク(CVE-2024-36405)は、KyberSlashと並ぶ2024年の ML-KEM タイミングリークの波における関連する全秘密鍵復元問題であり、NIST によって CVSS 7.5 と評価された。
バックエンドごとの攻撃コード、分析、再現手順は
avx2-cve-2026-10097/ と
neon-cve-2026-6330/ にある。