# Handoff — LSX handshake complete end-to-end **Date:** 2026-07-02 **Scope of the session:** `openfut-bridge` (the delivery test) that expanded into `openfut-launcher/openfut-hook` (the fix). Nothing was committed — everything below is uncommitted working-tree state. Read `docs/connection-gate-findings.md` (bottom two sections) for the full technical narrative. This file is the short "where we are / what to do next" version. --- ## TL;DR FIFA 23 now completes the **LSX handshake and holds a sustained encrypted session against our own bridge**, live — the first EA-side step our code services end-to-end. Three changes made it work: 1. **Hook redirect** — FIFA's `connect(127.0.0.1:3216)` is rewritten to `:3217` by our hook. The existing in-process offline shim keys on **port 3216 specifically**, so a different port slips past it and lands on our host bridge (loopback is shared with the Wine/Proton prefix — same netns). 2. **AES key** = `000102030405060708090a0b0c0d0e0f`. The `[0,1,2,…,15]` sequence that looked like a placeholder is the actual session key; confirmed by round-tripping against a captured live session. 3. **Session-seed fix** — `compute_seed()` must take the **raw ASCII bytes** of the first two chars of our response hex, not parse them as a hex pair. Last live run: FIFA held one `ESTAB` connection to the bridge and drove 20 EbisuSDK requests with **no crash**. --- ## Current deployment state (IMPORTANT) - **The redirect hook is currently deployed** as `/mnt/games/FIFA 23/version.dll` (md5 `dab3952809c24122af228a3201b9357b`). While this is in place, FIFA routes LSX to our bridge and **requires the bridge running on 3217** or LSX will not complete. - **Backup of the previous hook:** `/mnt/games/FIFA 23/version.dll.pre-lsx-redirect.bak` (md5 `fb7a5aae…`). - **To restore the previous behavior for normal offline play:** ```bash cp "/mnt/games/FIFA 23/version.dll.pre-lsx-redirect.bak" "/mnt/games/FIFA 23/version.dll" ``` - The bridge process from this session may or may not still be running. Check: `pgrep -a openfut-bridge` / `ss -tlnp | grep 3217`. --- ## Uncommitted changes (nothing is committed) ### `openfut-bridge` - `src/lsx.rs`: - **Seed fix** in `compute_seed()` (the load-bearing change). - AES-128 hand-roll replaced with the `aes` crate (+ a FIPS-197 unit test `aes128_matches_fips197_and_round_trips`). - A debug log line dumping raw session ciphertext (used during verification against the capture; harmless to keep, or remove). - `Cargo.toml` / `Cargo.lock`: added `aes = "0.8"`. - `docs/connection-gate-findings.md`: corrected classification + new "LSX complete" section. - `docs/HANDOFF-lsx-2026-07-02.md`: this file. - `captures/lsx-handshake-capture-2026-07-02.log`: a captured live handshake plus the raw session ciphertext, kept as a reference sample for verifying the implementation. ### `openfut-launcher/openfut-hook` - `src/connect_hook.rs`: added a `PORT_LSX_NBO (3216) → PORT_LSX_TARGET_NBO (3217)` arm in `redirect_if_ea`, plus result logging on the redirect path. > There is **other** pre-existing uncommitted work in these trees from before this > session (e.g. bridge TLS/proxy changes, core changes). Do not sweep it into a commit > without checking with the user. Confirm scope before committing anything. --- ## How to reproduce the working LSX session 1. **Build the hook** (redirect): ```bash cd openfut-launcher/openfut-hook cargo build --release --target x86_64-pc-windows-gnu ``` 2. **Deploy it** (back up first — already backed up once): ```bash SRC=openfut-launcher/openfut-hook/target/x86_64-pc-windows-gnu/release/openfut_hook.dll cp -f "$SRC" "/mnt/games/FIFA 23/version.dll" ``` 3. **Build + run the bridge on 3217:** ```bash cd openfut-bridge && cargo build --release LSX_ADDR=127.0.0.1:3217 RUST_LOG=openfut_bridge=debug \ ./target/release/openfut-bridge > /tmp/bridge-lsx.log 2>&1 & ``` 4. **Launch FIFA** (user does this — umu/Steam via `/home/alex/Desktop/launch-fifa23-live-editor.sh`). 5. **Verify:** `ss -tnp | grep 3217` should show `ESTAB FIFA23.exe ↔ openfut-bridge`, and `/tmp/bridge-lsx.log` should show multiple `LSX: dispatch …` lines (not one garbage message). --- ## Key facts / constants | Thing | Value | |---|---| | EA App LSX port (FIFA connects here) | `127.0.0.1:3216` | | Redirect target (our bridge LSX) | `127.0.0.1:3217` (`LSX_ADDR`) | | LSX AES-128-ECB key | `000102030405060708090a0b0c0d0e0f` | | Our greeting key (challenge plaintext) | `cacf897a20b6d612ad0c05e011df52bb` | | Session seed rule | first **two ASCII chars** of our `ChallengeAccepted` response hex, as raw bytes (e.g. `"0f…"` → `0x3066`), NOT the parsed hex pair | | Existing shim interception | in-process, keyed on **port 3216**; loopback is shared (FIFA netns == host netns) | Small verification helpers (`keyscan.py`, `seedscan.py`) live in the session scratchpad — trivial to recreate from `connection-gate-findings.md` if needed. --- ## Next steps (in priority order) 1. **Add a `GetGameInfo GameInfoId=…` handler** to the bridge dispatcher (`src/lsx.rs` `dispatch()`). It currently falls back to the generic `` ("unknown request type"). FIFA tolerated that, but may need real responses to progress. This is the immediate iteration surface now that we can see FIFA's real requests. 2. **Watch how far FIFA advances** with the LSX session satisfied — the next step is the Blaze/online layer (the old M2 `ONLINE_STATUS_EVENT` blocker). With LSX now handled by our bridge, that picture may change; re-evaluate M2 with FIFA actually reaching it. 3. **Port the seed fix into the hook's own `src/lsx.rs`** if the in-process LSX path is ever revived — it has the same `compute_seed` bug. 4. **Decide on the redirect's permanence** — right now it's a manual DLL swap. If LSX-via-bridge becomes the intended path, the launcher's setup/deploy flow should own it. ## Open question for the user We never captured what FIFA showed **on screen** during the successful run (advanced to a menu? sat at "connecting"? waited on `GetGameInfo`?). Ask, or observe on the next launch — it tells you whether LSX is fully satisfied or whether `GetGameInfo` is the next thing to address.