{
  "finding_id": "DF-3567",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "none",
  "confidence": "certain",
  "verdict": "BF_set_key clamps len from above (bf_skey.c:80-81) but never from below, so len<=0 makes all 72 key-schedule byte loads dereference data[0] (bf_skey.c:83-99) - a 1-byte out-of-bounds read of a zero-length key buffer, same class as the known rc4 DF-0971/DF-2366. Reproduced in-guest with the same-source userland-object pattern: guard-page run faults with si_addr==data (exit 42). Impact is none because BF_set_key has zero in-tree callers (compiled-in dead code under option crypto, sys/conf/files:2257); filed as hardening so a future caller cannot inherit the primitive. Fix validated at harness level: with fix.diff (skip P[] key mixing when len<1) the fault is gone and both the 9/9 Schneier KATs and the len-1..120 LibreSSL byte-identity differential still pass.",
  "exploit_chain": "",
  "evidence": "guard.log: FAULT-CONFIRMED: sig=11 si_addr=0x800475000 (baseline len=0); fixval.log: BUG-NOT-PRESENT: survived len=0 + RESULT-PASS 0 failures for bfkat_fixed/bfdiff_fixed; run.log: 9/9 Schneier vectors; bfdiff.log: kernel-vs-LibreSSL len 1..120 identical",
  "kernel_refs": [
    "sys/crypto/blowfish/bf_skey.c:80",
    "sys/crypto/blowfish/bf_skey.c:84",
    "sys/crypto/blowfish/bf_skey.c:86",
    "sys/crypto/blowfish/blowfish.h:83",
    "sys/conf/files:2257"
  ],
  "poc_changes": "No seed PoC existed; authored guard-page harness (guard_bf_len0.c) plus bfkat/bfdiff correctness harnesses. One compile fix on the way: DragonFly siginfo_t field is si_addr (not si_addr member via si->addr) and _exit needs unistd.h.",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 420,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -DNDEBUG -I shim -I /usr/src/sys -o guard_bf_len0 guard_bf_len0.c /usr/src/sys/crypto/blowfish/bf_skey.c /usr/src/sys/crypto/blowfish/bf_enc.c",
  "run_cmd": "./guard_bf_len0   # expect FAULT-CONFIRMED exit 42 baseline; ./guard_bf_fixed expect exit 0",
  "code_hash": "7f78a5aed1006841ea43a32c7d502f20a708b855fa12edb93f0e72663333fec2",
  "notes": "Phase V scope: Info hardening finding - full guest Phase V was not contractually required, but the batch requested in-guest correctness verification (KAT/cross-match), which subsumed the primitive demo and fix validation. bf_pi.h digit-table integrity proven by the 9/9 Schneier KATs; wrap loop and >72 clamp proven by the LibreSSL differential (len 1..120, pseudo-random keys). In-kernel reachability: none (dead code). Zeroization note: stack in[2] schedule scratch is not scrubbed (OpenSSL heritage) - below reporting threshold.",
  "recommended_fix": "bf_skey.c: skip the P[] key-mixing loop reads when len < 1 (see fix.diff), so no key byte is dereferenced for a degenerate length.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff applied to a source copy (never sys/): guard harness prints BUG-NOT-PRESENT (exit 0) instead of the data[0] fault; bfkat 9/9 and bfdiff len-1..120 vs LibreSSL still byte-identical - no behavioral change for valid lengths. Harness-level validation only (no kernel build): the function has no in-kernel callers, so no kernel-path regression is possible.",
  "fix_evidence": "fixval.log: BUG-NOT-PRESENT: survived len=0, RESULT-PASS: 0 failures x2 (bfkat_fixed, bfdiff_fixed)"
}