# DF-0220 — PoC: Predictable RNG pre-reseed claim (verification)

Finding: `findings/DF-0220-csprng-predictable-rng-pre-reseed.md`
Claim: `/dev/urandom`, `getrandom(2)`, and `kern.random` return a deterministic
all-zero-key ChaCha20 keystream before the first Fortuna reseed — identical
across independent boots.

## Files

| File             | Purpose                                                         |
|------------------|-----------------------------------------------------------------|
| `rand_probe.c`   | Reads 64 B from /dev/urandom, /dev/random, getrandom(2), kern.random; prints hex + uptime |
| `ref_keystream.c`| Computes the degenerate pre-reseed csprng keystream (all-zero chacha input[16]) for comparison |
| `build.sh`       | Builds both programs                                            |
| `run.sh`         | Runs the probe (single boot)                                    |
| `boot1_probe.txt`| Full probe output, boot #1 (fresh `vm.sh reset`)               |
| `boot2_probe.txt`| Full probe output, boot #2 (fresh `vm.sh reset`)               |
| `leak_sample.txt`| Side-by-side cross-boot byte comparison + analysis              |
| `env.txt`        | Guest uname, dmesg RNG lines, sysctl state                      |
| `VERDICT.md`     | Full narrative verdict                                          |
| `fix.diff`       | Defense-in-depth fix (gate-bypass is real, window is closed)    |
| `manifest.json`  | Machine-readable artifact catalog                               |

## Build

```
./build.sh
```
(equivalent to `cc -O2 -o rand_probe rand_probe.c && cc -O2 -o ref_keystream ref_keystream.c`)

## Run

```
./run.sh           # single-boot probe; prints hex of 4 RNG sources + uptime
./ref_keystream 64 # prints the degenerate all-zero pre-reseed keystream
```

## Expected (claim TRUE / bug present)

On two independent fresh boots, the 64-byte `/dev/urandom` (and getrandom,
kern.random) outputs would be **byte-for-byte identical** to each other AND
identical to `ref_keystream`'s output (the degenerate pre-reseed stream). With
`sysctl kern.rand_mode=csprng`, /dev/urandom would return **all zero bytes**.

## Actual (on DragonFly master DEV 6.5-DEVELOPMENT)

On two independent fresh `vm.sh reset` boots the outputs are **completely
different** (64/64 bytes differ) and **never** match the all-zero reference.
With `rand_mode=csprng`, /dev/urandom returns non-zero, varying bytes — proving
the csprng cipher context is already keyed (reseeded) before any userspace read.
**The claim does not reproduce.** See `VERDICT.md` and `leak_sample.txt` for the
root cause (the per-CPU `globaldata` entropy feed reseeds pool[0] during
`rand_initialize`, before `init`).

## Reproduce across boots (the decisive test)

```
dfbsd-qemu/vm.sh reset
dfbsd-qemu/vm.sh run_user 'cd poc/DF-0220 && ./rand_probe' > boot1.txt
dfbsd-qemu/vm.sh reset
dfbsd-qemu/vm.sh run_user 'cd poc/DF-0220 && ./rand_probe' > boot2.txt
diff <(sed -n '/\/dev\/urandom/,/^$/p' boot1.txt) \
     <(sed -n '/\/dev\/urandom/,/^$/p' boot2.txt)   # differs => not reproducible
```
(Note: `vm.sh reset` reverts the disk, so the PoC must be re-deployed — see
`build.sh`/`run.sh` which re-copy and rebuild as needed.)
