diff options
author | Vadim Yanitskiy <fixeria@osmocom.org> | 2023-04-22 20:45:29 +0700 |
---|---|---|
committer | laforge <laforge@osmocom.org> | 2023-05-10 00:14:13 +0000 |
commit | 87dd020d5fbcfadb994d5c808868ee6a0d178fe6 (patch) | |
tree | 8bdda7692f295a91b4831a0ca8ec370b0ce2b1d1 | |
parent | 6b19d802294159589ff0fe44fb74b9c03b92d638 (diff) |
Add very basic profile for R-UIM (CDMA) cards
R-UIM (CDMA) cards are pretty much like the normal GSM SIM cards and
"speak" the same 2G APDU protocol, except that they have their own file
hierarchy under MF(3f00)/DF.CDMA(7f25). They also have DF.TELECOM(7f10)
and even DF.GSM(7f20) with a limited subset of active EFs. The content
of DF.CDMA is specified in 3GPP2 C.S0023-D.
This patch adds a very limited card profile for R-UIM, including auto-
detecion and a few EF definitions under DF.CDMA. This may be useful
for people willing to explore or backup their R-UIMs. To me this was
useful for playing with an R-UIM card from Skylink [1] - a Russian
MNO, which provided 450 MHz CDMA coverage until 2016.
[1] https://en.wikipedia.org/wiki/Sky_Link_(Russia)
Change-Id: Iacdebdbc514d1cd1910d173d81edd28578ec436a
-rwxr-xr-x | pySim-shell.py | 1 | ||||
-rw-r--r-- | pySim/cdma_ruim.py | 193 | ||||
-rw-r--r-- | pySim/profile.py | 19 | ||||
-rw-r--r-- | pySim/ts_51_011.py | 2 |
4 files changed, 210 insertions, 5 deletions
diff --git a/pySim-shell.py b/pySim-shell.py index d09b45a..bf97b6f 100755 --- a/pySim-shell.py +++ b/pySim-shell.py @@ -44,6 +44,7 @@ from pySim.card_handler import CardHandler, CardHandlerAuto from pySim.filesystem import RuntimeState, CardDF, CardADF, CardModel from pySim.profile import CardProfile +from pySim.cdma_ruim import CardProfileRUIM from pySim.ts_102_221 import CardProfileUICC from pySim.ts_102_222 import Ts102222Commands from pySim.ts_31_102 import CardApplicationUSIM diff --git a/pySim/cdma_ruim.py b/pySim/cdma_ruim.py new file mode 100644 index 0000000..3fab558 --- /dev/null +++ b/pySim/cdma_ruim.py @@ -0,0 +1,193 @@ +# coding=utf-8 +"""R-UIM (Removable User Identity Module) card profile (see 3GPP2 C.S0023-D) + +(C) 2023 by Vadim Yanitskiy <fixeria@osmocom.org> + +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 2 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/>. +""" + +import enum + +from pySim.utils import * +from pySim.filesystem import * +from pySim.profile import match_ruim +from pySim.profile import CardProfile +from pySim.ts_51_011 import CardProfileSIM +from pySim.ts_51_011 import DF_TELECOM, DF_GSM +from pySim.ts_51_011 import EF_ServiceTable +from pySim.construct import * +from construct import * + + +# Mapping between CDMA Service Number and its description +EF_CST_map = { + 1 : 'CHV disable function', + 2 : 'Abbreviated Dialing Numbers (ADN)', + 3 : 'Fixed Dialing Numbers (FDN)', + 4 : 'Short Message Storage (SMS)', + 5 : 'HRPD', + 6 : 'Enhanced Phone Book', + 7 : 'Multi Media Domain (MMD)', + 8 : 'SF_EUIMID-based EUIMID', + 9 : 'MEID Support', + 10 : 'Extension1', + 11 : 'Extension2', + 12 : 'SMS Parameters', + 13 : 'Last Number Dialled (LND)', + 14 : 'Service Category Program for BC-SMS', + 15 : 'Messaging and 3GPD Extensions', + 16 : 'Root Certificates', + 17 : 'CDMA Home Service Provider Name', + 18 : 'Service Dialing Numbers (SDN)', + 19 : 'Extension3', + 20 : '3GPD-SIP', + 21 : 'WAP Browser', + 22 : 'Java', + 23 : 'Reserved for CDG', + 24 : 'Reserved for CDG', + 25 : 'Data Download via SMS Broadcast', + 26 : 'Data Download via SMS-PP', + 27 : 'Menu Selection', + 28 : 'Call Control', + 29 : 'Proactive R-UIM', + 30 : 'AKA', + 31 : 'IPv6', + 32 : 'RFU', + 33 : 'RFU', + 34 : 'RFU', + 35 : 'RFU', + 36 : 'RFU', + 37 : 'RFU', + 38 : '3GPD-MIP', + 39 : 'BCMCS', + 40 : 'Multimedia Messaging Service (MMS)', + 41 : 'Extension 8', + 42 : 'MMS User Connectivity Parameters', + 43 : 'Application Authentication', + 44 : 'Group Identifier Level 1', + 45 : 'Group Identifier Level 2', + 46 : 'De-Personalization Control Keys', + 47 : 'Cooperative Network List', +} + + +###################################################################### +# DF.CDMA +###################################################################### + +class EF_SPN(TransparentEF): + '''3.4.31 CDMA Home Service Provider Name''' + + _test_de_encode = [ + ( "010801536b796c696e6b204e57ffffffffffffffffffffffffffffffffffffffffffff", + { 'rfu0' : 0, 'show_in_hsa' : True, 'rfu2' : 0, + 'char_encoding' : 8, 'lang_ind' : 1, 'spn' : 'Skylink NW' } ), + ] + + def __init__(self, fid='6f41', sfid=None, name='EF.SPN', + desc='Service Provider Name', size=(35, 35), **kwargs): + super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs) + self._construct = BitStruct( + # Byte 1: Display Condition + 'rfu1'/BitsRFU(7), + 'show_in_hsa'/Flag, + # Byte 2: Character Encoding + 'rfu2'/BitsRFU(3), + 'char_encoding'/BitsInteger(5), # see C.R1001-G + # Byte 3: Language Indicator + 'lang_ind'/BitsInteger(8), # see C.R1001-G + # Bytes 4-35: Service Provider Name + 'spn'/Bytewise(GsmString(32)) + ) + +class EF_AD(TransparentEF): + '''3.4.33 Administrative Data''' + + _test_de_encode = [ + ( "000000", { 'ms_operation_mode' : 'normal', 'additional_info' : '0000', 'rfu' : '' } ), + ] + + class OP_MODE(enum.IntEnum): + normal = 0x00 + type_approval = 0x80 + normal_and_specific_facilities = 0x01 + type_approval_and_specific_facilities = 0x81 + maintenance_off_line = 0x02 + cell_test = 0x04 + + def __init__(self, fid='6f43', sfid=None, name='EF.AD', + desc='Service Provider Name', size=(3, None), **kwargs): + super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs) + self._construct = Struct( + # Byte 1: Display Condition + 'ms_operation_mode'/Enum(Byte, self.OP_MODE), + # Bytes 2-3: Additional information + 'additional_info'/Bytes(2), + # Bytes 4..: RFU + 'rfu'/GreedyBytesRFU, + ) + + +class EF_SMS(LinFixedEF): + '''3.4.27 Short Messages''' + def __init__(self, fid='6f3c', sfid=None, name='EF.SMS', desc='Short messages', **kwargs): + super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(2, 255), **kwargs) + self._construct = Struct( + # Byte 1: Status + 'status'/BitStruct( + 'rfu87'/BitsRFU(2), + 'protection'/Flag, + 'rfu54'/BitsRFU(2), + 'status'/FlagsEnum(BitsInteger(2), read=0, to_be_read=1, sent=2, to_be_sent=3), + 'used'/Flag, + ), + # Byte 2: Length + 'length'/Int8ub, + # Bytes 3..: SMS Transport Layer Message + 'tpdu'/Bytes(lambda ctx: ctx.length if ctx.status.used else 0), + ) + + +class DF_CDMA(CardDF): + def __init__(self): + super().__init__(fid='7f25', name='DF.CDMA', + desc='CDMA related files (3GPP2 C.S0023-D)') + files = [ + # TODO: lots of other files + EF_ServiceTable('6f32', None, 'EF.CST', + 'CDMA Service Table', table=EF_CST_map, size=(5, 16)), + EF_SPN(), + EF_AD(), + EF_SMS(), + ] + self.add_files(files) + + +class CardProfileRUIM(CardProfile): + '''R-UIM card profile as per 3GPP2 C.S0023-D''' + + ORDER = 2 + + def __init__(self): + super().__init__('R-UIM', desc='CDMA R-UIM Card', cla="a0", + sel_ctrl="0000", files_in_mf=[DF_TELECOM(), DF_GSM(), DF_CDMA()]) + + @staticmethod + def decode_select_response(resp_hex: str) -> object: + # TODO: Response parameters/data in case of DF_CDMA (section 2.6) + return CardProfileSIM.decode_select_response(resp_hex) + + @staticmethod + def match_with_card(scc: SimCardCommands) -> bool: + return match_ruim(scc) diff --git a/pySim/profile.py b/pySim/profile.py index c535bac..e464e1f 100644 --- a/pySim/profile.py +++ b/pySim/profile.py @@ -26,9 +26,12 @@ from pySim.filesystem import CardApplication, interpret_sw from pySim.utils import all_subclasses import abc import operator +from typing import List -def _mf_select_test(scc: SimCardCommands, cla_byte: str, sel_ctrl: str) -> bool: +def _mf_select_test(scc: SimCardCommands, + cla_byte: str, sel_ctrl: str, + fids: List[str]) -> bool: cla_byte_bak = scc.cla_byte sel_ctrl_bak = scc.sel_ctrl scc.reset_card() @@ -37,7 +40,8 @@ def _mf_select_test(scc: SimCardCommands, cla_byte: str, sel_ctrl: str) -> bool: scc.sel_ctrl = sel_ctrl rc = True try: - scc.select_file('3f00') + for fid in fids: + scc.select_file(fid) except: rc = False @@ -51,7 +55,7 @@ def match_uicc(scc: SimCardCommands) -> bool: """ Try to access MF via UICC APDUs (3GPP TS 102.221), if this works, the card is considered a UICC card. """ - return _mf_select_test(scc, "00", "0004") + return _mf_select_test(scc, "00", "0004", ["3f00"]) def match_sim(scc: SimCardCommands) -> bool: @@ -59,7 +63,14 @@ def match_sim(scc: SimCardCommands) -> bool: is also a simcard. This will be the case for most UICC cards, but there may also be plain UICC cards without 2G support as well. """ - return _mf_select_test(scc, "a0", "0000") + return _mf_select_test(scc, "a0", "0000", ["3f00"]) + + +def match_ruim(scc: SimCardCommands) -> bool: + """ Try to access MF/DF.CDMA via 2G APDUs (3GPP TS 11.11), if this works, + the card is considered an R-UIM card for CDMA. + """ + return _mf_select_test(scc, "a0", "0000", ["3f00", "7f25"]) class CardProfile: diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index 222bdaf..e9f0945 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -1200,7 +1200,7 @@ class DF_GSM(CardDF): class CardProfileSIM(CardProfile): - ORDER = 2 + ORDER = 3 def __init__(self): sw = { |