# DF-2368 — rijndael key-size validation is a no-op KASSERT (Nr=0 -> runaway round loop / OOB read)

File: `sys/crypto/rijndael/rijndael-alg-fst.c` (+ wrapper `sys/crypto/rijndael/rijndael-api.c`)

## Verdict (see VERDICT.md for the full narrative)

**REPRODUCED** on the stock INVARIANTS guest kernel (impact: panic / latent kernel DoS;
confidence: certain). Both halves of the finding were demonstrated through the REAL
kernel functions:

1. `panic: Invalid key size (0)` — `rijndael_set_key(bits=0)` reaches the KASSERT at
   `rijndael-alg-fst.c:738`, the ONLY validation. On production (non-INVARIANTS)
   kernels this compiles to `do {} while (0)` and `rijndaelKeySetupEnc` returns
   `0` at line 814, so the wrapper stores `ctx->Nr = 0` with a partially-written
   schedule (rk[0..7] written unconditionally, lines 740-743/762-763/784-785).
2. The Nr=0 consequence: the round loop (`r = Nr >> 1; for(;;){ ... rk += 8;
   if (--r == 0) break; ... }`, lines 951-1007) never terminates (`--r` runs
   -1, -2, ...) and walks `rk` forward 32 bytes per iteration, reading far past
   `ek`/`dk`. Demonstrated: **4128 bytes past the end of the 488-byte
   `rijndael_ctx`**, fatal kernel-mode read fault at `rijndaelEncrypt+0x1d9`.

NOT reachable by an unprivileged user today: every in-tree caller pre-validates the
key size (see VERDICT.md reachability section). This is a latent landmine for any
future/unprivileged-fed caller — hence the original Low severity, which this
verification confirms.

Fix validated A/B (`fix.diff`): invalid sizes rejected with zeroed schedules,
Nr=0 encrypts return immediately, and all 16 FIPS-197 / SP800-38A / OpenSSL-derived
KATs remain bit-identical.

## Rig

Kernel-compiled harness (runtime `kldload` GPFs on this guest) driving the REAL
`rijndael_set_key` / `rijndael_encrypt` / `rijndaelKeySetupEnc` through sysctl
`kern.rijnh.test`. Build/run below; all ops log with the `RIJNH:` tag (dmesg).

## Build

On the guest (as root, from this directory):

    ./build.sh              # installs rig into /usr/src, nativekernel build + install
                            # (buildkernel fails: "You must buildworld before
                            #  buildkernel" on this snapshot; nativekernel is the
                            #  documented native-tools path, same obj tree)
    reboot

## Run

    ./run_kat.sh                    # control: 16/16 KAT PASS + twin validation
    ./run_setkey.sh 0               # DEMO A: panic "Invalid key size (0)"
    ./run_poison.sh poison          # DEMO B: fatal trap 12, OOB read walk
    ./run_poison.sh direct          # DEMO B via raw rijndaelEncrypt
    ./run_idx.sh                    # DF-2367 side-channel evidence (shared rig)

After a panic the guest sits in DDB: recover with `vm.sh reset harness-kernel`
(snapshot taken right after the rig kernel was installed).

Fix validation: `patch -p1 < fix.diff` in /usr/src, rebuild, reboot, re-run the
same commands — see VERDICT.md for the recorded A/B.

## Expected output (stock kernel)

- `run_kat.sh`: `RIJNH: KAT summary 16 pass 0 fail of 16 vectors`,
  `twinval 600 vectors, 0 mismatches`, guest stays up.
- `run_setkey.sh 0`: kernel panic, ssh dies; serial console shows
  `panic: Invalid key size (0).` + backtrace rijndaelKeySetupEnc <-
  rijndael_set_key <- rijnh_run_setkey (panic.setkey0.txt).
- `run_poison.sh poison|direct`: `Fatal trap 12: page fault while in kernel
  mode`, `fault virtual address = 0x800475000`, `Stopped at
  rijndaelEncrypt+0x1d9: xorl -0x8(%rdi),%ecx` (panic.poison.txt,
  panic.direct.txt).

## Expected output (fixed kernel, fix.diff applied)

- `run_setkey.sh 0|1|127|257`: no panic; `ctx.Nr=0 ek[0]=00000000 ... dk[0]=00000000`
  (rejected, schedules zeroed).
- `run_poison.sh poison|direct`: `RIJNH: poison: SURVIVED Nr=0 encrypt; ct=00000000`.
- `run_kat.sh`: `16 pass 0 fail` — bit-identical to baseline (fixrun_dmesg.txt
  vs kat_baseline_dmesg.txt).

## Artifacts

- rijndael_harness.c / rijndael_twin_tables.h — kernel rig (twin tables are a
  verbatim copy of the Te tables from rijndael-alg-fst.c lines 56-386,718-722)
- rijnh.c — userland driver (mmaps the guard-page layout for DEMO B)
- build.sh, run_*.sh — exact commands
- build_baseline.log / build_fixed.log / install_*.log — full kernel build logs
- kat_baseline_dmesg.txt — stock-kernel KAT + twinval control (16/16, 600/600)
- panic.setkey0.txt / panic.poison.txt / panic.direct.txt — serial-console panics
- idx_dmesg.txt / idx_run.out / idx_analysis*.txt — DF-2367 evidence (shared)
- fixrun_dmesg.txt — fixed-kernel A/B log
- fix.diff — git-apply-able fix (validated on guest; never applied to sys/ here)
- env.txt, ttables.txt — guest environment, T-table kernel addresses
