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:

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:

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.