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.