blob: 18138a0ec8d08f2ad4a6927388be1836ae470699 [file] [log] [blame]
Alexander Chemeris067f69c2017-07-18 16:44:26 +03001# -*- coding: utf-8 -*-
2
Harald Welte14105dc2021-05-31 08:48:51 +02003# without this, pylint will fail when inner classes are used
4# within the 'nested' kwarg of our TlvMeta metaclass on python 3.7 :(
5# pylint: disable=undefined-variable
6
Harald Welteb2edd142021-01-08 23:29:35 +01007""" Various constants from ETSI TS 151.011 +
8Representation of the GSM SIM/USIM/ISIM filesystem hierarchy.
9
10The File (and its derived classes) uses the classes of pySim.filesystem in
11order to describe the files specified in the relevant ETSI + 3GPP specifications.
Alexander Chemeris067f69c2017-07-18 16:44:26 +030012"""
13
14#
15# Copyright (C) 2017 Alexander.Chemeris <Alexander.Chemeris@gmail.com>
Harald Welteb2edd142021-01-08 23:29:35 +010016# Copyright (C) 2021 Harald Welte <laforge@osmocom.org>
Alexander Chemeris067f69c2017-07-18 16:44:26 +030017#
18# This program is free software: you can redistribute it and/or modify
19# it under the terms of the GNU General Public License as published by
20# the Free Software Foundation, either version 2 of the License, or
21# (at your option) any later version.
22#
23# This program is distributed in the hope that it will be useful,
24# but WITHOUT ANY WARRANTY; without even the implied warranty of
25# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26# GNU General Public License for more details.
27#
28# You should have received a copy of the GNU General Public License
29# along with this program. If not, see <http://www.gnu.org/licenses/>.
30#
31
Harald Weltec91085e2022-02-10 18:05:45 +010032from pySim.profile import match_sim
33from pySim.profile import CardProfile
34from pySim.filesystem import *
Harald Welte228ae8e2022-07-17 22:01:04 +020035from pySim.ts_31_102_telecom import DF_PHONEBOOK, DF_MULTIMEDIA, DF_MCS, DF_V2X
Harald Weltec91085e2022-02-10 18:05:45 +010036import enum
37from pySim.construct import *
38from construct import Optional as COptional
39from construct import *
40from struct import pack, unpack
41from typing import Tuple
42from pySim.tlv import *
43from pySim.utils import *
Alexander Chemeris067f69c2017-07-18 16:44:26 +030044MF_num = '3F00'
45
46DF_num = {
Harald Weltec91085e2022-02-10 18:05:45 +010047 'TELECOM': '7F10',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030048
Harald Weltec91085e2022-02-10 18:05:45 +010049 'GSM': '7F20',
50 'IS-41': '7F22',
51 'FP-CTS': '7F23',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030052
Harald Weltec91085e2022-02-10 18:05:45 +010053 'GRAPHICS': '5F50',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030054
Harald Weltec91085e2022-02-10 18:05:45 +010055 'IRIDIUM': '5F30',
56 'GLOBST': '5F31',
57 'ICO': '5F32',
58 'ACeS': '5F33',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030059
Harald Weltec91085e2022-02-10 18:05:45 +010060 'EIA/TIA-553': '5F40',
61 'CTS': '5F60',
62 'SOLSA': '5F70',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030063
Harald Weltec91085e2022-02-10 18:05:45 +010064 'MExE': '5F3C',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030065}
66
67EF_num = {
Harald Weltec91085e2022-02-10 18:05:45 +010068 # MF
69 'ICCID': '2FE2',
70 'ELP': '2F05',
71 'DIR': '2F00',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030072
Harald Weltec91085e2022-02-10 18:05:45 +010073 # DF_TELECOM
74 'ADN': '6F3A',
75 'FDN': '6F3B',
76 'SMS': '6F3C',
77 'CCP': '6F3D',
78 'MSISDN': '6F40',
79 'SMSP': '6F42',
80 'SMSS': '6F43',
81 'LND': '6F44',
82 'SMSR': '6F47',
83 'SDN': '6F49',
84 'EXT1': '6F4A',
85 'EXT2': '6F4B',
86 'EXT3': '6F4C',
87 'BDN': '6F4D',
88 'EXT4': '6F4E',
89 'CMI': '6F58',
90 'ECCP': '6F4F',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030091
Harald Weltec91085e2022-02-10 18:05:45 +010092 # DF_GRAPHICS
93 'IMG': '4F20',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030094
Harald Weltec91085e2022-02-10 18:05:45 +010095 # DF_SoLSA
96 'SAI': '4F30',
97 'SLL': '4F31',
Alexander Chemeris067f69c2017-07-18 16:44:26 +030098
Harald Weltec91085e2022-02-10 18:05:45 +010099 # DF_MExE
100 'MExE-ST': '4F40',
101 'ORPK': '4F41',
102 'ARPK': '4F42',
103 'TPRPK': '4F43',
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300104
Harald Weltec91085e2022-02-10 18:05:45 +0100105 # DF_GSM
106 'LP': '6F05',
107 'IMSI': '6F07',
108 'Kc': '6F20',
109 'DCK': '6F2C',
110 'PLMNsel': '6F30',
111 'HPPLMN': '6F31',
112 'CNL': '6F32',
113 'ACMmax': '6F37',
114 'SST': '6F38',
115 'ACM': '6F39',
116 'GID1': '6F3E',
117 'GID2': '6F3F',
118 'PUCT': '6F41',
119 'CBMI': '6F45',
120 'SPN': '6F46',
121 'CBMID': '6F48',
122 'BCCH': '6F74',
123 'ACC': '6F78',
124 'FPLMN': '6F7B',
125 'LOCI': '6F7E',
126 'AD': '6FAD',
127 'PHASE': '6FAE',
128 'VGCS': '6FB1',
129 'VGCSS': '6FB2',
130 'VBS': '6FB3',
131 'VBSS': '6FB4',
132 'eMLPP': '6FB5',
133 'AAeM': '6FB6',
134 'ECC': '6FB7',
135 'CBMIR': '6F50',
136 'NIA': '6F51',
137 'KcGPRS': '6F52',
138 'LOCIGPRS': '6F53',
139 'SUME': '6F54',
140 'PLMNwAcT': '6F60',
141 'OPLMNwAcT': '6F61',
142 # Figure 8 names it HPLMNAcT, but in the text it's names it HPLMNwAcT
143 'HPLMNAcT': '6F62',
144 'HPLMNwAcT': '6F62',
145 'CPBCCH': '6F63',
146 'INVSCAN': '6F64',
147 'PNN': '6FC5',
148 'OPL': '6FC6',
149 'MBDN': '6FC7',
150 'EXT6': '6FC8',
151 'MBI': '6FC9',
152 'MWIS': '6FCA',
153 'CFIS': '6FCB',
154 'EXT7': '6FCC',
155 'SPDI': '6FCD',
156 'MMSN': '6FCE',
157 'EXT8': '6FCF',
158 'MMSICP': '6FD0',
159 'MMSUP': '6FD1',
160 'MMSUCP': '6FD2',
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300161}
162
163DF = {
Harald Weltec91085e2022-02-10 18:05:45 +0100164 'TELECOM': [MF_num, DF_num['TELECOM']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300165
Harald Weltec91085e2022-02-10 18:05:45 +0100166 'GSM': [MF_num, DF_num['GSM']],
167 'IS-41': [MF_num, DF_num['IS-41']],
168 'FP-CTS': [MF_num, DF_num['FP-CTS']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300169
Harald Weltec91085e2022-02-10 18:05:45 +0100170 'GRAPHICS': [MF_num, DF_num['GRAPHICS']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300171
Harald Weltec91085e2022-02-10 18:05:45 +0100172 'IRIDIUM': [MF_num, DF_num['IRIDIUM']],
173 'GLOBST': [MF_num, DF_num['GLOBST']],
174 'ICO': [MF_num, DF_num['ICO']],
175 'ACeS': [MF_num, DF_num['ACeS']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300176
Harald Weltec91085e2022-02-10 18:05:45 +0100177 'EIA/TIA-553': [MF_num, DF_num['EIA/TIA-553']],
178 'CTS': [MF_num, DF_num['CTS']],
179 'SoLSA': [MF_num, DF_num['SOLSA']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300180
Harald Weltec91085e2022-02-10 18:05:45 +0100181 'MExE': [MF_num, DF_num['MExE']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300182}
183
184
185EF = {
Harald Weltec91085e2022-02-10 18:05:45 +0100186 'ICCID': [MF_num, EF_num['ICCID']],
187 'ELP': [MF_num, EF_num['ELP']],
188 'DIR': [MF_num, EF_num['DIR']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300189
Harald Weltec91085e2022-02-10 18:05:45 +0100190 'ADN': DF['TELECOM']+[EF_num['ADN']],
191 'FDN': DF['TELECOM']+[EF_num['FDN']],
192 'SMS': DF['TELECOM']+[EF_num['SMS']],
193 'CCP': DF['TELECOM']+[EF_num['CCP']],
194 'MSISDN': DF['TELECOM']+[EF_num['MSISDN']],
195 'SMSP': DF['TELECOM']+[EF_num['SMSP']],
196 'SMSS': DF['TELECOM']+[EF_num['SMSS']],
197 'LND': DF['TELECOM']+[EF_num['LND']],
198 'SMSR': DF['TELECOM']+[EF_num['SMSR']],
199 'SDN': DF['TELECOM']+[EF_num['SDN']],
200 'EXT1': DF['TELECOM']+[EF_num['EXT1']],
201 'EXT2': DF['TELECOM']+[EF_num['EXT2']],
202 'EXT3': DF['TELECOM']+[EF_num['EXT3']],
203 'BDN': DF['TELECOM']+[EF_num['BDN']],
204 'EXT4': DF['TELECOM']+[EF_num['EXT4']],
205 'CMI': DF['TELECOM']+[EF_num['CMI']],
206 'ECCP': DF['TELECOM']+[EF_num['ECCP']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300207
Harald Weltec91085e2022-02-10 18:05:45 +0100208 'IMG': DF['GRAPHICS']+[EF_num['IMG']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300209
Harald Weltec91085e2022-02-10 18:05:45 +0100210 'SAI': DF['SoLSA']+[EF_num['SAI']],
211 'SLL': DF['SoLSA']+[EF_num['SLL']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300212
Harald Weltec91085e2022-02-10 18:05:45 +0100213 'MExE-ST': DF['MExE']+[EF_num['MExE-ST']],
214 'ORPK': DF['MExE']+[EF_num['ORPK']],
215 'ARPK': DF['MExE']+[EF_num['ARPK']],
216 'TPRPK': DF['MExE']+[EF_num['TPRPK']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300217
Harald Weltec91085e2022-02-10 18:05:45 +0100218 'LP': DF['GSM']+[EF_num['LP']],
219 'IMSI': DF['GSM']+[EF_num['IMSI']],
220 'Kc': DF['GSM']+[EF_num['Kc']],
221 'DCK': DF['GSM']+[EF_num['DCK']],
222 'PLMNsel': DF['GSM']+[EF_num['PLMNsel']],
223 'HPPLMN': DF['GSM']+[EF_num['HPPLMN']],
224 'CNL': DF['GSM']+[EF_num['CNL']],
225 'ACMmax': DF['GSM']+[EF_num['ACMmax']],
226 'SST': DF['GSM']+[EF_num['SST']],
227 'ACM': DF['GSM']+[EF_num['ACM']],
228 'GID1': DF['GSM']+[EF_num['GID1']],
229 'GID2': DF['GSM']+[EF_num['GID2']],
230 'PUCT': DF['GSM']+[EF_num['PUCT']],
231 'CBMI': DF['GSM']+[EF_num['CBMI']],
232 'SPN': DF['GSM']+[EF_num['SPN']],
233 'CBMID': DF['GSM']+[EF_num['CBMID']],
234 'BCCH': DF['GSM']+[EF_num['BCCH']],
235 'ACC': DF['GSM']+[EF_num['ACC']],
236 'FPLMN': DF['GSM']+[EF_num['FPLMN']],
237 'LOCI': DF['GSM']+[EF_num['LOCI']],
238 'AD': DF['GSM']+[EF_num['AD']],
239 'PHASE': DF['GSM']+[EF_num['PHASE']],
240 'VGCS': DF['GSM']+[EF_num['VGCS']],
241 'VGCSS': DF['GSM']+[EF_num['VGCSS']],
242 'VBS': DF['GSM']+[EF_num['VBS']],
243 'VBSS': DF['GSM']+[EF_num['VBSS']],
244 'eMLPP': DF['GSM']+[EF_num['eMLPP']],
245 'AAeM': DF['GSM']+[EF_num['AAeM']],
246 'ECC': DF['GSM']+[EF_num['ECC']],
247 'CBMIR': DF['GSM']+[EF_num['CBMIR']],
248 'NIA': DF['GSM']+[EF_num['NIA']],
249 'KcGPRS': DF['GSM']+[EF_num['KcGPRS']],
250 'LOCIGPRS': DF['GSM']+[EF_num['LOCIGPRS']],
251 'SUME': DF['GSM']+[EF_num['SUME']],
252 'PLMNwAcT': DF['GSM']+[EF_num['PLMNwAcT']],
253 'OPLMNwAcT': DF['GSM']+[EF_num['OPLMNwAcT']],
254 # Figure 8 names it HPLMNAcT, but in the text it's names it HPLMNwAcT
255 'HPLMNAcT': DF['GSM']+[EF_num['HPLMNAcT']],
256 'HPLMNwAcT': DF['GSM']+[EF_num['HPLMNAcT']],
257 'CPBCCH': DF['GSM']+[EF_num['CPBCCH']],
258 'INVSCAN': DF['GSM']+[EF_num['INVSCAN']],
259 'PNN': DF['GSM']+[EF_num['PNN']],
260 'OPL': DF['GSM']+[EF_num['OPL']],
261 'MBDN': DF['GSM']+[EF_num['MBDN']],
262 'EXT6': DF['GSM']+[EF_num['EXT6']],
263 'MBI': DF['GSM']+[EF_num['MBI']],
264 'MWIS': DF['GSM']+[EF_num['MWIS']],
265 'CFIS': DF['GSM']+[EF_num['CFIS']],
266 'EXT7': DF['GSM']+[EF_num['EXT7']],
267 'SPDI': DF['GSM']+[EF_num['SPDI']],
268 'MMSN': DF['GSM']+[EF_num['MMSN']],
269 'EXT8': DF['GSM']+[EF_num['EXT8']],
270 'MMSICP': DF['GSM']+[EF_num['MMSICP']],
271 'MMSUP': DF['GSM']+[EF_num['MMSUP']],
272 'MMSUCP': DF['GSM']+[EF_num['MMSUCP']],
Alexander Chemeris067f69c2017-07-18 16:44:26 +0300273}
Supreeth Herlebf5d6022020-03-20 15:18:27 +0100274
275# Mapping between SIM Service Number and its description
276EF_SST_map = {
Harald Weltec91085e2022-02-10 18:05:45 +0100277 1: 'CHV1 disable function',
278 2: 'Abbreviated Dialling Numbers (ADN)',
279 3: 'Fixed Dialling Numbers (FDN)',
280 4: 'Short Message Storage (SMS)',
281 5: 'Advice of Charge (AoC)',
282 6: 'Capability Configuration Parameters (CCP)',
283 7: 'PLMN selector',
284 8: 'RFU',
285 9: 'MSISDN',
286 10: 'Extension1',
287 11: 'Extension2',
288 12: 'SMS Parameters',
289 13: 'Last Number Dialled (LND)',
290 14: 'Cell Broadcast Message Identifier',
291 15: 'Group Identifier Level 1',
292 16: 'Group Identifier Level 2',
293 17: 'Service Provider Name',
294 18: 'Service Dialling Numbers (SDN)',
295 19: 'Extension3',
296 20: 'RFU',
297 21: 'VGCS Group Identifier List (EFVGCS and EFVGCSS)',
298 22: 'VBS Group Identifier List (EFVBS and EFVBSS)',
299 23: 'enhanced Multi-Level Precedence and Pre-emption Service',
300 24: 'Automatic Answer for eMLPP',
301 25: 'Data download via SMS-CB',
302 26: 'Data download via SMS-PP',
303 27: 'Menu selection',
304 28: 'Call control',
305 29: 'Proactive SIM',
306 30: 'Cell Broadcast Message Identifier Ranges',
307 31: 'Barred Dialling Numbers (BDN)',
308 32: 'Extension4',
309 33: 'De-personalization Control Keys',
310 34: 'Co-operative Network List',
311 35: 'Short Message Status Reports',
312 36: 'Network\'s indication of alerting in the MS',
313 37: 'Mobile Originated Short Message control by SIM',
314 38: 'GPRS',
315 39: 'Image (IMG)',
316 40: 'SoLSA (Support of Local Service Area)',
317 41: 'USSD string data object supported in Call Control',
318 42: 'RUN AT COMMAND command',
319 43: 'User controlled PLMN Selector with Access Technology',
320 44: 'Operator controlled PLMN Selector with Access Technology',
321 45: 'HPLMN Selector with Access Technology',
322 46: 'CPBCCH Information',
323 47: 'Investigation Scan',
324 48: 'Extended Capability Configuration Parameters',
325 49: 'MExE',
326 50: 'Reserved and shall be ignored',
327 51: 'PLMN Network Name',
328 52: 'Operator PLMN List',
329 53: 'Mailbox Dialling Numbers',
330 54: 'Message Waiting Indication Status',
331 55: 'Call Forwarding Indication Status',
332 56: 'Service Provider Display Information',
333 57: 'Multimedia Messaging Service (MMS)',
334 58: 'Extension 8',
335 59: 'MMS User Connectivity Parameters',
Vadim Yanitskiydfe3dbb2020-07-28 05:26:02 +0700336}
337
Harald Welteb2edd142021-01-08 23:29:35 +0100338
339######################################################################
340# DF.TELECOM
341######################################################################
342
Harald Weltef11f1302023-01-24 17:59:59 +0100343
344# TS 51.011 Section 10.5.1 / Table 12
345class ExtendedBcdAdapter(Adapter):
346 """Replace some hex-characters with other ASCII characters"""
347 # we only translate a=* / b=# as they habe a clear representation
348 # in terms of USSD / SS service codes
349 def _decode(self, obj, context, path):
350 if not isinstance(obj, str):
351 return obj
352 return obj.lower().replace("a","*").replace("b","#")
353
354 def _encode(self, obj, context, path):
355 if not isinstance(obj, str):
356 return obj
357 return obj.replace("*","a").replace("#","b")
358
Harald Welteb2edd142021-01-08 23:29:35 +0100359# TS 51.011 Section 10.5.1
360class EF_ADN(LinFixedEF):
Harald Welte0dc6c202023-01-24 18:10:13 +0100361 def __init__(self, fid='6f3a', sfid=None, name='EF.ADN', desc='Abbreviated Dialing Numbers', ext=1, **kwargs):
Harald Welte99e4cc02022-07-21 15:25:47 +0200362 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(14, 30), **kwargs)
Harald Welte0dc6c202023-01-24 18:10:13 +0100363 ext_name = 'ext%u_record_id' % ext
Harald Welte1e73d222022-02-13 11:32:50 +0100364 self._construct = Struct('alpha_id'/COptional(GsmStringAdapter(Rpad(Bytes(this._.total_len-14)), codec='ascii')),
365 'len_of_bcd'/Int8ub,
366 'ton_npi'/TonNpi,
Harald Weltef11f1302023-01-24 17:59:59 +0100367 'dialing_nr'/ExtendedBcdAdapter(BcdAdapter(Rpad(Bytes(10)))),
Harald Welte1e73d222022-02-13 11:32:50 +0100368 'cap_conf_id'/Int8ub,
Harald Welte0dc6c202023-01-24 18:10:13 +0100369 ext_name/Int8ub)
Harald Welteb2edd142021-01-08 23:29:35 +0100370
371# TS 51.011 Section 10.5.5
Harald Welteec7d0da2021-04-02 22:01:19 +0200372class EF_SMS(LinFixedEF):
Harald Welte6169c722022-02-12 09:05:15 +0100373 def __init__(self, fid='6f3c', sfid=None, name='EF.SMS', desc='Short messages', **kwargs):
Harald Welte99e4cc02022-07-21 15:25:47 +0200374 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(176, 176), **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100375
Harald Weltef6b37af2023-01-24 15:42:26 +0100376 def _decode_record_bin(self, raw_bin_data, **kwargs):
Harald Welteec7d0da2021-04-02 22:01:19 +0200377 def decode_status(status):
378 if status & 0x01 == 0x00:
379 return (None, 'free_space')
380 elif status & 0x07 == 0x01:
381 return ('mt', 'message_read')
382 elif status & 0x07 == 0x03:
383 return ('mt', 'message_to_be_read')
384 elif status & 0x07 == 0x07:
385 return ('mo', 'message_to_be_sent')
386 elif status & 0x1f == 0x05:
387 return ('mo', 'sent_status_not_requested')
388 elif status & 0x1f == 0x0d:
389 return ('mo', 'sent_status_req_but_not_received')
390 elif status & 0x1f == 0x15:
391 return ('mo', 'sent_status_req_rx_not_stored_smsr')
392 elif status & 0x1f == 0x1d:
393 return ('mo', 'sent_status_req_rx_stored_smsr')
394 else:
395 return (None, 'rfu')
396
397 status = decode_status(raw_bin_data[0])
398 remainder = raw_bin_data[1:]
399 return {'direction': status[0], 'status': status[1], 'remainder': b2h(remainder)}
400
401
402# TS 51.011 Section 10.5.5
Harald Welteb2edd142021-01-08 23:29:35 +0100403class EF_MSISDN(LinFixedEF):
Harald Welte6169c722022-02-12 09:05:15 +0100404 def __init__(self, fid='6f40', sfid=None, name='EF.MSISDN', desc='MSISDN', **kwargs):
Harald Welte99e4cc02022-07-21 15:25:47 +0200405 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(15, 34), **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100406
Harald Weltef6b37af2023-01-24 15:42:26 +0100407 def _decode_record_hex(self, raw_hex_data, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100408 return {'msisdn': dec_msisdn(raw_hex_data)}
Harald Weltec91085e2022-02-10 18:05:45 +0100409
Harald Weltef6b37af2023-01-24 15:42:26 +0100410 def _encode_record_hex(self, abstract, **kwargs):
Philipp Maierf9cbe092021-04-23 19:37:36 +0200411 msisdn = abstract['msisdn']
412 if type(msisdn) == str:
413 encoded_msisdn = enc_msisdn(msisdn)
414 else:
Harald Weltec91085e2022-02-10 18:05:45 +0100415 encoded_msisdn = enc_msisdn(msisdn[2], msisdn[0], msisdn[1])
416 alpha_identifier = (list(self.rec_len)[
417 0] - len(encoded_msisdn) // 2) * "ff"
Philipp Maierb46cb3f2021-04-20 22:38:21 +0200418 return alpha_identifier + encoded_msisdn
Harald Welteb2edd142021-01-08 23:29:35 +0100419
420# TS 51.011 Section 10.5.6
421class EF_SMSP(LinFixedEF):
Harald Weltebc0e2092022-02-13 10:54:58 +0100422 class ValidityPeriodAdapter(Adapter):
423 def _decode(self, obj, context, path):
424 if obj <= 143:
425 return obj + 1 * 5
426 elif obj <= 167:
427 return 12 * 60 + ((obj - 143) * 30)
428 elif obj <= 196:
429 return (obj - 166) * (24 * 60)
430 elif obj <= 255:
431 return (obj - 192) * (7 * 24 * 60)
432 else:
433 raise ValueError
434 def _encode(self, obj, context, path):
435 if obj <= 12*60:
436 return obj/5 - 1
437 elif obj <= 24*60:
438 return 143 + ((obj - (12 * 60)) / 30)
439 elif obj <= 30 * 24 * 60:
440 return 166 + (obj / (24 * 60))
441 elif obj <= 63 * 7 * 24 * 60:
442 return 192 + (obj / (7 * 24 * 60))
443 else:
444 raise ValueError
445
Harald Welte6169c722022-02-12 09:05:15 +0100446 def __init__(self, fid='6f42', sfid=None, name='EF.SMSP', desc='Short message service parameters', **kwargs):
Harald Welte99e4cc02022-07-21 15:25:47 +0200447 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(28, None), **kwargs)
Harald Weltebc0e2092022-02-13 10:54:58 +0100448 ScAddr = Struct('length'/Int8ub, 'ton_npi'/TonNpi, 'call_number'/BcdAdapter(Rpad(Bytes(10))))
449 self._construct = Struct('alpha_id'/COptional(GsmStringAdapter(Rpad(Bytes(this._.total_len-28)))),
450 'parameter_indicators'/InvertAdapter(FlagsEnum(Byte, tp_dest_addr=1, tp_sc_addr=2,
451 tp_pid=3, tp_dcs=4, tp_vp=5)),
452 'tp_dest_addr'/ScAddr,
453 'tp_sc_addr'/ScAddr,
454
455 'tp_pid'/HexAdapter(Bytes(1)),
456 'tp_dcs'/HexAdapter(Bytes(1)),
457 'tp_vp_minutes'/EF_SMSP.ValidityPeriodAdapter(Byte))
Harald Welteb2edd142021-01-08 23:29:35 +0100458
Harald Welte790b2702021-04-11 00:01:35 +0200459# TS 51.011 Section 10.5.7
460class EF_SMSS(TransparentEF):
461 class MemCapAdapter(Adapter):
462 def _decode(self, obj, context, path):
463 return False if obj & 1 else True
Harald Weltec91085e2022-02-10 18:05:45 +0100464
Harald Welte790b2702021-04-11 00:01:35 +0200465 def _encode(self, obj, context, path):
466 return 0 if obj else 1
Harald Weltec91085e2022-02-10 18:05:45 +0100467
Harald Welte13edf302022-07-21 15:19:23 +0200468 def __init__(self, fid='6f43', sfid=None, name='EF.SMSS', desc='SMS status', size=(2, 8), **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100469 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100470 self._construct = Struct(
471 'last_used_tpmr'/Int8ub, 'memory_capacity_exceeded'/self.MemCapAdapter(Int8ub))
Harald Welte790b2702021-04-11 00:01:35 +0200472
473# TS 51.011 Section 10.5.8
474class EF_SMSR(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200475 def __init__(self, fid='6f47', sfid=None, name='EF.SMSR', desc='SMS status reports', rec_len=(30, 30), **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100476 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100477 self._construct = Struct(
478 'sms_record_id'/Int8ub, 'sms_status_report'/HexAdapter(Bytes(29)))
479
Harald Welte790b2702021-04-11 00:01:35 +0200480
481class EF_EXT(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200482 def __init__(self, fid, sfid=None, name='EF.EXT', desc='Extension', rec_len=(13, 13), **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100483 super().__init__(fid=fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100484 self._construct = Struct(
485 'record_type'/Int8ub, 'extension_data'/HexAdapter(Bytes(11)), 'identifier'/Int8ub)
Harald Welte790b2702021-04-11 00:01:35 +0200486
487# TS 51.011 Section 10.5.16
488class EF_CMI(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200489 def __init__(self, fid='6f58', sfid=None, name='EF.CMI', rec_len=(2, 21),
Harald Welte6169c722022-02-12 09:05:15 +0100490 desc='Comparison Method Information', **kwargs):
491 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100492 self._construct = Struct(
Harald Welte540adb02022-02-13 11:33:21 +0100493 'alpha_id'/GsmStringAdapter(Rpad(Bytes(this._.total_len-1))), 'comparison_method_id'/Int8ub)
Harald Weltec91085e2022-02-10 18:05:45 +0100494
Harald Welte790b2702021-04-11 00:01:35 +0200495
Harald Welteb2edd142021-01-08 23:29:35 +0100496class DF_TELECOM(CardDF):
Harald Welte6169c722022-02-12 09:05:15 +0100497 def __init__(self, fid='7f10', name='DF.TELECOM', desc=None, **kwargs):
498 super().__init__(fid=fid, name=name, desc=desc, **kwargs)
Harald Welteb2edd142021-01-08 23:29:35 +0100499 files = [
Harald Weltec91085e2022-02-10 18:05:45 +0100500 EF_ADN(),
Harald Welte0dc6c202023-01-24 18:10:13 +0100501 EF_ADN(fid='6f3b', name='EF.FDN', desc='Fixed dialling numbers', ext=2),
Harald Weltec91085e2022-02-10 18:05:45 +0100502 EF_SMS(),
503 LinFixedEF(fid='6f3d', name='EF.CCP',
Harald Welte99e4cc02022-07-21 15:25:47 +0200504 desc='Capability Configuration Parameters', rec_len=(14, 14)),
Harald Weltec91085e2022-02-10 18:05:45 +0100505 LinFixedEF(fid='6f4f', name='EF.ECCP',
Harald Welte99e4cc02022-07-21 15:25:47 +0200506 desc='Extended Capability Configuration Parameters', rec_len=(15, 32)),
Harald Weltec91085e2022-02-10 18:05:45 +0100507 EF_MSISDN(),
508 EF_SMSP(),
509 EF_SMSS(),
Harald Weltea1bb3f72023-01-24 18:15:56 +0100510 EF_ADN('6f44', None, 'EF.LND', 'Last Number Dialled', ext=1),
Harald Welte0dc6c202023-01-24 18:10:13 +0100511 EF_ADN('6f49', None, 'EF.SDN', 'Service Dialling Numbers', ext=3),
Harald Weltec91085e2022-02-10 18:05:45 +0100512 EF_EXT('6f4a', None, 'EF.EXT1', 'Extension1 (ADN/SSC)'),
513 EF_EXT('6f4b', None, 'EF.EXT2', 'Extension2 (FDN/SSC)'),
514 EF_EXT('6f4c', None, 'EF.EXT3', 'Extension3 (SDN)'),
515 EF_ADN(fid='6f4d', name='EF.BDN', desc='Barred Dialling Numbers'),
516 EF_EXT('6f4e', None, 'EF.EXT4', 'Extension4 (BDN/SSC)'),
517 EF_SMSR(),
518 EF_CMI(),
Harald Weltede4c14c2022-07-16 11:53:59 +0200519 # not really part of 51.011 but something that TS 31.102 specifies may exist here.
520 DF_PHONEBOOK(),
Harald Weltea0452212022-07-17 21:23:21 +0200521 DF_MULTIMEDIA(),
Harald Welte650f6122022-07-17 21:42:50 +0200522 DF_MCS(),
Harald Welte228ae8e2022-07-17 22:01:04 +0200523 DF_V2X(),
Harald Weltec91085e2022-02-10 18:05:45 +0100524 ]
Harald Welteb2edd142021-01-08 23:29:35 +0100525 self.add_files(files)
526
Harald Welteb2edd142021-01-08 23:29:35 +0100527######################################################################
528# DF.GSM
529######################################################################
530
531# TS 51.011 Section 10.3.1
532class EF_LP(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200533 def __init__(self, fid='6f05', sfid=None, name='EF.LP', size=(1, None), rec_len=1,
Harald Welteb2edd142021-01-08 23:29:35 +0100534 desc='Language Preference'):
535 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len)
Harald Weltec91085e2022-02-10 18:05:45 +0100536
Harald Weltef6b37af2023-01-24 15:42:26 +0100537 def _decode_record_bin(self, in_bin, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100538 return b2h(in_bin)
Harald Weltec91085e2022-02-10 18:05:45 +0100539
Harald Weltef6b37af2023-01-24 15:42:26 +0100540 def _encode_record_bin(self, in_json, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100541 return h2b(in_json)
542
543# TS 51.011 Section 10.3.2
544class EF_IMSI(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200545 def __init__(self, fid='6f07', sfid=None, name='EF.IMSI', desc='IMSI', size=(9, 9)):
Harald Welteb2edd142021-01-08 23:29:35 +0100546 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
Bjoern Riemere91405e2021-12-17 15:16:35 +0100547 # add those commands to the general commands of a TransparentEF
548 self.shell_commands += [self.AddlShellCommands(self)]
Harald Weltec91085e2022-02-10 18:05:45 +0100549
Harald Welteb2edd142021-01-08 23:29:35 +0100550 def _decode_hex(self, raw_hex):
551 return {'imsi': dec_imsi(raw_hex)}
Harald Weltec91085e2022-02-10 18:05:45 +0100552
Harald Welteb2edd142021-01-08 23:29:35 +0100553 def _encode_hex(self, abstract):
554 return enc_imsi(abstract['imsi'])
Harald Weltec91085e2022-02-10 18:05:45 +0100555
Bjoern Riemere91405e2021-12-17 15:16:35 +0100556 @with_default_category('File-Specific Commands')
557 class AddlShellCommands(CommandSet):
Harald Weltec91085e2022-02-10 18:05:45 +0100558 def __init__(self, ef: TransparentEF):
Bjoern Riemere91405e2021-12-17 15:16:35 +0100559 super().__init__()
Harald Weltec91085e2022-02-10 18:05:45 +0100560 self._ef = ef
Bjoern Riemere91405e2021-12-17 15:16:35 +0100561
562 def do_update_imsi_plmn(self, arg: str):
563 """Change the plmn part of the IMSI"""
564 plmn = arg.strip()
565 if len(plmn) == 5 or len(plmn) == 6:
Harald Weltea6c0f882022-07-17 14:23:17 +0200566 (data, sw) = self._cmd.lchan.read_binary_dec()
Bjoern Riemere91405e2021-12-17 15:16:35 +0100567 if sw == '9000' and len(data['imsi'])-len(plmn) == 10:
568 imsi = data['imsi']
569 msin = imsi[len(plmn):]
Harald Weltea6c0f882022-07-17 14:23:17 +0200570 (data, sw) = self._cmd.lchan.update_binary_dec(
Harald Weltec91085e2022-02-10 18:05:45 +0100571 {'imsi': plmn+msin})
Bjoern Riemere91405e2021-12-17 15:16:35 +0100572 if sw == '9000' and data:
Harald Weltec91085e2022-02-10 18:05:45 +0100573 self._cmd.poutput_json(
Harald Weltea6c0f882022-07-17 14:23:17 +0200574 self._cmd.lchan.selected_file.decode_hex(data))
Bjoern Riemere91405e2021-12-17 15:16:35 +0100575 else:
576 raise ValueError("PLMN length does not match IMSI length")
577 else:
578 raise ValueError("PLMN has wrong length!")
579
Harald Welteb2edd142021-01-08 23:29:35 +0100580
581# TS 51.011 Section 10.3.4
582class EF_PLMNsel(TransRecEF):
583 def __init__(self, fid='6f30', sfid=None, name='EF.PLMNsel', desc='PLMN selector',
Harald Welte13edf302022-07-21 15:19:23 +0200584 size=(24, None), rec_len=3, **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100585 super().__init__(fid, name=name, sfid=sfid, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100586
Harald Weltef6b37af2023-01-24 15:42:26 +0100587 def _decode_record_hex(self, in_hex, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100588 if in_hex[:6] == "ffffff":
589 return None
590 else:
591 return dec_plmn(in_hex)
Harald Weltec91085e2022-02-10 18:05:45 +0100592
Harald Weltef6b37af2023-01-24 15:42:26 +0100593 def _encode_record_hex(self, in_json, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100594 if in_json == None:
595 return "ffffff"
596 else:
597 return enc_plmn(in_json['mcc'], in_json['mnc'])
598
Harald Welte790b2702021-04-11 00:01:35 +0200599# TS 51.011 Section 10.3.6
600class EF_ACMmax(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200601 def __init__(self, fid='6f37', sfid=None, name='EF.ACMmax', size=(3, 3),
Harald Welte6169c722022-02-12 09:05:15 +0100602 desc='ACM maximum value', **kwargs):
603 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200604 self._construct = Struct('acm_max'/Int24ub)
605
Harald Welteb2edd142021-01-08 23:29:35 +0100606# TS 51.011 Section 10.3.7
607class EF_ServiceTable(TransparentEF):
608 def __init__(self, fid, sfid, name, desc, size, table):
609 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
610 self.table = table
Harald Weltec91085e2022-02-10 18:05:45 +0100611
Harald Welte7a8aa862021-10-14 20:46:19 +0200612 @staticmethod
Harald Weltec91085e2022-02-10 18:05:45 +0100613 def _bit_byte_offset_for_service(service: int) -> Tuple[int, int]:
Harald Welte7a8aa862021-10-14 20:46:19 +0200614 i = service - 1
615 byte_offset = i//4
616 bit_offset = (i % 4) * 2
617 return (byte_offset, bit_offset)
Harald Weltec91085e2022-02-10 18:05:45 +0100618
Harald Welteb2edd142021-01-08 23:29:35 +0100619 def _decode_bin(self, raw_bin):
620 ret = {}
621 for i in range(0, len(raw_bin)*4):
622 service_nr = i+1
623 byte = int(raw_bin[i//4])
624 bit_offset = (i % 4) * 2
625 bits = (byte >> bit_offset) & 3
626 ret[service_nr] = {
Harald Weltec91085e2022-02-10 18:05:45 +0100627 'description': self.table[service_nr] if service_nr in self.table else None,
628 'allocated': True if bits & 1 else False,
629 'activated': True if bits & 2 else False,
630 }
Harald Welteb2edd142021-01-08 23:29:35 +0100631 return ret
Harald Weltec91085e2022-02-10 18:05:45 +0100632
Harald Welte7a8aa862021-10-14 20:46:19 +0200633 def _encode_bin(self, in_json):
634 # compute the required binary size
635 bin_len = 0
636 for srv in in_json.keys():
637 service_nr = int(srv)
Harald Weltec91085e2022-02-10 18:05:45 +0100638 (byte_offset, bit_offset) = EF_ServiceTable._bit_byte_offset_for_service(
639 service_nr)
Harald Welte7a8aa862021-10-14 20:46:19 +0200640 if byte_offset >= bin_len:
641 bin_len = byte_offset+1
642 # encode the actual data
643 out = bytearray(b'\x00' * bin_len)
644 for srv in in_json.keys():
645 service_nr = int(srv)
Harald Weltec91085e2022-02-10 18:05:45 +0100646 (byte_offset, bit_offset) = EF_ServiceTable._bit_byte_offset_for_service(
647 service_nr)
Harald Welte7a8aa862021-10-14 20:46:19 +0200648 bits = 0
649 if in_json[srv]['allocated'] == True:
650 bits |= 1
651 if in_json[srv]['activated'] == True:
652 bits |= 2
653 out[byte_offset] |= ((bits & 3) << bit_offset)
654 return out
Harald Welteb2edd142021-01-08 23:29:35 +0100655
656# TS 51.011 Section 10.3.11
657class EF_SPN(TransparentEF):
Harald Welte6169c722022-02-12 09:05:15 +0100658 def __init__(self, fid='6f46', sfid=None, name='EF.SPN',
Harald Welte13edf302022-07-21 15:19:23 +0200659 desc='Service Provider Name', size=(17, 17), **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100660 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Robert Falkenbergb07a3e92021-05-07 15:23:20 +0200661 self._construct = BitStruct(
662 # Byte 1
663 'rfu'/BitsRFU(6),
664 'hide_in_oplmn'/Flag,
665 'show_in_hplmn'/Flag,
666 # Bytes 2..17
667 'spn'/Bytewise(GsmString(16))
668 )
Harald Welteb2edd142021-01-08 23:29:35 +0100669
670# TS 51.011 Section 10.3.13
671class EF_CBMI(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200672 def __init__(self, fid='6f45', sfid=None, name='EF.CBMI', size=(2, None), rec_len=2,
Harald Welte6169c722022-02-12 09:05:15 +0100673 desc='Cell Broadcast message identifier selection', **kwargs):
674 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200675 self._construct = GreedyRange(Int16ub)
Harald Welteb2edd142021-01-08 23:29:35 +0100676
677# TS 51.011 Section 10.3.15
678class EF_ACC(TransparentEF):
Harald Welte6169c722022-02-12 09:05:15 +0100679 def __init__(self, fid='6f78', sfid=None, name='EF.ACC',
Harald Welte13edf302022-07-21 15:19:23 +0200680 desc='Access Control Class', size=(2, 2), **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100681 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte1e73d222022-02-13 11:32:50 +0100682 self._construct = HexAdapter(Bytes(2))
Harald Welteb2edd142021-01-08 23:29:35 +0100683
Harald Welte790b2702021-04-11 00:01:35 +0200684# TS 51.011 Section 10.3.16
685class EF_LOCI(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200686 def __init__(self, fid='6f7e', sfid=None, name='EF.LOCI', desc='Location Information', size=(11, 11)):
Harald Welte790b2702021-04-11 00:01:35 +0200687 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
Harald Welte3c98d5e2022-07-20 07:40:05 +0200688 self._construct = Struct('tmsi'/HexAdapter(Bytes(4)), 'lai'/HexAdapter(Bytes(5)), 'tmsi_time'/Int8ub,
Harald Welte790b2702021-04-11 00:01:35 +0200689 'lu_status'/Enum(Byte, updated=0, not_updated=1, plmn_not_allowed=2,
690 location_area_not_allowed=3))
691
Harald Welteb2edd142021-01-08 23:29:35 +0100692# TS 51.011 Section 10.3.18
693class EF_AD(TransparentEF):
Robert Falkenberg9d16fbc2021-04-12 11:43:22 +0200694 class OP_MODE(enum.IntEnum):
Harald Weltec91085e2022-02-10 18:05:45 +0100695 normal = 0x00
696 type_approval = 0x80
697 normal_and_specific_facilities = 0x01
698 type_approval_and_specific_facilities = 0x81
699 maintenance_off_line = 0x02
700 cell_test = 0x04
Robert Falkenberg9d16fbc2021-04-12 11:43:22 +0200701 #OP_MODE_DICT = {int(v) : str(v) for v in EF_AD.OP_MODE}
702 #OP_MODE_DICT_REVERSED = {str(v) : int(v) for v in EF_AD.OP_MODE}
703
Harald Welte13edf302022-07-21 15:19:23 +0200704 def __init__(self, fid='6fad', sfid=None, name='EF.AD', desc='Administrative Data', size=(3, 4)):
Harald Welteb2edd142021-01-08 23:29:35 +0100705 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
Robert Falkenberg9d16fbc2021-04-12 11:43:22 +0200706 self._construct = BitStruct(
707 # Byte 1
708 'ms_operation_mode'/Bytewise(Enum(Byte, EF_AD.OP_MODE)),
709 # Byte 2
710 'rfu1'/Bytewise(ByteRFU),
711 # Byte 3
712 'rfu2'/BitsRFU(7),
713 'ofm'/Flag,
714 # Byte 4 (optional),
715 'extensions'/COptional(Struct(
716 'rfu3'/BitsRFU(4),
717 'mnc_len'/BitsInteger(4),
718 # Byte 5..N-4 (optional, RFU)
719 'extensions'/Bytewise(GreedyBytesRFU)
720 ))
721 )
Harald Welteb2edd142021-01-08 23:29:35 +0100722
Harald Welte790b2702021-04-11 00:01:35 +0200723# TS 51.011 Section 10.3.20 / 10.3.22
724class EF_VGCS(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200725 def __init__(self, fid='6fb1', sfid=None, name='EF.VGCS', size=(4, 200), rec_len=4,
Harald Welte6169c722022-02-12 09:05:15 +0100726 desc='Voice Group Call Service', **kwargs):
727 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200728 self._construct = BcdAdapter(Bytes(4))
729
730# TS 51.011 Section 10.3.21 / 10.3.23
731class EF_VGCSS(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200732 def __init__(self, fid='6fb2', sfid=None, name='EF.VGCSS', size=(7, 7),
Harald Welte6169c722022-02-12 09:05:15 +0100733 desc='Voice Group Call Service Status', **kwargs):
734 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte5b9472d2023-01-24 17:26:59 +0100735 self._construct = BitsSwapped(BitStruct(
736 'flags'/Bit[50], Padding(6, pattern=b'\xff')))
Harald Welte790b2702021-04-11 00:01:35 +0200737
738# TS 51.011 Section 10.3.24
739class EF_eMLPP(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200740 def __init__(self, fid='6fb5', sfid=None, name='EF.eMLPP', size=(2, 2),
Harald Welte6169c722022-02-12 09:05:15 +0100741 desc='enhanced Multi Level Pre-emption and Priority', **kwargs):
742 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100743 FlagsConstruct = FlagsEnum(
744 Byte, A=1, B=2, zero=4, one=8, two=16, three=32, four=64)
745 self._construct = Struct(
746 'levels'/FlagsConstruct, 'fast_call_setup_cond'/FlagsConstruct)
Harald Welte790b2702021-04-11 00:01:35 +0200747
748# TS 51.011 Section 10.3.25
749class EF_AAeM(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200750 def __init__(self, fid='6fb6', sfid=None, name='EF.AAeM', size=(1, 1),
Harald Welte6169c722022-02-12 09:05:15 +0100751 desc='Automatic Answer for eMLPP Service', **kwargs):
752 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100753 FlagsConstruct = FlagsEnum(
754 Byte, A=1, B=2, zero=4, one=8, two=16, three=32, four=64)
Harald Welte790b2702021-04-11 00:01:35 +0200755 self._construct = Struct('auto_answer_prio_levels'/FlagsConstruct)
756
757# TS 51.011 Section 10.3.26
Harald Welteb2edd142021-01-08 23:29:35 +0100758class EF_CBMID(EF_CBMI):
Harald Welte13edf302022-07-21 15:19:23 +0200759 def __init__(self, fid='6f48', sfid=None, name='EF.CBMID', size=(2, None), rec_len=2,
Harald Welte6169c722022-02-12 09:05:15 +0100760 desc='Cell Broadcast Message Identifier for Data Download', **kwargs):
761 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200762 self._construct = GreedyRange(Int16ub)
Harald Welteb2edd142021-01-08 23:29:35 +0100763
Harald Welte89e59542021-04-02 21:33:13 +0200764# TS 51.011 Section 10.3.27
765class EF_ECC(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200766 def __init__(self, fid='6fb7', sfid=None, name='EF.ECC', size=(3, 15), rec_len=3,
Harald Welte6169c722022-02-12 09:05:15 +0100767 desc='Emergency Call Codes', **kwargs):
768 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200769 self._construct = GreedyRange(BcdAdapter(Bytes(3)))
Harald Welteb2edd142021-01-08 23:29:35 +0100770
771# TS 51.011 Section 10.3.28
772class EF_CBMIR(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200773 def __init__(self, fid='6f50', sfid=None, name='EF.CBMIR', size=(4, None), rec_len=4,
Harald Welte6169c722022-02-12 09:05:15 +0100774 desc='Cell Broadcast message identifier range selection', **kwargs):
775 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200776 self._construct = GreedyRange(Struct('lower'/Int16ub, 'upper'/Int16ub))
Harald Welteb2edd142021-01-08 23:29:35 +0100777
Harald Welte790b2702021-04-11 00:01:35 +0200778# TS 51.011 Section 10.3.29
779class EF_DCK(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200780 def __init__(self, fid='6f2c', sfid=None, name='EF.DCK', size=(16, 16),
Harald Welte6169c722022-02-12 09:05:15 +0100781 desc='Depersonalisation Control Keys', **kwargs):
782 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200783 self._construct = Struct('network'/BcdAdapter(Bytes(4)),
784 'network_subset'/BcdAdapter(Bytes(4)),
785 'service_provider'/BcdAdapter(Bytes(4)),
786 'corporate'/BcdAdapter(Bytes(4)))
787# TS 51.011 Section 10.3.30
788class EF_CNL(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200789 def __init__(self, fid='6f32', sfid=None, name='EF.CNL', size=(6, None), rec_len=6,
Harald Welte6169c722022-02-12 09:05:15 +0100790 desc='Co-operative Network List', **kwargs):
791 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100792
Harald Weltef6b37af2023-01-24 15:42:26 +0100793 def _decode_record_hex(self, in_hex, **kwargs):
Harald Welte790b2702021-04-11 00:01:35 +0200794 (in_plmn, sub, svp, corp) = unpack('!3sBBB', h2b(in_hex))
795 res = dec_plmn(b2h(in_plmn))
796 res['network_subset'] = sub
797 res['service_provider_id'] = svp
798 res['corporate_id'] = corp
799 return res
Harald Weltec91085e2022-02-10 18:05:45 +0100800
Harald Weltef6b37af2023-01-24 15:42:26 +0100801 def _encode_record_hex(self, in_json, **kwargs):
Harald Welte790b2702021-04-11 00:01:35 +0200802 plmn = enc_plmn(in_json['mcc'], in_json['mnc'])
Vadim Yanitskiy1a95d2b2021-05-02 01:42:09 +0200803 return b2h(pack('!3sBBB',
804 h2b(plmn),
805 in_json['network_subset'],
806 in_json['service_provider_id'],
807 in_json['corporate_id']))
Harald Welte790b2702021-04-11 00:01:35 +0200808
809# TS 51.011 Section 10.3.31
810class EF_NIA(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200811 def __init__(self, fid='6f51', sfid=None, name='EF.NIA', rec_len=(1, 32),
Harald Welte6169c722022-02-12 09:05:15 +0100812 desc='Network\'s Indication of Alerting', **kwargs):
813 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100814 self._construct = Struct(
815 'alerting_category'/Int8ub, 'category'/GreedyBytes)
Harald Welte790b2702021-04-11 00:01:35 +0200816
817# TS 51.011 Section 10.3.32
818class EF_Kc(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200819 def __init__(self, fid='6f20', sfid=None, name='EF.Kc', desc='Ciphering key Kc', size=(9, 9), **kwargs):
Harald Welted90ceb82022-07-17 22:10:58 +0200820 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200821 self._construct = Struct('kc'/HexAdapter(Bytes(8)), 'cksn'/Int8ub)
822
823# TS 51.011 Section 10.3.33
824class EF_LOCIGPRS(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200825 def __init__(self, fid='6f53', sfid=None, name='EF.LOCIGPRS', desc='GPRS Location Information', size=(14, 14)):
Harald Welte790b2702021-04-11 00:01:35 +0200826 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size)
Harald Welte3c98d5e2022-07-20 07:40:05 +0200827 self._construct = Struct('ptmsi'/HexAdapter(Bytes(4)), 'ptmsi_sig'/Int8ub, 'rai'/HexAdapter(Bytes(6)),
Harald Welte790b2702021-04-11 00:01:35 +0200828 'rau_status'/Enum(Byte, updated=0, not_updated=1, plmn_not_allowed=2,
829 routing_area_not_allowed=3))
Harald Welteb2edd142021-01-08 23:29:35 +0100830
831# TS 51.011 Section 10.3.35..37
832class EF_xPLMNwAcT(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200833 def __init__(self, fid, sfid=None, name=None, desc=None, size=(40, None), rec_len=5, **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100834 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100835
Harald Weltef6b37af2023-01-24 15:42:26 +0100836 def _decode_record_hex(self, in_hex, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100837 if in_hex[:6] == "ffffff":
838 return None
839 else:
840 return dec_xplmn_w_act(in_hex)
Harald Weltec91085e2022-02-10 18:05:45 +0100841
Harald Weltef6b37af2023-01-24 15:42:26 +0100842 def _encode_record_hex(self, in_json, **kwargs):
Harald Welteb2edd142021-01-08 23:29:35 +0100843 if in_json == None:
844 return "ffffff0000"
845 else:
846 hplmn = enc_plmn(in_json['mcc'], in_json['mnc'])
847 act = self.enc_act(in_json['act'])
848 return hplmn + act
Harald Weltec91085e2022-02-10 18:05:45 +0100849
Harald Welteb2edd142021-01-08 23:29:35 +0100850 @staticmethod
851 def enc_act(in_list):
852 u16 = 0
853 # first the simple ones
854 if 'UTRAN' in in_list:
855 u16 |= 0x8000
856 if 'NG-RAN' in in_list:
857 u16 |= 0x0800
858 if 'GSM COMPACT' in in_list:
859 u16 |= 0x0040
860 if 'cdma2000 HRPD' in in_list:
861 u16 |= 0x0020
862 if 'cdma2000 1xRTT' in in_list:
863 u16 |= 0x0010
864 # E-UTRAN
Philipp Maiere7d41792021-04-29 16:20:07 +0200865 if 'E-UTRAN' in in_list:
866 u16 |= 0x4000
Vadim Yanitskiy5452d642021-03-07 21:45:34 +0100867 if 'E-UTRAN WB-S1' in in_list:
868 u16 |= 0x6000
869 if 'E-UTRAN NB-S1' in in_list:
870 u16 |= 0x5000
Harald Welteb2edd142021-01-08 23:29:35 +0100871 # GSM mess
872 if 'GSM' in in_list and 'EC-GSM-IoT' in in_list:
873 u16 |= 0x008C
874 elif 'GSM' in in_list:
875 u16 |= 0x0084
876 elif 'EC-GSM-IuT' in in_list:
877 u16 |= 0x0088
Harald Weltec91085e2022-02-10 18:05:45 +0100878 return '%04X' % (u16)
Harald Welteb2edd142021-01-08 23:29:35 +0100879
Harald Welte790b2702021-04-11 00:01:35 +0200880# TS 51.011 Section 10.3.38
881class EF_CPBCCH(TransRecEF):
Harald Welte13edf302022-07-21 15:19:23 +0200882 def __init__(self, fid='6f63', sfid=None, name='EF.CPBCCH', size=(2, 14), rec_len=2,
Harald Welted90ceb82022-07-17 22:10:58 +0200883 desc='CPBCCH Information', **kwargs):
884 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200885 self._construct = Struct('cpbcch'/Int16ub)
886
887# TS 51.011 Section 10.3.39
888class EF_InvScan(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +0200889 def __init__(self, fid='6f64', sfid=None, name='EF.InvScan', size=(1, 1),
Harald Welted90ceb82022-07-17 22:10:58 +0200890 desc='IOnvestigation Scan', **kwargs):
891 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Weltec91085e2022-02-10 18:05:45 +0100892 self._construct = FlagsEnum(
893 Byte, in_limited_service_mode=1, after_successful_plmn_selection=2)
Harald Welte790b2702021-04-11 00:01:35 +0200894
Harald Welte14105dc2021-05-31 08:48:51 +0200895# TS 51.011 Section 4.2.58
896class EF_PNN(LinFixedEF):
897 class FullNameForNetwork(BER_TLV_IE, tag=0x43):
898 # TS 24.008 10.5.3.5a
Harald Welte857f1102022-07-20 07:44:25 +0200899 # TODO: proper decode
900 _construct = HexAdapter(GreedyBytes)
Harald Weltec91085e2022-02-10 18:05:45 +0100901
Harald Welte14105dc2021-05-31 08:48:51 +0200902 class ShortNameForNetwork(BER_TLV_IE, tag=0x45):
903 # TS 24.008 10.5.3.5a
Harald Welte857f1102022-07-20 07:44:25 +0200904 # TODO: proper decode
905 _construct = HexAdapter(GreedyBytes)
Harald Weltec91085e2022-02-10 18:05:45 +0100906
Harald Welte14105dc2021-05-31 08:48:51 +0200907 class NetworkNameCollection(TLV_IE_Collection, nested=[FullNameForNetwork, ShortNameForNetwork]):
908 pass
Harald Weltec91085e2022-02-10 18:05:45 +0100909
Harald Welte6169c722022-02-12 09:05:15 +0100910 def __init__(self, fid='6fc5', sfid=None, name='EF.PNN', desc='PLMN Network Name', **kwargs):
911 super().__init__(fid, sfid=sfid, name=name, desc=desc, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200912 self._tlv = EF_PNN.NetworkNameCollection
913
Harald Welte790b2702021-04-11 00:01:35 +0200914# TS 51.011 Section 10.3.42
915class EF_OPL(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200916 def __init__(self, fid='6fc6', sfid=None, name='EF.OPL', rec_len=(8, 8), desc='Operator PLMN List', **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100917 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Welte3c98d5e2022-07-20 07:40:05 +0200918 self._construct = Struct('lai'/Struct('mcc_mnc'/BcdAdapter(Bytes(3)),
919 'lac_min'/HexAdapter(Bytes(2)), 'lac_max'/HexAdapter(Bytes(2))), 'pnn_record_id'/Int8ub)
Harald Welte790b2702021-04-11 00:01:35 +0200920
921# TS 51.011 Section 10.3.44 + TS 31.102 4.2.62
922class EF_MBI(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200923 def __init__(self, fid='6fc9', sfid=None, name='EF.MBI', rec_len=(4, 5), desc='Mailbox Identifier', **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100924 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200925 self._construct = Struct('mbi_voicemail'/Int8ub, 'mbi_fax'/Int8ub, 'mbi_email'/Int8ub,
926 'mbi_other'/Int8ub, 'mbi_videocall'/COptional(Int8ub))
927
928# TS 51.011 Section 10.3.45 + TS 31.102 4.2.63
929class EF_MWIS(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200930 def __init__(self, fid='6fca', sfid=None, name='EF.MWIS', rec_len=(5, 6),
Harald Welte6169c722022-02-12 09:05:15 +0100931 desc='Message Waiting Indication Status', **kwargs):
932 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +0200933 self._construct = Struct('mwi_status'/FlagsEnum(Byte, voicemail=1, fax=2, email=4, other=8, videomail=16),
934 'num_waiting_voicemail'/Int8ub,
935 'num_waiting_fax'/Int8ub, 'num_waiting_email'/Int8ub,
936 'num_waiting_other'/Int8ub, 'num_waiting_videomail'/COptional(Int8ub))
937
Harald Welte14105dc2021-05-31 08:48:51 +0200938# TS 51.011 Section 10.3.66
939class EF_SPDI(TransparentEF):
940 class ServiceProviderPLMN(BER_TLV_IE, tag=0x80):
941 # flexible numbers of 3-byte PLMN records
942 _construct = GreedyRange(BcdAdapter(Bytes(3)))
Harald Weltec91085e2022-02-10 18:05:45 +0100943
Harald Welte14105dc2021-05-31 08:48:51 +0200944 class SPDI(BER_TLV_IE, tag=0xA3, nested=[ServiceProviderPLMN]):
945 pass
946 def __init__(self, fid='6fcd', sfid=None, name='EF.SPDI',
Harald Welte6169c722022-02-12 09:05:15 +0100947 desc='Service Provider Display Information', **kwargs):
948 super().__init__(fid, sfid=sfid, name=name, desc=desc, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200949 self._tlv = EF_SPDI.SPDI
950
Harald Welte790b2702021-04-11 00:01:35 +0200951# TS 51.011 Section 10.3.51
952class EF_MMSN(LinFixedEF):
Harald Welte99e4cc02022-07-21 15:25:47 +0200953 def __init__(self, fid='6fce', sfid=None, name='EF.MMSN', rec_len=(4, 20), desc='MMS Notification', **kwargs):
Harald Welte6169c722022-02-12 09:05:15 +0100954 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Welte3c98d5e2022-07-20 07:40:05 +0200955 self._construct = Struct('mms_status'/HexAdapter(Bytes(2)), 'mms_implementation'/HexAdapter(Bytes(1)),
956 'mms_notification'/HexAdapter(Bytes(this._.total_len-4)), 'ext_record_nr'/Byte)
Harald Welte790b2702021-04-11 00:01:35 +0200957
Harald Welte14105dc2021-05-31 08:48:51 +0200958# TS 51.011 Annex K.1
959class MMS_Implementation(BER_TLV_IE, tag=0x80):
960 _construct = FlagsEnum(Byte, WAP=1)
961
Harald Welte790b2702021-04-11 00:01:35 +0200962# TS 51.011 Section 10.3.53
963class EF_MMSICP(TransparentEF):
Harald Welte14105dc2021-05-31 08:48:51 +0200964 class MMS_Relay_Server(BER_TLV_IE, tag=0x81):
965 # 3GPP TS 23.140
966 pass
Harald Weltec91085e2022-02-10 18:05:45 +0100967
Harald Welte14105dc2021-05-31 08:48:51 +0200968 class Interface_to_CN(BER_TLV_IE, tag=0x82):
969 # 3GPP TS 23.140
970 pass
Harald Weltec91085e2022-02-10 18:05:45 +0100971
Harald Welte14105dc2021-05-31 08:48:51 +0200972 class Gateway(BER_TLV_IE, tag=0x83):
973 # Address, Type of address, Port, Service, AuthType, AuthId, AuthPass / 3GPP TS 23.140
974 pass
Harald Weltec91085e2022-02-10 18:05:45 +0100975
Harald Welte14105dc2021-05-31 08:48:51 +0200976 class MMS_ConnectivityParamters(TLV_IE_Collection,
Harald Weltec91085e2022-02-10 18:05:45 +0100977 nested=[MMS_Implementation, MMS_Relay_Server, Interface_to_CN, Gateway]):
Harald Welte14105dc2021-05-31 08:48:51 +0200978 pass
Harald Welte13edf302022-07-21 15:19:23 +0200979 def __init__(self, fid='6fd0', sfid=None, name='EF.MMSICP', size=(1, None),
Harald Welte6169c722022-02-12 09:05:15 +0100980 desc='MMS Issuer Connectivity Parameters', **kwargs):
981 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte14105dc2021-05-31 08:48:51 +0200982 self._tlv = EF_MMSICP.MMS_ConnectivityParamters
Harald Welte790b2702021-04-11 00:01:35 +0200983
984# TS 51.011 Section 10.3.54
985class EF_MMSUP(LinFixedEF):
Harald Welte14105dc2021-05-31 08:48:51 +0200986 class MMS_UserPref_ProfileName(BER_TLV_IE, tag=0x81):
987 pass
Harald Weltec91085e2022-02-10 18:05:45 +0100988
Harald Welte14105dc2021-05-31 08:48:51 +0200989 class MMS_UserPref_Info(BER_TLV_IE, tag=0x82):
990 pass
Harald Weltec91085e2022-02-10 18:05:45 +0100991
Harald Welte14105dc2021-05-31 08:48:51 +0200992 class MMS_User_Preferences(TLV_IE_Collection,
Harald Weltec91085e2022-02-10 18:05:45 +0100993 nested=[MMS_Implementation, MMS_UserPref_ProfileName, MMS_UserPref_Info]):
Harald Welte14105dc2021-05-31 08:48:51 +0200994 pass
Harald Welte99e4cc02022-07-21 15:25:47 +0200995 def __init__(self, fid='6fd1', sfid=None, name='EF.MMSUP', rec_len=(1, None),
Harald Welte6169c722022-02-12 09:05:15 +0100996 desc='MMS User Preferences', **kwargs):
997 super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=rec_len, **kwargs)
Harald Welte6113fe92022-01-21 15:51:35 +0100998 self._tlv = EF_MMSUP.MMS_User_Preferences
Harald Welte790b2702021-04-11 00:01:35 +0200999
1000# TS 51.011 Section 10.3.55
1001class EF_MMSUCP(TransparentEF):
Harald Welte13edf302022-07-21 15:19:23 +02001002 def __init__(self, fid='6fd2', sfid=None, name='EF.MMSUCP', size=(1, None),
Harald Welte6169c722022-02-12 09:05:15 +01001003 desc='MMS User Connectivity Parameters', **kwargs):
1004 super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, **kwargs)
Harald Welte790b2702021-04-11 00:01:35 +02001005
Harald Welteb2edd142021-01-08 23:29:35 +01001006
1007class DF_GSM(CardDF):
1008 def __init__(self, fid='7f20', name='DF.GSM', desc='GSM Network related files'):
1009 super().__init__(fid=fid, name=name, desc=desc)
1010 files = [
Harald Weltec91085e2022-02-10 18:05:45 +01001011 EF_LP(),
1012 EF_IMSI(),
1013 EF_Kc(),
1014 EF_PLMNsel(),
1015 TransparentEF('6f31', None, 'EF.HPPLMN',
1016 'Higher Priority PLMN search period'),
1017 EF_ACMmax(),
1018 EF_ServiceTable('6f38', None, 'EF.SST',
Harald Welte13edf302022-07-21 15:19:23 +02001019 'SIM service table', table=EF_SST_map, size=(2, 16)),
Harald Weltec91085e2022-02-10 18:05:45 +01001020 CyclicEF('6f39', None, 'EF.ACM',
Harald Welte99e4cc02022-07-21 15:25:47 +02001021 'Accumulated call meter', rec_len=(3, 3)),
Harald Weltec91085e2022-02-10 18:05:45 +01001022 TransparentEF('6f3e', None, 'EF.GID1', 'Group Identifier Level 1'),
1023 TransparentEF('6f3f', None, 'EF.GID2', 'Group Identifier Level 2'),
1024 EF_SPN(),
1025 TransparentEF('6f41', None, 'EF.PUCT',
Harald Welte13edf302022-07-21 15:19:23 +02001026 'Price per unit and currency table', size=(5, 5)),
Harald Weltec91085e2022-02-10 18:05:45 +01001027 EF_CBMI(),
1028 TransparentEF('6f7f', None, 'EF.BCCH',
Harald Welte13edf302022-07-21 15:19:23 +02001029 'Broadcast control channels', size=(16, 16)),
Harald Weltec91085e2022-02-10 18:05:45 +01001030 EF_ACC(),
1031 EF_PLMNsel('6f7b', None, 'EF.FPLMN',
Harald Welte13edf302022-07-21 15:19:23 +02001032 'Forbidden PLMNs', size=(12, 12)),
Harald Weltec91085e2022-02-10 18:05:45 +01001033 EF_LOCI(),
1034 EF_AD(),
1035 TransparentEF('6fa3', None, 'EF.Phase',
Harald Welte13edf302022-07-21 15:19:23 +02001036 'Phase identification', size=(1, 1)),
Harald Weltec91085e2022-02-10 18:05:45 +01001037 EF_VGCS(),
1038 EF_VGCSS(),
1039 EF_VGCS('6fb3', None, 'EF.VBS', 'Voice Broadcast Service'),
1040 EF_VGCSS('6fb4', None, 'EF.VBSS',
1041 'Voice Broadcast Service Status'),
1042 EF_eMLPP(),
1043 EF_AAeM(),
1044 EF_CBMID(),
1045 EF_ECC(),
1046 EF_CBMIR(),
1047 EF_DCK(),
1048 EF_CNL(),
1049 EF_NIA(),
1050 EF_Kc('6f52', None, 'EF.KcGPRS', 'GPRS Ciphering key KcGPRS'),
1051 EF_LOCIGPRS(),
1052 TransparentEF('6f54', None, 'EF.SUME', 'SetUpMenu Elements'),
1053 EF_xPLMNwAcT('6f60', None, 'EF.PLMNwAcT',
1054 'User controlled PLMN Selector with Access Technology'),
1055 EF_xPLMNwAcT('6f61', None, 'EF.OPLMNwAcT',
1056 'Operator controlled PLMN Selector with Access Technology'),
1057 EF_xPLMNwAcT('6f62', None, 'EF.HPLMNwAcT',
1058 'HPLMN Selector with Access Technology'),
1059 EF_CPBCCH(),
1060 EF_InvScan(),
1061 EF_PNN(),
1062 EF_OPL(),
1063 EF_ADN('6fc7', None, 'EF.MBDN', 'Mailbox Dialling Numbers'),
1064 EF_MBI(),
1065 EF_MWIS(),
1066 EF_ADN('6fcb', None, 'EF.CFIS',
1067 'Call Forwarding Indication Status'),
1068 EF_EXT('6fc8', None, 'EF.EXT6', 'Externsion6 (MBDN)'),
1069 EF_EXT('6fcc', None, 'EF.EXT7', 'Externsion7 (CFIS)'),
1070 EF_SPDI(),
1071 EF_MMSN(),
1072 EF_EXT('6fcf', None, 'EF.EXT8', 'Extension8 (MMSN)'),
1073 EF_MMSICP(),
1074 EF_MMSUP(),
1075 EF_MMSUCP(),
1076 ]
Harald Welteb2edd142021-01-08 23:29:35 +01001077 self.add_files(files)
1078
Harald Weltec91085e2022-02-10 18:05:45 +01001079
Philipp Maierc8387dc2021-10-29 17:59:50 +02001080class CardProfileSIM(CardProfile):
Philipp Maiera028c7d2021-11-08 16:12:03 +01001081
1082 ORDER = 2
1083
Philipp Maierc8387dc2021-10-29 17:59:50 +02001084 def __init__(self):
Philipp Maiera4df9422021-11-10 17:13:40 +01001085 sw = {
Harald Weltec91085e2022-02-10 18:05:45 +01001086 'Normal': {
1087 '9000': 'Normal ending of the command',
1088 '91xx': 'normal ending of the command, with extra information from the proactive SIM containing a command for the ME',
1089 '9exx': 'length XX of the response data given in case of a SIM data download error',
1090 '9fxx': 'length XX of the response data',
Philipp Maiera4df9422021-11-10 17:13:40 +01001091 },
Harald Weltec91085e2022-02-10 18:05:45 +01001092 'Postponed processing': {
1093 '9300': 'SIM Application Toolkit is busy. Command cannot be executed at present, further normal commands are allowed',
Philipp Maiera4df9422021-11-10 17:13:40 +01001094 },
Harald Weltec91085e2022-02-10 18:05:45 +01001095 'Memory management': {
1096 '920x': 'command successful but after using an internal update retry routine X times',
1097 '9240': 'memory problem',
Philipp Maiera4df9422021-11-10 17:13:40 +01001098 },
Harald Weltec91085e2022-02-10 18:05:45 +01001099 'Referencing management': {
1100 '9400': 'no EF selected',
1101 '9402': 'out of range (invalid address)',
1102 '9404': 'file ID not found or pattern not found',
1103 '9408': 'file is inconsistent with the command',
Philipp Maiera4df9422021-11-10 17:13:40 +01001104 },
Harald Weltec91085e2022-02-10 18:05:45 +01001105 'Security management': {
1106 '9802': 'no CHV initialized',
1107 '9804': 'access condition not fulfilled, unsuccessful CHV verification or authentication failed',
1108 '9808': 'in contradiction with CHV status',
1109 '9810': 'in contradiction with invalidation status',
1110 '9840': 'unsuccessful verification, CHV blocked, UNBLOCK CHV blocked',
1111 '9850': 'increase cannot be performed, Max value reached',
Philipp Maiera4df9422021-11-10 17:13:40 +01001112 },
Harald Weltec91085e2022-02-10 18:05:45 +01001113 'Application independent errors': {
1114 '67xx': 'incorrect parameter P3',
1115 '6bxx': 'incorrect parameter P1 or P2',
1116 '6dxx': 'unknown instruction code given in the command',
1117 '6exx': 'wrong instruction class given in the command',
1118 '6fxx': 'technical problem with no diagnostic given',
Philipp Maiera4df9422021-11-10 17:13:40 +01001119 },
Harald Weltec91085e2022-02-10 18:05:45 +01001120 }
Philipp Maiera4df9422021-11-10 17:13:40 +01001121
Harald Weltec91085e2022-02-10 18:05:45 +01001122 super().__init__('SIM', desc='GSM SIM Card', cla="a0",
1123 sel_ctrl="0000", files_in_mf=[DF_TELECOM(), DF_GSM()], sw=sw)
Philipp Maier4ab971c2021-11-11 11:53:49 +01001124
Philipp Maier5998a3a2021-11-16 15:16:39 +01001125 @staticmethod
Harald Weltec91085e2022-02-10 18:05:45 +01001126 def decode_select_response(resp_hex: str) -> object:
Philipp Maier4ab971c2021-11-11 11:53:49 +01001127 resp_bin = h2b(resp_hex)
1128 struct_of_file_map = {
1129 0: 'transparent',
1130 1: 'linear_fixed',
1131 3: 'cyclic'
Harald Weltec91085e2022-02-10 18:05:45 +01001132 }
Philipp Maier4ab971c2021-11-11 11:53:49 +01001133 type_of_file_map = {
1134 1: 'mf',
1135 2: 'df',
1136 4: 'working_ef'
Harald Weltec91085e2022-02-10 18:05:45 +01001137 }
Philipp Maier4ab971c2021-11-11 11:53:49 +01001138 ret = {
Harald Welte747a9782022-02-13 17:52:28 +01001139 'file_descriptor': {
1140 'file_descriptor_byte': {},
1141 },
Philipp Maier4ab971c2021-11-11 11:53:49 +01001142 'proprietary_info': {},
Harald Weltec91085e2022-02-10 18:05:45 +01001143 }
Philipp Maier4ab971c2021-11-11 11:53:49 +01001144 ret['file_id'] = b2h(resp_bin[4:6])
Harald Weltec91085e2022-02-10 18:05:45 +01001145 ret['proprietary_info']['available_memory'] = int.from_bytes(
1146 resp_bin[2:4], 'big')
1147 file_type = type_of_file_map[resp_bin[6]
1148 ] if resp_bin[6] in type_of_file_map else resp_bin[6]
Harald Welte747a9782022-02-13 17:52:28 +01001149 ret['file_descriptor']['file_descriptor_byte']['file_type'] = file_type
Philipp Maier4ab971c2021-11-11 11:53:49 +01001150 if file_type in ['mf', 'df']:
1151 ret['file_characteristics'] = b2h(resp_bin[13:14])
1152 ret['num_direct_child_df'] = resp_bin[14]
1153 ret['num_direct_child_ef'] = resp_bin[15]
1154 ret['num_chv_unblock_adm_codes'] = int(resp_bin[16])
1155 # CHV / UNBLOCK CHV stats
1156 elif file_type in ['working_ef']:
Harald Weltec91085e2022-02-10 18:05:45 +01001157 file_struct = struct_of_file_map[resp_bin[13]
1158 ] if resp_bin[13] in struct_of_file_map else resp_bin[13]
Harald Welte747a9782022-02-13 17:52:28 +01001159 ret['file_descriptor']['file_descriptor_byte']['structure'] = file_struct
Philipp Maier4ab971c2021-11-11 11:53:49 +01001160 ret['access_conditions'] = b2h(resp_bin[8:10])
1161 if resp_bin[11] & 0x01 == 0:
1162 ret['life_cycle_status_int'] = 'operational_activated'
1163 elif resp_bin[11] & 0x04:
1164 ret['life_cycle_status_int'] = 'operational_deactivated'
1165 else:
1166 ret['life_cycle_status_int'] = 'terminated'
1167 return ret
Philipp Maiera028c7d2021-11-08 16:12:03 +01001168
1169 @staticmethod
Harald Weltec91085e2022-02-10 18:05:45 +01001170 def match_with_card(scc: SimCardCommands) -> bool:
Philipp Maiera028c7d2021-11-08 16:12:03 +01001171 return match_sim(scc)