DF-2367 / verdict.json
{ "finding_id": "DF-2367", "status": "reproduced", "reproduced": 1, "impact": "leak", "confidence": "likely", "verdict": "The side-channel mechanism is reproduced byte-exact through the REAL kernel rijndael code: every T-table lookup index in rijndaelEncrypt/rijndaelDecrypt is a secret-dependent byte (round 1: index = key_byte XOR plaintext_byte; rijndael-alg-fst.c:953-1007, 1013-1040). An instrumented twin of the round loop, validated byte-exact against the real rijndael_encrypt on 900 vectors with ct(real==twin) asserted per trace, dumped the 160-index access sequence per AES-128 block: flipping one key byte flips exactly the corresponding round-1 index and the touched Te0 cache line (tables are 1 KB = 16 cache lines at fixed kernel addresses, ttables.txt), and 40/40 statistical samples satisfy all 16 round-1 index==key^pt identities. End-to-end Prime+Probe/Flush+Reload key recovery was NOT executed: QEMU/KVM provides no cache-occupancy measurement fidelity for a cross-mode attack, and an aggregate timing probe honestly showed no separable signal (59-69 ns/op, overlapping) because the channel is per-access line occupancy, which is precisely what the trace demonstrates. Reachability confirmed: wlan_ccmp calls rijndael_encrypt several times per 802.11 frame with no AES-NI bypass, and cryptoapi AES-CBC/XTS (dm-crypt) walks the same tables on every block IO; opencrypto/IPsec use a separate aesni path. Confidentiality-only local key recovery channel; Medium as filed; privesc closed (no write primitive, no direct kernel-memory disclosure).", "exploit_chain": "co-resident unprivileged observer primes/probes LLC sets covering the kernel Te0 lines (fixed KVA, 16 lines/table) while the victim encrypts (wlan_ccmp per-frame or dm-crypt IO); round-1 hit pattern yields index = key XOR known plaintext byte; repeating over known/chosen plaintexts recovers the AES key schedule (classic Osvik-Shamir-Tromer/Fush-Reload methodology for this exact T-table design). Demonstrated on-rig up to the observable: the index sequence and its line-granularity key dependence.", "evidence": "leak_sample.txt (byte-exact 160-index traces for K, K-prime, K-double-prime with per-trace ct real==twin); idx_analysis.txt (round-1 divergence at exactly the flipped key byte, 136/160 after avalanche, Te0 line 0 vs line 8); idx_analysis2.txt (40/40 samples satisfy all 16 index==key^pt identities); ttables.txt (Te0 at 0xffffffff80d897e0, 0x400-byte tables); idx_dmesg.txt (full kernel log incl. timing probe honest negative); kat_baseline_dmesg.txt (16/16 KAT control)", "kernel_refs": [ "sys/crypto/rijndael/rijndael-alg-fst.c:56", "sys/crypto/rijndael/rijndael-alg-fst.c:953", "sys/crypto/rijndael/rijndael-alg-fst.c:978", "sys/crypto/rijndael/rijndael-alg-fst.c:1013", "sys/crypto/rijndael/rijndael-alg-fst.c:1132", "sys/crypto/rijndael/rijndael-api.c:53", "sys/netproto/802_11/wlan_ccmp/ieee80211_crypto_ccmp.c:141", "sys/netproto/802_11/wlan_ccmp/ieee80211_crypto_ccmp.c:399", "sys/crypto/cryptoapi/cryptoapi.c:314", "sys/crypto/cryptoapi/cryptoapi.c:405", "sys/dev/disk/dm/crypt/dm_target_crypt.c:306" ], "poc_changes": "Original filing had no runnable PoC (poc_path null). Rig authored from scratch: kernel-compiled sysctl harness (runtime kldload GPFs on this guest) with an instrumented twin of the round loop (tables copied verbatim from the audited source) validated byte-exact against the real functions on every run; several SP800-38A expected values sketched from memory in the filing preparation were wrong and were re-derived against OpenSSL 3.0.22 before embedding (checkvec.log).", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Mon Oct 19 02:17:08 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 2280, "guest_dirty": 0, "build_cmd": "sh build.sh (installs rig into guest /usr/src, make -j6 nativekernel KERNCONF=X86_64_GENERIC, make installkernel, builds /root/rijnh); reboot", "run_cmd": "sh run_idx.sh (idx full traces + idxr1 matrix + table addresses + timing probe; results in dmesg tag RIJNH:)", "code_hash": "1bcb06fab7f0552321352a960a146d4d301c0e9475dc31608ba41f0af45e5f2a", "notes": "No fix.diff: the remedy is an algorithm swap (AES-NI or constant-time implementation for wlan_ccmp and cryptoapi software AES), not a minimal patch validatable on this rig. Aggregate timing probe honestly negative (warm caches); the demonstrated observable is the secret-dependent memory-access pattern itself. Privesc assessment: closed - read-only side channel, confidentiality impact only.", "recommended_fix": "Route wlan_ccmp and cryptoapi software AES through the in-tree AES-NI implementation with a constant-time (bitsliced) fallback instead of the T-table rijndael core" } |