Sorry! The patch had one error (name of argument mismatch with use in function body). Fixed it.
On Tue, Dec 4, 2018 at 9:47 AM Daniel Laszlo Sitzer <[email protected]> wrote: > Hello everyone, > > I implemented decoding of the [O|H]PLMNwAcT elementary file in pySim. > Here https://github.com/lazlo/pysim-dec-plmn you will also find unit > tests for the code I wrote. > > Let me know if I should further refactor the code (maybe to use more of > the existing conversions functions in pySim/util.py). I'm aware it is not > the most elegant code but it does its job. > > Best, > > Lazlo >
From c4923d41ea78f96ce8c35d38f8022661a8d1d08b Mon Sep 17 00:00:00 2001 From: Laszlo Sitzer <[email protected]> Date: Mon, 3 Dec 2018 17:40:20 +0100 Subject: [PATCH] WIP: Decode xPLMNwAcT. --- pySim-read.py | 8 +++--- pySim/utils.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/pySim-read.py b/pySim-read.py index 4356453..6341fd0 100755 --- a/pySim-read.py +++ b/pySim-read.py @@ -37,7 +37,7 @@ except ImportError: import simplejson as json from pySim.commands import SimCardCommands -from pySim.utils import h2b, swap_nibbles, rpad, dec_imsi, dec_iccid +from pySim.utils import h2b, swap_nibbles, rpad, dec_imsi, dec_iccid, format_xplmn_w_act def parse_options(): @@ -129,7 +129,7 @@ if __name__ == '__main__': try: (res, sw) = scc.read_binary(EF['PLMNwAcT']) if sw == '9000': - print("PLMNwAcT: %s" % (res)) + print("PLMNwAcT:\n%s" % (format_xplmn_w_act(res))) else: print("PLMNwAcT: Can't read, response code = %s" % (sw,)) except Exception as e: @@ -139,7 +139,7 @@ if __name__ == '__main__': try: (res, sw) = scc.read_binary(EF['OPLMNwAcT']) if sw == '9000': - print("OPLMNwAcT: %s" % (res)) + print("OPLMNwAcT:\n%s" % (format_xplmn_w_act(res))) else: print("OPLMNwAcT: Can't read, response code = %s" % (sw,)) except Exception as e: @@ -149,7 +149,7 @@ if __name__ == '__main__': try: (res, sw) = scc.read_binary(EF['HPLMNAcT']) if sw == '9000': - print("HPLMNAcT: %s" % (res)) + print("HPLMNAcT:\n%s" % (format_xplmn_w_act(res))) else: print("HPLMNAcT: Can't read, response code = %s" % (sw,)) except Exception as e: diff --git a/pySim/utils.py b/pySim/utils.py index ba94702..3ea543f 100644 --- a/pySim/utils.py +++ b/pySim/utils.py @@ -113,6 +113,79 @@ def enc_spn(name, hplmn_disp=False, oplmn_disp=False): if oplmn_disp: byte1 = byte1|0x02 return i2h([byte1])+s2h(name) +def hexstr_to_fivebytearr(s): + return [s[i:i+10] for i in range(0, len(s), 10) ] + +# Accepts hex string representing three bytes +def dec_mcc_from_plmn(plmn): + ia = h2i(plmn) + digit1 = ia[0] & 0x0F # 1st byte, LSB + digit2 = (ia[0] & 0xF0) >> 4 # 1st byte, MSB + digit3 = ia[1] & 0x0F # 2nd byte, LSB + if digit3 == 0xF and digit2 == 0xF and digit1 == 0xF: + return 0xFFF # 4095 + mcc = digit1 * 100 + mcc += digit2 * 10 + mcc += digit3 + return mcc + +def dec_mnc_from_plmn(plmn): + ia = h2i(plmn) + digit1 = ia[2] & 0x0F # 3rd byte, LSB + digit2 = (ia[2] & 0xF0) >> 4 # 3rd byte, MSB + digit3 = (ia[1] & 0xF0) >> 4 # 2nd byte, MSB + if digit3 == 0xF and digit2 == 0xF and digit1 == 0xF: + return 0xFFF # 4095 + mnc = 0 + # signifies two digit MNC + if digit3 == 0xF: + mnc += digit1 * 10 + mnc += digit2 + else: + mnc += digit1 * 100 + mnc += digit2 * 10 + mnc += digit3 + return mnc + +def dec_act(twohexbytes): + act_list = [ + {'bit': 15, 'name': "UTRAN"}, + {'bit': 14, 'name': "E-UTRAN"}, + {'bit': 7, 'name': "GSM"}, + {'bit': 6, 'name': "GSM COMPACT"}, + {'bit': 5, 'name': "cdma2000 HRPD"}, + {'bit': 4, 'name': "cdma2000 1xRTT"}, + ] + ia = h2i(twohexbytes) + u16t = (ia[0] << 8)|ia[1] + sel = [] + for a in act_list: + if u16t & (1 << a['bit']): + sel.append(a['name']) + return sel + +def dec_xplmn_w_act(fivehexbytes): + res = {'mcc': 0, 'mnc': 0, 'act': []} + plmn_chars = 6 + act_chars = 4 + plmn_str = fivehexbytes[:plmn_chars] # first three bytes (six ascii hex chars) + act_str = fivehexbytes[plmn_chars:plmn_chars + act_chars] # two bytes after first three bytes + res['mcc'] = dec_mcc_from_plmn(plmn_str) + res['mnc'] = dec_mnc_from_plmn(plmn_str) + res['act'] = dec_act(act_str) + return res + +def format_xplmn_w_act(hexstr): + s = "" + for rec_data in hexstr_to_fivebytearr(hexstr): + rec_info = dec_xplmn_w_act(rec_data) + if rec_info['mcc'] == 0xFFF and rec_info['mnc'] == 0xFFF: + rec_str = "unused" + else: + rec_str = "MCC: %3s MNC: %3s AcT: %s" % (rec_info['mcc'], rec_info['mnc'], ", ".join(rec_info['act'])) + s += "%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 -- 2.19.2
