A
2026-07-01 23:09:47 -04:00
|
|
|
# Roadmap — Closed-Loop eSIM Provisioning ("SIM Drop")
|
|
|
|
|
|
|
|
|
|
_Last updated: 2026-07-02_
|
|
|
|
|
|
|
|
|
|
## Context
|
|
|
|
|
|
|
|
|
|
**Goal.** A "SIM drop": a WiFi access point dropped into the field, pre-loaded
|
|
|
|
|
with a batch of eSIM profiles already registered in the 5G core, that hands
|
|
|
|
|
credentials to devices through a captive portal reached by QR code. If a backhaul
|
|
|
|
|
link to the core exists, it can also register new subscribers dynamically.
|
|
|
|
|
|
|
|
|
|
**End devices.**
|
|
|
|
|
- **COTS UEs** (handsets / modems) with real eUICCs.
|
|
|
|
|
- An in-house **software UE stack** that can load credentials from a file.
|
|
|
|
|
|
|
|
|
|
**Constraints & resources.**
|
|
|
|
|
- **Purely eSIM** — no physical SIM programming (Open-Cells cards on hand are not
|
|
|
|
|
the target path).
|
|
|
|
|
- Available for testing: **srsRAN gNB + Open5GS running**, a **test eUICC / phone**.
|
|
|
|
|
- Deployment targets **Pi and Android**, equally.
|
|
|
|
|
|
A
2026-07-01 23:15:24 -04:00
|
|
|
## The trust model (and how we work with it — not against it)
|
|
|
|
|
|
|
|
|
|
Consumer eSIM (GSMA SGP.22 RSP) doesn't let you sideload a profile file into an
|
|
|
|
|
eUICC: the device's LPA downloads it from an **SM-DP+**, and the eUICC only
|
|
|
|
|
installs profiles from an SM-DP+ whose certificate chains to a **CI root the
|
|
|
|
|
eUICC trusts**.
|
|
|
|
|
|
|
|
|
|
The key realization: **we control which eUICC the device uses.** We do *not* need
|
|
|
|
|
to defeat a phone's soldered factory eUICC (that would need GSMA CI accreditation).
|
|
|
|
|
Instead we supply a **controllable eUICC** whose root-of-trust is ours/test — and
|
|
|
|
|
then any COTS UE works with our own local SM-DP+, with **no GSMA involvement**.
|
|
|
|
|
This is a productized, well-trodden path (sysmocom sells the cards and runs a
|
|
|
|
|
test SM-DP+ for them).
|
|
|
|
|
|
|
|
|
|
Concretely, three ingredients:
|
|
|
|
|
|
|
|
|
|
1. **A controllable eUICC**, e.g. **sysmoEUICC1** — a removable eUICC in 2FF/3FF/4FF
|
|
|
|
|
plastic (or MFF2 solder) form, loaded with **test (SGP.26) or private roots**
|
|
|
|
|
instead of GSMA keys. Plugs into virtually any COTS phone/modem with a SIM slot.
|
|
|
|
|
2. **A local SM-DP+** — Osmocom **`osmo-smdpp`** (proof-of-concept, ships with
|
|
|
|
|
pySim), serving *our* SAIP profiles, using SGP.26 test / private-root certs that
|
|
|
|
|
match the eUICC.
|
|
|
|
|
3. **An LPA on the device** — **EasyEUICC / OpenEUICC** (Android, via UICC Carrier
|
|
|
|
|
Privileges; needs the eUICC's ISD-R to grant an ARA-M rule) or **`lpac`** for
|
|
|
|
|
modems / CLI. The LPA consumes an activation-code **QR** and drives the install.
|
|
|
|
|
|
|
|
|
|
Delivery tracks:
|
A
2026-07-01 23:09:47 -04:00
|
|
|
|
|
|
|
|
- ✅ **Software UE** — loads a profile/credential file directly. Works today, no RSP.
|
A
2026-07-01 23:15:24 -04:00
|
|
|
- ✅ **COTS UE + controllable eUICC** — removable sysmoEUICC (test/private root) in a
|
|
|
|
|
COTS phone/modem + LPA + our local `osmo-smdpp`. The real eSIM path.
|
|
|
|
|
- ⚠️ **A phone's untouched factory eUICC** — would reject a local SM-DP+ (needs GSMA
|
|
|
|
|
CI accreditation). We sidestep this by supplying the eUICC, so it's not a blocker.
|
A
2026-07-01 23:09:47 -04:00
|
|
|
|
|
|
|
|
## Where we are (done)
|
|
|
|
|
|
|
|
|
|
Provisioning server: credential generation (IMSI/Ki/OPc/ICCID), SQLite store,
|
|
|
|
|
per-MAC rate limiting, captive portal, Open5GS/free5gc adapters, `v2` + real
|
|
|
|
|
`SAIP` profile generation, security-hardened, 109 tests. **Missing: the last mile
|
|
|
|
|
(delivery to a device) and live core-integration proof.**
|
|
|
|
|
|
|
|
|
|
## Target architecture
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Drop device (Pi / Android)
|
|
|
|
|
├─ WiFi AP (open) + captive portal (QR entry)
|
|
|
|
|
├─ Provisioning server (Flask) ← built
|
|
|
|
|
├─ Subscriber DB (pre-registered batch + dynamic) ← built, needs batch layer
|
|
|
|
|
├─ Local SM-DP+ (osmo-smdpp) ← Phase 3
|
|
|
|
|
└─ Backhaul to core (optional) ← dynamic registration when present
|
|
|
|
|
|
|
|
|
|
Two delivery tracks:
|
A
2026-07-01 23:15:24 -04:00
|
|
|
Track S — Software UE: profile file → soft-UE → attach (Phase 1)
|
|
|
|
|
Track E — COTS UE + eUICC: COTS phone/modem with a controllable
|
|
|
|
|
(removable/private-root) eUICC + LPA:
|
|
|
|
|
QR activation code → LPA → local SM-DP+
|
|
|
|
|
→ eUICC installs SAIP profile → attach (Phase 3)
|
A
2026-07-01 23:09:47 -04:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Phases
|
|
|
|
|
|
|
|
|
|
### Phase 0 — Prove core attach (de-risk the foundation)
|
|
|
|
|
Register one generated credential in Open5GS and attach with the software UE (or
|
|
|
|
|
a test eUICC) on srsRAN+Open5GS; confirm authentication succeeds.
|
|
|
|
|
- Validates our Milenage/OPc derivation and the adapter document shape against a
|
|
|
|
|
**live** core — everything downstream depends on this being correct.
|
|
|
|
|
- **Needs from you:** Open5GS reachability (MongoDB URI / network) or you run the
|
|
|
|
|
sync; the slice (SST/SD), APN/DNN, and PLMN the gNB expects.
|
|
|
|
|
|
|
|
|
|
### Phase 1 — Software-UE loop (file delivery; first closed loop, no SM-DP+)
|
|
|
|
|
- Define the soft-UE profile format and add an exporter (extend
|
|
|
|
|
`scripts/make_profile.py` / a new `/api/provision` format).
|
|
|
|
|
- Flow: WiFi → captive portal → provision → download soft-UE profile → attach.
|
|
|
|
|
- **Needs from you:** the exact format your soft-UE ingests (e.g. srsUE-style
|
|
|
|
|
`ue.conf` with `imsi/k/opc/opc_type`, or a custom schema).
|
|
|
|
|
|
|
|
|
|
### Phase 2 — Pre-registered batch + drop packaging (the "drop" model) [software-only; can start now]
|
|
|
|
|
- Batch generator: pre-generate _N_ profiles, register all in the core, persist to
|
|
|
|
|
the drop DB marked "available".
|
|
|
|
|
- Captive-portal **claim** flow: atomically hand an unclaimed pre-registered
|
|
|
|
|
profile to a device (QR/portal).
|
|
|
|
|
- **Offline operation:** with no backhaul, hand out from the pre-loaded batch;
|
|
|
|
|
queue dynamic registrations for when the core link returns.
|
|
|
|
|
- Deliverable: a drop that works fully offline from a pre-loaded batch.
|
|
|
|
|
|
A
2026-07-01 23:15:24 -04:00
|
|
|
### Phase 3 — COTS UE via local SM-DP+ (the real eSIM last mile)
|
|
|
|
|
- Obtain **controllable eUICCs** (removable sysmoEUICC1 with SGP.26/private root, or
|
|
|
|
|
equivalent) and confirm an **LPA** on the target UEs (EasyEUICC/OpenEUICC on
|
|
|
|
|
Android; `lpac` for modems). Verify the eUICC's ISD-R grants the ARA-M rule the
|
|
|
|
|
LPA needs.
|
|
|
|
|
- Stand up **`osmo-smdpp`** on the drop; wire our SAIP profiles into it; manage the
|
|
|
|
|
matching (SGP.26/private) CI cert chain.
|
A
2026-07-01 23:09:47 -04:00
|
|
|
- Complete the SAIP profile to an installable one (PIN/PUK, ARR, security domain,
|
A
2026-07-01 23:15:24 -04:00
|
|
|
remaining mandatory PEs) — **validated against the real eUICC** (this is where
|
A
2026-07-01 23:09:47 -04:00
|
|
|
the deferred SAIP PE work finally gets card-validated rather than guessed).
|
A
2026-07-01 23:15:24 -04:00
|
|
|
Cross-check against pySim's known-good test profiles.
|
|
|
|
|
- Captive portal renders the LPA activation-code **QR**; a COTS phone/modem (with
|
|
|
|
|
the controllable eUICC) installs and attaches.
|
|
|
|
|
- Deliverable: COTS UE + controllable eUICC → scan QR → eSIM installed → on the network.
|
A
2026-07-01 23:09:47 -04:00
|
|
|
|
|
|
|
|
### Phase 4 — Field hardening (Pi + Android, first-class)
|
|
|
|
|
Offline/power/thermal, monitoring/observability, capacity, subscriber
|
|
|
|
|
revoke/expire/resync, backhaul-aware dynamic registration, secure batch loading.
|
|
|
|
|
|
|
|
|
|
## Recommended immediate next steps
|
|
|
|
|
|
|
|
|
|
1. **Phase 0** — prove live attach (software UE + Open5GS). Highest de-risking value.
|
|
|
|
|
2. **Phase 2 groundwork (in parallel, software-only, no hardware needed):** the
|
|
|
|
|
batch pre-registration generator + atomic claim flow. This is squarely on the
|
|
|
|
|
critical path for the "dropped, pre-loaded, offline" model and I can build and
|
|
|
|
|
test it now.
|
|
|
|
|
|
|
|
|
|
## Open questions
|
|
|
|
|
|
|
|
|
|
- **Soft-UE profile format** — what schema does your software UE ingest?
|
|
|
|
|
- **Open5GS access** — reachable from the dev environment, or do you run sync?
|
|
|
|
|
MongoDB URI, slice SST/SD, APN/DNN, PLMN to match the gNB.
|
|
|
|
|
- **SM-DP+** — OK to vendor/run `osmo-smdpp` on the drop, or a different RSP?
|
A
2026-07-01 23:15:24 -04:00
|
|
|
- **Controllable eUICCs** — which eUICC do we standardize on (sysmoEUICC1 with
|
|
|
|
|
SGP.26 vs private root)? Do the current "test eUICC/phone" you have match the
|
|
|
|
|
SGP.26 root osmo-smdpp ships, or do we need a private-root batch?
|
|
|
|
|
- **LPA** — EasyEUICC/OpenEUICC (Android) and/or `lpac` (modems) as the on-device
|
|
|
|
|
LPA? Any UEs whose SIM slot / carrier-privilege behavior needs checking?
|
A
2026-07-01 23:09:47 -04:00
|
|
|
- **Batch model** — expected batch size per drop; how batches are provisioned and
|
|
|
|
|
loaded (offline media vs one-time backhaul).
|