Using eSIMs with devices that only have a physical SIM slot via a 9eSIM SIM card with Android and Linux
Do you have a phone, tablet, or laptop (or, well, any device…) which will only take a physical SIM, but with which you’d like to use eSIMs?
Then this is a blogpost for you, as that’s exactly what this is: a physical SIM, onto which one can provision eSIMs, using software to swap between them.
What I bought from 9eSIM
I bought the bundle - SIM and smartcard reader - from 9eSIM.
The first shipment from China got lost but, after a bit of waiting, they posted another one without complaint. That was shipped by a different delivery company, and it arrived in just over a week.
In the box, I got:
-
A SIM card, with the usual push-out sections to change it from normal to micro to nano.
- The SIM was in a blue envelope, not attached to the cardboard saying “9eSIM v2” - at first, I thought “they’ve forgotten to put in the SIM card”.
- If you want to use the smartcard reader, do not discard the SIM’s packaging. You will need it to make the smartcard reader work reliably.
-
A SIM card adapter.
-
A USB smartcard reader, and a USB-A to USB-C adapter.
Including delivery, it came to about £30.
Use the SIM’s packaging to make it fit in the smartcard reader
I spent a lot of time trying to get the SIM and smartcard reader working.
The solution was a frustratingly simple one: the best way to use the supplied smartcard reader is to use the original packaging for the SIM.
This packaging is the right size to slide into the reader while positioning the SIM’s contacts over the contact points on the reader. I will keep that together with the smartcard reader.
When I realised that - rather than trying to slide the popped-out SIM into the right place and keep it there - it Just Worked.
Adding and switching eSIMs
The SIM card is advertised as have “a memory capacity of 1.6M, [which] can store up to 50 groups of eSIM profile data”.
To make use of it, one needs to download one or more eSIMs to the SIM.
To do this, and to switch between profiles, one needs to use a “Local Profile Agent” (or “LPA”).
I tested the process for this using both Android and Linux, and both worked just fine.
Test eSIM profiles you can try to for free
While I was getting used to how it worked, I didn’t want to buy an actual eSIM.
Fortunately, there are a couple of options.
First, there are four official Android test eSIM profiles
While I could start to provision these, I could not download them, with what appears to be a TLS error.
Second, osmocom has a very useful page of other test profiles.
I was able to install test eSIM profiles for TruPhone and TruPhone / Speedtest.
These provisioned correctly onto the SIM. I could not use them to make or receive calls or start a data session - which was fine - but they did show up in Android’s SIM card manager as available eSIMs.
Adding and switching eSIMs via Android
There is an .apk from the 9eSIM site.
I wasn’t too keen on using this but, well, it worked, and is probably the simplest option.
I tested it first by putting the SIM into my phone, replacing my main physical SIM. This was recognised by the app immediately.
Once I had worked out how to correctly seat the SIM in the reader, I tried that too, using a USB-C hub to connect the smartcard reader to my phone. That worked fine too.
Provisioning eSIMs using the Android application was easy as long as the QR code was on a different screen, since I could just scan the QR code for the eSIM using the camera. I’ve not looked to see if there is a way to use Android to import a QR code on its own screen.
Using the 9eSIM application, one can enable and disable eSIMs, and swap between them. Once enabled, they appeared in Android’s own SIM management settings. I did not need to reboot.
Deleting an eSIM is also easy. One needs to type a security phrase - the name of the eSIM - to trigger deletion, which is a simple means of avoiding accidental deletion.
Adding and switching eSIMs via Linux
Since I want to use the SIM with the integrated WWAN modem of a laptop running Linux, I was keen to see if I could get this all to work using Linux and Free software.
So far, I have not found a way of writing profiles to the SIM while it is in the laptop - I need to take it out and put it in the smartcard reader.
And, if I’m going to do that then, from a practical point of view, it is little more effort to hook it up to my phone and swap and provisions eSIMs from there.
Still, I wanted to get it working within Linux and FOSS just because.
The smartcard reader and Linux
Connecting the smartcard reader and running lsusb
:
Bus 001 Device 011: ID 058f:9540 Alcor Micro Corp. AU9540 Smartcard Reader
It looks like this is a quite common smartcard reader, sometimes built into laptops.
lsusb -s 1:11 -v
:
Bus 001 Device 011: ID 058f:9540 Alcor Micro Corp. AU9540 Smartcard Reader
Negotiated speed: Full Speed (12Mbps)
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.01
bDeviceClass 0 [unknown]
bDeviceSubClass 0 [unknown]
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x058f Alcor Micro Corp.
idProduct 0x9540 AU9540 Smartcard Reader
bcdDevice 1.20
iManufacturer 1 Generic
iProduct 2 EMV Smartcard Reader
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x005d
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 50mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 11 Chip/SmartCard
bInterfaceSubClass 0 [unknown]
bInterfaceProtocol 0
iInterface 0
ChipCard Interface Descriptor:
bLength 54
bDescriptorType 33
bcdCCID 1.10
nMaxSlotIndex 0
bVoltageSupport 7 5.0V 3.0V 1.8V
dwProtocols 3 T=0 T=1
dwDefaultClock 3700
dwMaxiumumClock 12000
bNumClockSupported 3
dwDataRate 9946 bps
dwMaxDataRate 688172 bps
bNumDataRatesSupp. 138
dwMaxIFSD 254
dwSyncProtocols 00000007 2-wire 3-wire I2C
dwMechanical 00000000
dwFeatures 000404BE
Auto configuration based on ATR
Auto activation on insert
Auto voltage selection
Auto clock change
Auto baud rate change
Auto PPS made by CCID
Auto IFSD exchange (T=1)
Short and extended APDU level exchange
dwMaxCCIDMsgLen 272
bClassGetResponse echo
bClassEnvelope echo
wlcdLayout none
bPINSupport 0
bMaxCCIDBusySlots 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0004 1x 4 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 0
Binary Object Store Descriptor:
bLength 5
bDescriptorType 15
wTotalLength 0x000c
bNumDeviceCaps 1
USB 2.0 Extension Device Capability:
bLength 7
bDescriptorType 16
bDevCapabilityType 2
bmAttributes 0x00000002
HIRD Link Power Management (LPM) Supported
Device Status: 0x0000
(Bus Powered)
I spent quite a long time trying to work out why it would not detect the SIM in the smartcard reader (which, as above, was solved by using the supplied packaging material).
I have not reproduced all my troubleshooting here, but it was reasonably obvious from the error messages that, while my laptop recognised and could talk to the smartcard reader, the SIM was not recognised.
lpac
I started with a command line tool called lpac
.
It has a .deb release version, which I installed with:
sudo apt install lpac_2.1.0_amd64.deb -y
It installed without error to /usr/bin/lpac
.
lpac
’s output is in json, so run it through jq
to prettify it.
lpac chip info | jq
shows information about the SIM card / eUICC:
(I’ve removed some potentially sensitive/personal bits)
{
"type": "lpa",
"payload": {
"code": 0,
"message": "success",
"data": {
"eidValue": "8904xxxxx",
"EuiccConfiguredAddresses": {
"defaultDpAddress": "smdp-plus-0.eu.cd.rsp.kigen.com",
"rootDsAddress": "lpa.ds.gsma.com"
},
"EUICCInfo2": {
"profileVersion": "2.3.1",
"svn": "2.3.0",
"euiccFirmwareVer": "36.17.4",
"extCardResource": {
"installedApplication": 11,
"freeNonVolatileMemory": 1528320,
"freeVolatileMemory": 32739
},
"uiccCapability": [
"usimSupport",
"isimSupport",
"csimSupport",
"akaMilenage",
"akaCave",
"akaTuak128",
"akaTuak256",
"gbaAuthenUsim",
"gbaAuthenISim",
"eapClient",
"javacard",
"multipleUsimSupport",
"multipleIsimSupport",
"multipleCsimSupport"
],
"ts102241Version": "15.1.0",
"globalplatformVersion": "2.3.0",
"rspCapability": [
"additionalProfile",
"testProfileSupport"
],
"euiccCiPKIdListForVerification": [
"8137xxxxx"
],
"euiccCiPKIdListForSigning": [
"8137xxxxx"
],
"euiccCategory": null,
"ppVersion": "1.0.0",
"sasAcreditationNumber": "KN-DN-UP-0924",
"certificationDataObject": {
"platformLabel": null,
"discoveryBaseURL": null
}
},
"rulesAuthorisationTable": [
{
"pprIds": [
"ppr1",
"ppr2"
],
"allowedOperators": [
{
"plmn": "eeeeee",
"gid1": null,
"gid2": null
}
],
"pprFlags": []
}
]
}
}
}
It appears to use a platform run by Kigen for remote SIM provisioning, so it looks like there is a dependency on a third party’s infrastructure to make all this work.
Use lpac profile list | jq
to list the downloaded SIMs, and see their ICCID and AID.
To enable / disable downloaded eSIMs, use lpac profile {enable,disable} ICCID/AID | jq
.
Using this test profile, I tried adding/downloading SIMs via lpac
.
Specifying the SM-DP+ address (-s
) and the matching ID (-m
) worked:
lpac profile download -s rsp.truphone.com -m QRF-SPEEDTEST`
Specifying the activation code (-a
) in the manner set out in the documentation failed (Edit: quoting issue; see below):
lpac profile download -a LPA:1$rsp.truphone.com$QRF-SPEEDTEST | jq
It returned:
{
"type": "progress",
"payload": {
"code": 0,
"message": "es10b_cancel_session",
"data": null
}
}
{
"type": "progress",
"payload": {
"code": 0,
"message": "es9p_cancel_session",
"data": null
}
}
{
"type": "lpa",
"payload": {
"code": -1,
"message": "activation_code",
"data": "invalid"
}
}
To check this was not just an issue with the test profiles, I bought a 30 day, £2.50 LycaMobile eSIM for testing, so that I could try it with an “actual” eSIM, rather than a test eSIM.
Lyca’s email gave me a QR code, but did not specify (explicitly) the SM-DP+ address or matching ID.
The image’s alt-text was just my order number with Lyca.
I used GNOME’s “Decoder”, which lets one scan a QR card either from the device’s camera or from a screenshot.
That gave me the full activation code, which looked like this:
LPA:1$dp-plus-par07-01.oasis-smartsim.com$XHY48-xxxxx-xxxxx-xxxxx$x.x.x.x.x.x.xxxxx.x.x.x.x
(I don’t know how much of it is sensitive!)
This too failed using lpac
.
I have not dug into why it failed.
I missed the opportunity to test extracting the parameters and pushing them manually into lpac
via -s
and -m
as I had already used EasyLPAC at that point. I suspect that that would have worked.
Update: doh, it is just a matter of quoting the string, with single quotes. So:
lpac profile download -a 'LPA:1$rsp.truphone.com$QRF-BETTERROAMING-PMRDGIR2EARDEIT5'
How embarrassing.
I tried to update the lpac
documentation to make this more obvious, but the maintainer decided that it wasn’t needed. So I guess this blogpost will have to do :)
Thanks to Tom for that :)
Linux GUI: EasyLPAC
There is a GUI for lpac
, called EasyLPAC.
I used the latest Github release, with the version of lpac
that I had already installed.
I did not install it; I just ran it, and it worked.
I tested, on a different machine, the version of EasyLPAC which comes with lpac
included, but I could not get this to work. I did not pursue this.
I was able to download an eSIM using EasyLPAC in a few different ways:
- having an LPA:1 activation code on the system clipboard
- having a QR code image on the system clipboard
- “scanning an image file”, which consisted of opening a QR code saved as an image file on my computer
It was really quite straightforward.
I noted that the instructions say:
Note: Reading LPA activation code and QRCode from clipboard not working in Wayland
But they did work for me, using Wayland.
Importing the LycaMobile eSIM, using the details extracted from the QR code, worked.
Connectivity worked fine via Linux
I put the 9eSIM into my laptop’s SIM slot, and booted it.
In GNOME’s “Mobile Network” settings, it was recognised as a LycaMobile SIM.
I had to set the APN manually.
It took a couple of minutes for the eSIM to activate and, once activated, I was able to browse the Internet.
So there we go: an eSIM on a physical SIM on a laptop running Debian, with very little effort.
Other options
I quite like the look of this Sysmocom SIM.
I’d be interested in giving that a try some point.
You may also like:
- Getting the Sierra Wireless EM7455 LTE modem working in a ThinkPad with Debian 12 Linux (with GPS)
- Editing directories and their contents with vidir from moreutils
- Solving VirtualBox's 'Cannot operate in vmx boot mode' error by changing grub config with Linux kernel 6.12 (Debian)
- Backing up the photos on an iPhone to a computer running Debian Linux using rsync
- Replacing `nautilus-image-converter` with a nautilus bash script
- Setting GNOME's font scaling factor using a bash script
- Initial thoughts on Debian (testing) Linux on a Lenovo ThinkPad X1 Yoga Gen 6
- (Fixed!) I can't get the Bluetooth module of an Intel AX201 card to discover nearby devices using Debian / Linux 6.11.10, and it is bugging me
- Using khal and khard to access appointments and contacts synced from a Nextcloud caldav/cardav server using vdirsyncer
- Using (only) a Linux terminal for my personal computing in 2024
- Tech-related bits and pieces which brought me joy today
- Is now the best time ever for Linux laptops?
- wallabag: a FOSS, self-hosted, read-it-later application
- Setting up my federated fleamarket with flohmarkt
- Tweaking GNOME extensions GSConnect and WinTile-Beyond's metadata to make them work with GNOME 47