diff options
-rwxr-xr-x | pySim-read.py | 7 | ||||
-rw-r--r-- | pySim/cards.py | 41 | ||||
-rw-r--r-- | pySim/commands.py | 11 | ||||
-rw-r--r-- | pySim/utils.py | 22 | ||||
-rw-r--r-- | pysim-testdata/sysmoISIM-SJA2.ok | 6 |
5 files changed, 83 insertions, 4 deletions
diff --git a/pySim-read.py b/pySim-read.py index 69cab4d..d6674a5 100755 --- a/pySim-read.py +++ b/pySim-read.py @@ -241,6 +241,13 @@ if __name__ == '__main__': # Check whether we have th AID of USIM, if so select it by its AID # EF.UST - File Id in ADF USIM : 6f38 if '9000' == card.select_adf_by_aid(): + # EF.EHPLMN + if card.file_exists(EF_USIM_ADF_map['EHPLMN']): + (res, sw) = card.read_ehplmn() + if sw == '9000': + print("EHPLMN:\n%s" % (res)) + else: + print("EHPLMN: Can't read, response code = %s" % (sw,)) # EF.UST (res, sw) = card.read_binary(EF_USIM_ADF_map['UST']) if sw == '9000': diff --git a/pySim/cards.py b/pySim/cards.py index 808fde1..2d779b3 100644 --- a/pySim/cards.py +++ b/pySim/cards.py @@ -24,6 +24,7 @@ # from pySim.ts_51_011 import EF, DF +from pySim.ts_31_102 import EF_USIM_ADF_map from pySim.utils import * from smartcard.util import toBytes @@ -41,6 +42,13 @@ class Card(object): print("warning: erasing is not supported for specified card type!") return + def file_exists(self, fid): + res_arr = self._scc.try_select_file(fid) + for res in res_arr: + if res[1] != '9000': + return False + return True + def verify_adm(self, key): ''' Authenticate with ADM key @@ -262,6 +270,25 @@ class Card(object): len = self._scc.record_size(ef) self._scc.update_record(ef, rec_no, "ff" * len, force_len=False, verify=True) +class UsimCard(Card): + def __init__(self, ssc): + super(UsimCard, self).__init__(ssc) + + def read_ehplmn(self): + (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN']) + if sw == '9000': + return (format_xplmn(res), sw) + else: + return (None, sw) + + def update_ehplmn(self, mcc, mnc): + data = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'], length=None, offset=0) + size = len(data[0]) // 2 + ehplmn = enc_plmn(mcc, mnc) + data, sw = self._scc.update_binary(EF_USIM_ADF_map['EHPLMN'], ehplmn) + return sw + + class _MagicSimBase(Card): """ @@ -552,7 +579,7 @@ class SysmoSIMgr1(GrcardSim): return None return None -class SysmoUSIMgr1(Card): +class SysmoUSIMgr1(UsimCard): """ sysmocom sysmoUSIM-GR1 """ @@ -653,7 +680,7 @@ class SysmoSIMgr2(Card): data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80)) -class SysmoUSIMSJS1(Card): +class SysmoUSIMSJS1(UsimCard): """ sysmocom sysmoUSIM-SJS1 """ @@ -1037,7 +1064,7 @@ class WavemobileSim(Card): return None -class SysmoISIMSJA2(Card): +class SysmoISIMSJA2(UsimCard): """ sysmocom sysmoISIM-SJA2 """ @@ -1144,16 +1171,22 @@ class SysmoISIMSJA2(Card): if p.get('opc'): self._scc.update_binary('af20', p['opc'], 17) - # update EF-USIM_AUTH_KEY in ADF.USIM self._scc.select_file(['3f00']) aid = self.read_aid() if (aid): + # update EF-USIM_AUTH_KEY in ADF.USIM self._scc.select_adf(aid) if p.get('ki'): self._scc.update_binary('af20', p['ki'], 1) if p.get('opc'): self._scc.update_binary('af20', p['opc'], 17) + # update EF.EHPLMN in ADF.USIM + if self.file_exists(EF_USIM_ADF_map['EHPLMN']): + if p.get('mcc') and p.get('mnc'): + sw = self.update_ehplmn(p['mcc'], p['mnc']) + if sw != '9000': + print("Programming EHPLMN failed with code %s"%sw) return diff --git a/pySim/commands.py b/pySim/commands.py index 7288b19..c260a97 100644 --- a/pySim/commands.py +++ b/pySim/commands.py @@ -100,6 +100,17 @@ class SimCardCommands(object): def sel_ctrl(self, value): self._sel_ctrl = value + def try_select_file(self, dir_list): + rv = [] + if type(dir_list) is not list: + dir_list = [dir_list] + for i in dir_list: + data, sw = self._tp.send_apdu(self.cla_byte + "a4" + self.sel_ctrl + "02" + i) + rv.append((data, sw)) + if sw != '9000': + return rv + return rv + def select_file(self, dir_list): rv = [] if type(dir_list) is not list: diff --git a/pySim/utils.py b/pySim/utils.py index ac82774..dc14d58 100644 --- a/pySim/utils.py +++ b/pySim/utils.py @@ -125,6 +125,9 @@ def enc_spn(name, hplmn_disp=False, oplmn_disp=False): def hexstr_to_fivebytearr(s): return [s[i:i+10] for i in range(0, len(s), 10) ] +def hexstr_to_threebytearr(s): + return [s[i:i+6] for i in range(0, len(s), 6) ] + # Accepts hex string representing three bytes def dec_mcc_from_plmn(plmn): ia = h2i(plmn) @@ -213,6 +216,25 @@ def dec_epsloci(hexstr): res['status'] = h2i(hexstr[34:36]) return res +def dec_xplmn(threehexbytes): + res = {'mcc': 0, 'mnc': 0, 'act': []} + plmn_chars = 6 + plmn_str = threehexbytes[:plmn_chars] # first three bytes (six ascii hex chars) + res['mcc'] = dec_mcc_from_plmn(plmn_str) + res['mnc'] = dec_mnc_from_plmn(plmn_str) + return res + +def format_xplmn(hexstr): + s = "" + for rec_data in hexstr_to_threebytearr(hexstr): + rec_info = dec_xplmn(rec_data) + if rec_info['mcc'] == 0xFFF and rec_info['mnc'] == 0xFFF: + rec_str = "unused" + else: + rec_str = "MCC: %03d MNC: %03d" % (rec_info['mcc'], rec_info['mnc']) + s += "\t%s # %s\n" % (rec_data, rec_str) + return s + def derive_milenage_opc(ki_hex, op_hex): """ Run the milenage algorithm to calculate OPC from Ki and OP diff --git a/pysim-testdata/sysmoISIM-SJA2.ok b/pysim-testdata/sysmoISIM-SJA2.ok index fd3f252..6054840 100644 --- a/pysim-testdata/sysmoISIM-SJA2.ok +++ b/pysim-testdata/sysmoISIM-SJA2.ok @@ -100,6 +100,12 @@ SIM Service Table: ff33ffff3f003f0f300cf0c3f00000 Service 58 - Extension 8 Service 59 - MMS User Connectivity Parameters +EHPLMN: + 00f110 # MCC: 001 MNC: 001 + ffffff # unused + ffffff # unused + ffffff # unused + USIM Service Table: beff9f9de73e0408400170730000002e00000000 Service 2 - Fixed Dialling Numbers (FDN) Service 3 - Extension 2 |