CCID driver and Multiple Enabled Profiles (MEP)

Some smartphones can handle 2 SIM cards. The smartphones now use eSIM (embedded SIM) instead of rSIM (removable SIM). It is still useful to have 2 subscriber configurations so the same eSIM should support two (or more) USIM applications.

Specification

From:

RSP Technical Specification
Version 3.0
19th October 2022
https://www.gsma.com/esim/resources/sgp-22-v3-0/

Chapter 2.12 Multiple Enabled Profiles, page 77:

This specification defines optional support of Multiple Enabled (MEP), where several Profiles can be in Enabled state. This enables a Device with more than one baseband to use more than one Profile at the same time for providing connectivity to different networks.

The multiplexing of the APDU streams to those Profiles on a single physical interface is specified in ETSI TS 102 221 (Smart Cards; UICC-Terminal interface; Release 17). This specification uses the term "eSIM Port" for what ETSI TS 102 221 calls a logical SE interface (LSI).

[...]

Several options for different features are defined for MEP:

  • APDU multiplexing can use any of the mechanisms defined in ETSI TS 102 221 [6], e.g.:

    • eSIM Port selection via the APDU MANAGE LSI (select LSI) when the transmission protocol T=0 or T=1 is used.

    • eSIM Port selection via the NAD byte when the transmission protocol T=1 is used.

Implementation

Reda ZAITI, from Thales, implemented the second mechanism: eSIM Port selection via the NAD byte. The original patch is simple: Add possibility to set/get NAD on T=1 for MEP.

This feature can be used to test eSIM chips using a standard smart card reader. The CCID driver must manage the T=1 protocol so only TPDU readers can be used.

The PC/SC workgroup does not define anything regarding MEP. So it was implemented using SCardControl() and the control code SCARD_CTL_CODE(3600).

Sample code

A sample code GetSetNAD.py is provided:

#! /usr/bin/env python3

"""
#   GetSetNAD.py: get/set NAD value
#   Copyright (C) 2022  Ludovic Rousseau
"""

#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, see <http://www.gnu.org/licenses/>.

from smartcard.System import readers
from smartcard.pcsc.PCSCPart10 import SCARD_LEAVE_CARD, SCARD_CTL_CODE
from smartcard import Exceptions
from smartcard.util import toHexString


def get_nad(cardConnection):
    print("Get NAD")

    get_NAD = [0x3F, 0, 0]
    print(" command:", toHexString(get_NAD))
    res = cardConnection.control(SCARD_CTL_CODE(3600), get_NAD)
    print("  result:", toHexString(res))
    status = res[3]
    if status == 0:
        print("Success")
        nad = res[4]
        print("NAD:", nad)
    else:
        print("Failed!")


def set_nad(cardConnection, nad):
    print("Set NAD")

    set_NAD = [0x3E, 0, 1, nad]
    print(" command:", toHexString(set_NAD))
    res = cardConnection.control(SCARD_CTL_CODE(3600), set_NAD)
    print("  result:", toHexString(res))
    status = res[3]
    if status == 0:
        print("Success")
    else:
        print("Failed!")


if __name__ == "__main__":
    import sys

    reader_idx = 0
    if len(sys.argv) > 1:
        reader_idx = int(sys.argv[1])

    reader = readers()[reader_idx]
    print("Reader:", reader)

    cardConnection = reader.createConnection()
    cardConnection.connect(disposition=SCARD_LEAVE_CARD)

    get_nad(cardConnection)
    set_nad(cardConnection, 42)
    get_nad(cardConnection)

Output

 ./GetSetNAD.py 1
Reader: Gemalto PC Twin Reader 01 00
Get NAD
 command: 3F 00 00
  result: 3F 00 02 00 00
Success
NAD: 0
Set NAD
 command: 3E 00 01 2A
  result: 3E 00 01 00
Success
Get NAD
 command: 3F 00 00
  result: 3F 00 02 00 2A
Success
NAD: 42

Here the NAD is changed from the default value 0 to 42.

To enable the feature in the CCID driver you need to define ENABLE_MULTIPLE_ENABLED_PROFILES in the source code and rebuild + reinstall the driver.

It is NOT enabled by default because:

  • very few people will need it

  • it is too easy to create a Denial Of Service using the SCardControl() code and update the NAD value

Example of denial of service

Just after running the GetSetNAD.py program you can try to send an APDU to the smart card:

$ echo "00 00 00 00" | scriptor -r "Gemalto PC Twin Reader 01 00"
Using given card reader: Gemalto PC Twin Reader 01 00
Using T=1 protocol
Reading commands from STDIN
> 00 00 00 00
Can't get info: Transaction failed.

From pcscd logs you get:

00000004 [140363545183936] APDU: 00 00 00 00
00000005 [140363545183936] ../src/ifdhandler.c:1360:IFDHTransmitToICC() usb:08e6/3437:libudev:0:/dev/bus/usb/001/008 (lun: 10000)
00000004 [140363545183936] ../src/commands.c:2289:CmdXfrBlockTPDU_T1() T=1: 4 and 65548 bytes
00000004 [140363545183936] ../src/openct/proto-t1.c:599:t1_build() more bit: 0
00000005 [140363545183936] sending: 2A 40 04 00 00 00 00 6E
00000006 [140363545183936] -> 000001 6F 08 00 00 00 00 20 00 00 00 2A 40 04 00 00 00 00 6E
00002295 [140363545183936] <- 000001 80 04 00 00 00 00 20 00 00 00 00 92 00 92
00000016 [140363545183936] received: 00 92 00 92
00000004 [140363545183936] ../src/openct/proto-t1.c:242:t1_transceive() R-BLOCK required
00000004 [140363545183936] sending: 2A 92 00 B8
00000005 [140363545183936] -> 000001 6F 04 00 00 00 00 21 00 00 00 2A 92 00 B8
00002016 [140363545183936] <- 000001 80 04 00 00 00 00 21 00 00 00 00 92 00 92
00000012 [140363545183936] received: 00 92 00 92
00000004 [140363545183936] ../src/openct/proto-t1.c:242:t1_transceive() R-BLOCK required
00000003 [140363545183936] ../src/openct/proto-t1.c:250:t1_transceive() Rule 7.2
00000002 [140363545183936] sending: 2A 92 00 B8
00000005 [140363545183936] -> 000001 6F 04 00 00 00 00 22 00 00 00 2A 92 00 B8
01555310 [140363545183936] <- 000001 80 00 00 00 00 00 22 40 FE 00
00000020 [140363545183936] ../src/commands.c:1564:CCID_Receive Card absent or mute
00000006 [140363545183936] ../src/openct/proto-t1.c:234:t1_transceive() fatal: transmit/receive failed
00000004 [140363545183936] SW:
00000004 [140363545183936] ../src/ifdwrapper.c:543:IFDTransmit() Card not transacted: 612
00000003 [140363545183936] ../src/winscard.c:1622:SCardTransmit() Card not transacted: rv=SCARD_E_NOT_TRANSACTED
00000003 [140363545183936] ../src/winscard.c:1650:SCardTransmit() UnrefReader() count was: 2
00000005 [140363545183936] ../src/winscard_svc.c:719:ContextThread() TRANSMIT for client 15, rv=SCARD_E_NOT_TRANSACTED

You can see the NAD (node address byte) value (42 or 0x2A) in the first byte of the T=1 block sent by the driver to the reader. My smart card does not like this NAD value (it is not an eSIM with MEP support) and requests an R-Block before becoming mute.

Conclusion

Very few people will use this feature. I guess only developers of eSIM and testers/evaluators of eSIM will need this.

My driver is Free Software and was modified to add the feature. This is the beauty of Free Software.

libccid now uses meson build tool

With the version 1.6.0 of libccid I just released (see New version of libccid: 1.6.0) the recommended tool to configure and build libccid is now meson.

I already explained why I now use meson instead of autoconf/automake in pcsc-lite now uses meson build tool.

Meson for libccid

A typical use case is:

meson setup builddir
cd builddir
meson compile
meson install

If you need/want to disable or enable some libccid options then change the first command to use something like:

meson setup builddir -Dserial=true -Dembedded=true

The available options are (file meson.options):

extra_bundle_id

appended to the name of the bundle directory

class

enable the CCIDCLASSDRIVER in Info.plist

composite-as-multislot

composite device are seen as multi-slots (disabled by default)

embedded

for embedded systems [limit RAM and CPU resources by disabling features (log)] (disabled by default)

os_log

use os_log(3) instead of printf() for debug (Sierra 10.12 and up)] (disabled by default)

pcsclite

use pcsc-lite debug support

serial

build the driver for the serial CCID readers (disabled by default)

zlp

enable the Zero Length Packet patch for some Gemalto readers (disabled by default)

In the case of regression

If you need a special configuration that is not possible using meson it is still possible to generate and run the configure script and build libccid as before:

./bootstrap
./configure your_arguments

You can also create a patch and submit it to https://salsa.debian.org/rousseau/PCSC/ or https://github.com/LudovicRousseau/PCSC.

Conclusion

Meson is a nice tool.

I do not expect regression but since version 1.6.0 is the first release with meson support I may have missed some use cases.

New version of libccid: 1.6.0

I just released version 1.6.0 of libccid the Free Software CCID class smart card reader driver.

Changes:

1.6.0 - 1 June 2024, Ludovic Rousseau

  • Add support of

    • Aladdin R.D. JCR SecurBio

    • AvidCard CAC Smart Card Reader

    • FujitsuTechnologySolutions GmbH Dual Smartcard Reader D321

    • Ledger Stax

    • NXP Pegoda 3

    • authenton #1- CTAP2.1

  • provide files for meson build tool (replaces autoconf/automake)

  • Add possibility to set/get NAD on T=1 for MEP

  • multi-slots readers

    • Better handling of reader removal

    • Use CLOCK_MONOTONIC for timeouts

  • Some other minor improvements

New version of PySCard: 2.0.10

I just released a new version of pyscard. PySCard is a python module adding smart cards support (PC/SC) to Python.

The PySCard project is available at:

Changes:

2.0.10 (June 2024)

  • add 'swig' in pyproject.toml build requires

  • CardMonitoringThread(): do not catch unexpected exceptions

New version of pcsc-lite: 2.2.3

I just released a new version of pcsc-lite 2.2.3.

pcsc-lite is a Free Software implementation of the PC/SC (or WinSCard) API for Unix systems

Changes:

2.2.3: Ludovic Rousseau 26 May 2024

  • meson:

    • Fix build on Slackware 15

    • fail if both libusb and libudev are used

  • Fix memory leak on exit

  • libpcscspy: dump an output buffer only if the call succeeded

  • Some code cleanup

pcsc-lite now uses meson build tool

With the version 2.2.0 of pcsc-lite I just released (see New version of pcsc-lite: 2.2.0) the recommanded tool to configure and build pcsc-lite is now meson.

Problems with autoconf/automake

The change was motivated by the effects of the xz utils backdoor in March 2024.

Meson

Meson (and ninja used by meson) is used by a lot of software, like GNOME libraries and applications. See the list of adopters in the Wikipedia Meson page.

It is also an opportunity to learn new tools.

Meson for pcsc-lite

A typical use case is:

meson setup builddir
cd builddir
meson compile
meson install

If you need/want to disable some pcsc-lite options then change the first command to use something like:

meson setup builddir -Dlibudev=false -Dipcdir=/var/run/pcscd

The available options are (file meson.options):

embedded

for embedded systems [limit RAM and CPU resources by disabling features (log)] (disabled by default)

filter_names

reader filtering using PCSCLITE_FILTER_IGNORE_READER_NAMES and PCSCLITE_FILTER_EXTEND_READER_NAMES environment variables

ipcdir

Direcrory for pcsc-lite internal communication socket (/run/pcscd by default)

libsystemd

Use systemd for daemon auto start

libudev

Use libudev (preferred) for USB hotplug

libusb

Use libusb for USB hotplug (disabled by default)

polkit

Use polkit to enforce access control

serial

Support serial readers (disabled by default)

serialconfdir

Path for serial configuration files (/etc/reader.conf.d by default)

systemdunit

Systemd unit directory to use ("user" by default)

usb

Support USB readers

usbdropdir

Path for USB drivers (/usr/lib/pcsc/drivers by default)

Peformances

Another reason to use meson is that the configuration + compilation times should be much shorter.

Computer I used for the tests: MacBook Pro from 2009, MacBookPro5,3, 4 GB of RAM, CPU Core 2 Duo at 2.66 GHz. I just replaced the hard drive by an SSD and installed Debian GNU/Linux (to replace macOS).

I use an old (15 year-old) computer on purpose. The goal is to be able measure times.

autoconf

  • bootstrap: 18 seconds (48 %)

  • configure: 9.5 seconds (25 %)

  • compile: 10 seconds (26 %)

  • total: 37.5 seconds

meson

  • configure: 2 seconds (22 %)

  • compile: 7 seconds (77 %)

  • total : 9 seconds

Speed up: x4.1

Here, a lot of time is used to generate the configure script (in the autoconf case) and run it. If you have a lot more files to compile in your project the speed up may be lower for you. I guess meson should always be faster than autoconf/automake.

Drop unused features

The move to meson is also an occasion to do some cleanup in the code and features supported by pcsc-lite.

Serial readers

I have not removed anything, but the support of serial readers is not enabled by default. I think I have not had a computer with a serial port since at least 10 years.

In case you need it, you can enable it using:

meson setup builddir -Dserial=true

Vintage Unix systems

pcsc-lite has special code for HPUX, OSF, AIX, Solaris and SunOS4. I guess nobody is using these systems anymore.

In the case of regression

If you need a special configuration that is not possible using meson it is still possible to generate and run the configure script and build pcsc-lite as before:

./bootstrap
./configure your_arguments

You can also create a patch and submit it to https://salsa.debian.org/rousseau/PCSC/ or https://github.com/LudovicRousseau/PCSC.

I already fixed Meson issues. So be sure to use the current master branch of the pcsc-lite git repository.

Conclusion

It is funny to note that we have now much faster computers than 20 years ago when the pcsc-lite project was started. But faster tools are developed now to replace the slower ones. How could we be happy to use slower tools on our slower computers?

The erooM principle is a nice idea. I hope to see more examples.

[UPDATE May 2024]

pcsc-lite version 2.2.1 added the meson option filter_names.