| # 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, CardProfileAddon |
| 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", |
| { 'rfu1' : 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'/HexAdapter(Bytes(2)), |
| # Bytes 4..: RFU |
| 'rfu'/HexAdapter(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) |
| |
| class AddonRUIM(CardProfileAddon): |
| """An Addon that can be found on on a combined SIM + RUIM or UICC + RUIM to support CDMA.""" |
| def __init__(self): |
| files = [ |
| DF_CDMA() |
| ] |
| super().__init__('RUIM', desc='CDMA RUIM', files_in_mf=files) |
| |
| def probe(self, card: 'CardBase') -> bool: |
| return card.file_exists(self.files_in_mf[0].fid) |