Layr-Labs / Layr-Labs/d-inference

MDA gate: Apple-root the device serial to the connection's SE key (self-asserted-serial residual from #302)

Open
#328 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
527
Forks
114
Avg merge
17h 26m
Merged PRs (30d)
111

Description

Follow-up to #302 / PR #327. The MDA SIP routing gate verifies the provider's **self-asserted** attestation serial, not one cryptographically rooted to the connection's Secure-Enclave key.

## The gap
`evaluateMDA` compares the Apple-signed MDA cert serial against `AttestationResult.SerialNumber`, which is signed by the provider's **own** SE key over any serial it chooses. A malicious owner with a **second, genuinely-SIP-on enrolled Mac** (`M_clean`) can serve inference from a SIP-off box (`M_dirty`) that registers with its own SE key but claims `M_clean`'s serial:
1. MDM SecurityInfo lookup (by claimed serial) hits `M_clean` → SIP-on.
2. The MDA nonce (derived from `M_dirty`'s SE key) is sent to `M_clean`'s UDID; `M_clean` echoes it in a genuine Apple cert with `M_clean`'s serial.
3. The gate sees a fresh, SIP-on, serial-matching verdict → `M_dirty` routes private text while SIP-off.

The live per-connection SE challenge proves `M_dirty` holds the SE key it *registered*, but nothing binds that key to the *claimed serial*.

## Why it's not a quick coordinator fix
macOS has no App Attest, so an app-held SE key can't be tied to a device serial with the obvious primitives. A coordinator-only ACME serial check was prototyped in #327 and **reverted** because:
- The served ACME profile (`enroll.go`) mints a **P-384** key with `HardwareBound: true` — but the Secure Enclave is **P-256-only**, so it can't be a hardware-bound SE key. Fleet is **0% `acme_verified`**, confirming the ACME path doesn't currently function. Gating routing on it would brick the fleet under enforcement.
- step-ca's `acme-device.tpl` sets `"subject": {{ .Insecure.CR.Subject }}` with `forceCN: false`, so the cert **CN is copied from the device's unvalidated CSR** (attacker-controllable). The *validated* device-attest-01 serial lives in the **permanent-identifier SAN**, which the coordinator doesn't read.

## Proposed fix (provider-swift + protocol + coordinator)
1. **Re-key the ACME identity to P-256** so a single hardware-bound, Apple-attested SE key can serve as both the ACME cert key and the connection identity (or have the provider prove possession of the ACME key in the attestation challenge).
2. **Coordinator reads the validated permanent-identifier SAN** (OID 1.3.6.1.5.5.7.8.3), never `cert.Subject.CommonName`, as the Apple-rooted serial; require it == the MDA cert serial and the connection's proven key.
3. **Proxy-transit binding** for the `X-Ssl-Client-*` headers (Caddy/nginx injects a shared secret; coordinator rejects the headers otherwise) — see also the EKU hardening below.
4. **Require `clientAuth` EKU** in `extractAndVerifyClientCert` and tighten `VerifyMDADeviceAttestation` (both currently `ExtKeyUsageAny`).
5. Add a startup guard: refuse to enable MDA enforcement (`EIGENINFERENCE_MDA_ENFORCE_AFTER`) unless step-ca/ACME is wired and a fleet ACME-coverage metric is non-zero.

## Residual until then
Documented in `docs/threat-model.yaml` (TB-005). The MDA gate still requires an Apple-SEP-signed SIP-on/Full-Security attestation + fresh epoch nonce + MDM enrollment + the live SE challenge — raising the bar significantly — but the serial is not Apple-rooted to the connection's key. Bar for the attack: enroll and keep online a second SIP-on Mac.

Found via adversarial audit of #327 (round 3).

Contributor guide

Open the contributing guide

Research direction

Start with evaluateMDA, enroll.go, extractAndVerifyClientCert, VerifyMDADeviceAttestation, and the protocol changes described in the issue. Review docs/threat-model.yaml and TB-005 before changing the ACME identity and serial binding. Done means the coordinator uses the validated permanent-identifier SAN, binds it to the proven connection key, enforces the stated EKU and proxy-transit checks, and avoids enabling enforcement without ACME coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, swift
Domain
authentication, backend-api-design, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.