Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions docs/demo-evidence/STORY-144/AC-144-002-before-after-contrast.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
Output AC-144-002-before-after-contrast.gif
Output AC-144-002-before-after-contrast.webm

Set FontFamily "Menlo"
Set FontSize 14
Set Width 900
Set Height 560
Set Theme "Dracula"
Set Padding 20
Set WaitTimeout 30s

# Setup: navigate to the worktree
Hide
Type "cd /Users/zious/Documents/GITHUB/wirerust/.worktrees/story-144-tls-carry-reassembly"
Enter
Sleep 200ms
Show

# ── Title banner ───────────────────────────────────────────────────────────────
Type "echo '=== BEFORE vs AFTER: TLS ClientHello fragmentation reassembly (STORY-144) ==='"
Enter
Sleep 600ms

# ── BEFORE: baseline develop (missed SNI/JA3) ────────────────────────────────
Type "echo '--- BEFORE (baseline develop): fragmented ClientHello ---'"
Enter
Sleep 300ms
Type "echo ' SNI: (empty -- MISSED)'"
Enter
Sleep 200ms
Type "echo ' JA3: (empty -- MISSED)'"
Enter
Sleep 200ms
Type "echo ' parse_errors: 2'"
Enter
Sleep 800ms

# ── AFTER: STORY-144 (reassembled, SNI/JA3 extracted) ────────────────────────
Type "echo '--- AFTER (STORY-144): same fragmented pcap ---'"
Enter
Sleep 300ms
Type "/Users/zious/Documents/GITHUB/wirerust/.factory/demo-evidence/fix-tls-clienthello-frag/story-144/show-tls-result.sh /Users/zious/Documents/GITHUB/wirerust/.factory/demo-evidence/fix-tls-clienthello-frag/tls-clienthello-fragmented.pcap 'FRAGMENTED (reassembled)'"
Enter
Wait+Screen /parse_errors/
Sleep 3s
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions docs/demo-evidence/STORY-144/AC-144-002-control-regression.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Output AC-144-002-control-regression.gif
Output AC-144-002-control-regression.webm

Set FontFamily "Menlo"
Set FontSize 14
Set Width 900
Set Height 380
Set Theme "Dracula"
Set Padding 20
Set WaitTimeout 30s

# Setup: navigate to the worktree
Hide
Type "cd /Users/zious/Documents/GITHUB/wirerust/.worktrees/story-144-tls-carry-reassembly"
Enter
Sleep 200ms
Show

# ── Title banner ───────────────────────────────────────────────────────────────
Type "echo '=== STORY-144: single-record ClientHello regression check ==='"
Enter
Sleep 600ms

# ── CONTROL: single TLS record, must still work ───────────────────────────────
Type "echo '--- Control regression: ClientHello in ONE TLS record ---'"
Enter
Sleep 300ms
Type "/Users/zious/Documents/GITHUB/wirerust/.factory/demo-evidence/fix-tls-clienthello-frag/story-144/show-tls-result.sh /Users/zious/Documents/GITHUB/wirerust/.factory/demo-evidence/fix-tls-clienthello-frag/tls-clienthello-control.pcap 'CONTROL (single TLS record) -- no regression'"
Enter
Wait+Screen /parse_errors/
Sleep 3s
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions docs/demo-evidence/STORY-144/AC-144-002-reassembly-fragmented.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Output AC-144-002-reassembly-fragmented.gif
Output AC-144-002-reassembly-fragmented.webm

Set FontFamily "Menlo"
Set FontSize 14
Set Width 900
Set Height 380
Set Theme "Dracula"
Set Padding 20
Set WaitTimeout 30s

# Setup: navigate to the worktree and put the STORY-144 binary on PATH
Hide
Type "cd /Users/zious/Documents/GITHUB/wirerust/.worktrees/story-144-tls-carry-reassembly"
Enter
Sleep 200ms
Show

# ── Title banner ───────────────────────────────────────────────────────────────
Type "echo '=== AFTER fix (STORY-144): fragmented ClientHello is now REASSEMBLED ==='"
Enter
Sleep 600ms

# ── EVASION case now DETECTED ─────────────────────────────────────────────────
Type "echo '--- AC-144-002: ClientHello split across 2 TLS records ---'"
Enter
Sleep 300ms
Type "/Users/zious/Documents/GITHUB/wirerust/.factory/demo-evidence/fix-tls-clienthello-frag/story-144/show-tls-result.sh /Users/zious/Documents/GITHUB/wirerust/.factory/demo-evidence/fix-tls-clienthello-frag/tls-clienthello-fragmented.pcap 'FRAGMENTED (2 TLS records) -- STORY-144'"
Enter
Wait+Screen /parse_errors/
Sleep 3s
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Output AC-144-003-overflow-clear-recover.gif
Output AC-144-003-overflow-clear-recover.webm

Set FontFamily "Menlo"
Set FontSize 13
Set Width 900
Set Height 480
Set Theme "Dracula"
Set Padding 20
Set WaitTimeout 120s

# Setup: navigate to the worktree
Hide
Type "cd /Users/zious/Documents/GITHUB/wirerust/.worktrees/story-144-tls-carry-reassembly"
Enter
Sleep 300ms
Show

# ── Title banner ───────────────────────────────────────────────────────────────
Type "echo '=== STORY-144 AC-144-003: carry overflow -- clear and recover ==='"
Enter
Sleep 600ms

# ── Run the AC-144-003 overflow tests ─────────────────────────────────────────
Type "echo '--- Red-Gate tests: carry overflow clears state + counter in summarize() ---'"
Enter
Sleep 300ms
Type "cargo test 'test_vp039_carry_overflow_clear_and_recover' 'test_BC_2_07_039_summarize_exposes_handshake_reassembly_overflows_key' -- --nocapture 2>&1 | grep -E 'test story_144|test result'"
Enter
Wait+Screen /test result/
Sleep 3s
Binary file not shown.
120 changes: 120 additions & 0 deletions docs/demo-evidence/STORY-144/evidence-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Demo Evidence Report: STORY-144 — TLS Carry Buffer + ClientHello Fragmentation Reassembly

**Story:** STORY-144
**Branch:** `feature/story-144-tls-carry-reassembly`
**Binary:** `wirerust 0.11.0` (worktree release build)
**Date:** 2026-06-29
**Baseline reference:** `../AC-001-tls-frag-evasion-baseline.gif` (develop before fix)

---

## Headline Result

| Pcap | Baseline (develop) | STORY-144 (after fix) |
|------|-------------------|----------------------|
| `tls-clienthello-fragmented.pcap` | SNI: MISSED, JA3: MISSED, parse_errors: 2 | **SNI: ['example.com'], JA3: 6169fabc98e3e6c9..., parse_errors: 0** |
| `tls-clienthello-control.pcap` | SNI: ['example.com'], JA3: detected | SNI: ['example.com'], JA3: detected (no regression) |

**The evasion is closed.** The same fragmented ClientHello pcap that produced zero SNI/JA3 on baseline now correctly extracts both after STORY-144.

---

## AC Coverage

### AC-144-002: Handshake-message carry buffer (ClientToServer)

Behavioral contract: `BC-2.07.038`. A ClientHello fragmented across multiple TLS records must be reassembled and SNI/JA3 extracted as if it arrived in a single record.

#### Demo: Fragmented ClientHello → NOW DETECTED

| File | Description |
|------|-------------|
| `AC-144-002-reassembly-fragmented.gif` | `tls-clienthello-fragmented.pcap` against STORY-144 binary. Shows SNI=['example.com'], JA3 hash, parse_errors:0 |
| `AC-144-002-reassembly-fragmented.webm` | Same recording, archival format |
| `AC-144-002-reassembly-fragmented.tape` | VHS script source |

**Path covered:** success path (fragmented ClientHello fully reassembled).

#### Demo: Single-record Control Regression Check

| File | Description |
|------|-------------|
| `AC-144-002-control-regression.gif` | `tls-clienthello-control.pcap` against STORY-144 binary. Shows SNI still extracted (no regression). |
| `AC-144-002-control-regression.webm` | Same recording, archival format |
| `AC-144-002-control-regression.tape` | VHS script source |

**Path covered:** regression guard — single-record path unaffected by carry logic.

#### Demo: Before/After Contrast (Headline)

| File | Description |
|------|-------------|
| `AC-144-002-before-after-contrast.gif` | Side-by-side text showing BEFORE (MISSED/parse_errors:2) followed by AFTER STORY-144 (SNI+JA3 extracted, parse_errors:0) |
| `AC-144-002-before-after-contrast.webm` | Same recording, archival format |
| `AC-144-002-before-after-contrast.tape` | VHS script source |

**Path covered:** before/after contrast for PR evidence. The BEFORE values are reproduced from the baseline recording at `../AC-001-tls-frag-evasion-baseline.gif`.

---

### AC-144-003: Clear-and-recover on carry buffer overflow

Behavioral contract: `BC-2.07.039`. When a carry buffer overflow is detected (body_len > MAX_BUF = 65,536, or carry + payload would exceed MAX_BUF), the carry is cleared and `handshake_reassembly_overflows` is incremented. The counter is surfaced in `summarize()` detail.

**Recording method:** Unit test output via `cargo test --nocapture` (see note below).

| File | Description |
|------|-------------|
| `AC-144-003-overflow-clear-recover.gif` | `cargo test` run of `test_vp039_carry_overflow_clear_and_recover` + `test_BC_2_07_039_summarize_exposes_handshake_reassembly_overflows_key`. Both pass (ok). |
| `AC-144-003-overflow-clear-recover.webm` | Same recording, archival format |
| `AC-144-003-overflow-clear-recover.tape` | VHS script source |

**Note on recording method:** Crafting a real PCAP that triggers the overflow path and then shows `handshake_reassembly_overflows` in JSON output requires a multi-packet pcap with a spoofed body_len. The unit tests directly invoke `TlsAnalyzer::on_data` with crafted byte vectors that produce the overflow condition and then call `summarize()` to verify the counter. The terminal recording shows both tests passing under `cargo test`, which is the correct evidence for this invariant. A future improvement could craft a pcap via `gen_pcaps.py` but is out of scope for STORY-144.

**Paths covered:** overflow-clear path (Decision-5 guard), counter persistence through `summarize()`.

---

## Full Coverage Matrix

| AC | Description | Recording | Error Path | Notes |
|----|-------------|-----------|------------|-------|
| AC-144-002 | Two-record fragmented ClientHello reassembly | `AC-144-002-reassembly-fragmented.gif` | N/A (failure=baseline, see `../AC-001-tls-frag-evasion-baseline.gif`) | Success path demonstrated on real pcap fixture |
| AC-144-002 | Control regression (single-record) | `AC-144-002-control-regression.gif` | N/A | No regression confirmed |
| AC-144-002 | Before/after contrast | `AC-144-002-before-after-contrast.gif` | BEFORE = error path reproduced from baseline text | Headline PR evidence |
| AC-144-003 | Carry overflow clear-and-recover | `AC-144-003-overflow-clear-recover.gif` | Overflow condition triggered in unit test | Unit-test capture (pcap infeasible without crafted fixture) |

---

## Fixtures Reused

These fixtures from the baseline cycle are reused unchanged:

| File | Hash (sha256 prefix) |
|------|----------------------|
| `../tls-clienthello-control.pcap` | baseline fixture, single TLS record |
| `../tls-clienthello-fragmented.pcap` | baseline fixture, 2-record split |

---

## Baseline Comparison

The baseline recording (`../AC-001-tls-frag-evasion-baseline.gif`) showed:

```
EVASION (2 TLS records):
SNI: (empty — MISSED)
JA3: (empty — MISSED)
parse_errors: 2
```

STORY-144 produces:

```
FRAGMENTED (reassembled):
SNI: ['example.com']
JA3: 6169fabc98e3e6c9...
parse_errors: 0
```

**Evasion closed: YES.**
21 changes: 21 additions & 0 deletions docs/demo-evidence/STORY-144/show-tls-result.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh
# Show compact TLS analysis: SNI, JA3, parse_errors
# Uses the STORY-144 release binary in the worktree
PCAP="$1"
LABEL="$2"
WDIR="/Users/zious/Documents/GITHUB/wirerust/.worktrees/story-144-tls-carry-reassembly"
echo "=== $LABEL ==="
"$WDIR/target/release/wirerust" analyze --tls --json /tmp/wrtls-out.json "$PCAP" 2>/dev/null
python3 -c "
import sys, json
with open('/tmp/wrtls-out.json') as f:
data = json.load(f)
tls = next(a for a in data['analyzers'] if a['analyzer_name'] == 'TLS')
d = tls['detail']
sni = d['top_snis']
ja3 = list(d['ja3_hashes'].keys())
errs = d['parse_errors']
print(f' SNI: {sni if sni else \"(empty -- MISSED)\"}')
print(f' JA3: {ja3[0][:16]+\"...\" if ja3 else \"(empty -- MISSED)\"}')
print(f' parse_errors: {errs}')
"
Loading