Skip to content

Commit

Permalink
utils: add EF [H|O]PLMNwAcT decoding.
Browse files Browse the repository at this point in the history
Allow decoding and pretty printing of PLMNwAcT, HPLMNwAcT and OPLMNwAct.

Includes unit tests for the added functions.

Change-Id: I9b8ca6ffd98f665690b84239d9a228e2c72c6ff9
  • Loading branch information
lazlo authored and laf0rge committed May 10, 2019
1 parent 91d4ec7 commit 851e9c0
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 7 deletions.
8 changes: 4 additions & 4 deletions pySim-read.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
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():
Expand Down Expand Up @@ -129,7 +129,7 @@ def parse_options():
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:
Expand All @@ -139,7 +139,7 @@ def parse_options():
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:
Expand All @@ -149,7 +149,7 @@ def parse_options():
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:
Expand Down
73 changes: 73 additions & 0 deletions pySim/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 += "\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
Expand Down
76 changes: 76 additions & 0 deletions pySim/utils_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/pyton

import unittest
import utils

class DecTestCase(unittest.TestCase):

def testSplitHexStringToListOf5ByteEntries(self):
input_str = "ffffff0003ffffff0002ffffff0001"
expected = [
"ffffff0003",
"ffffff0002",
"ffffff0001",
]
self.assertEqual(utils.hexstr_to_fivebytearr(input_str), expected)

def testDecMCCfromPLMN(self):
self.assertEqual(utils.dec_mcc_from_plmn("92f501"), 295)

def testDecMCCfromPLMN_unused(self):
self.assertEqual(utils.dec_mcc_from_plmn("ff0f00"), 4095)

def testDecMNCfromPLMN_twoDigitMNC(self):
self.assertEqual(utils.dec_mnc_from_plmn("92f501"), 10)

def testDecMNCfromPLMN_threeDigitMNC(self):
self.assertEqual(utils.dec_mnc_from_plmn("031263"), 361)

def testDecMNCfromPLMN_unused(self):
self.assertEqual(utils.dec_mnc_from_plmn("00f0ff"), 4095)

def testDecAct_noneSet(self):
self.assertEqual(utils.dec_act("0000"), [])

def testDecAct_onlyUtran(self):
self.assertEqual(utils.dec_act("8000"), ["UTRAN"])

def testDecAct_onlyEUtran(self):
self.assertEqual(utils.dec_act("4000"), ["E-UTRAN"])

def testDecAct_onlyGsm(self):
self.assertEqual(utils.dec_act("0080"), ["GSM"])

def testDecAct_onlyGsmCompact(self):
self.assertEqual(utils.dec_act("0040"), ["GSM COMPACT"])

def testDecAct_onlyCdma2000HRPD(self):
self.assertEqual(utils.dec_act("0020"), ["cdma2000 HRPD"])

def testDecAct_onlyCdma20001xRTT(self):
self.assertEqual(utils.dec_act("0010"), ["cdma2000 1xRTT"])

def testDecAct_allSet(self):
self.assertEqual(utils.dec_act("ffff"), ["UTRAN", "E-UTRAN", "GSM", "GSM COMPACT", "cdma2000 HRPD", "cdma2000 1xRTT"])

def testDecxPlmn_w_act(self):
expected = {'mcc': 295, 'mnc': 10, 'act': ["UTRAN"]}
self.assertEqual(utils.dec_xplmn_w_act("92f5018000"), expected)

def testFormatxPlmn_w_act(self):
input_str = "92f501800092f5508000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000"
expected = '''92f5018000 # MCC: 295 MNC: 10 AcT: UTRAN
92f5508000 # MCC: 295 MNC: 5 AcT: UTRAN
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
'''
self.assertEqual(utils.format_xplmn_w_act(input_str), expected)

if __name__ == "__main__":
unittest.main()
45 changes: 42 additions & 3 deletions pysim-testdata/sysmoUSIM-SJS1.ok
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,48 @@ ICCID: 1122334455667788990
IMSI: 001010000000102
SMSP: ffffffffffffffffffffffffffffffffffffffffffffffffe1ffffffffffffffffffffffff0581005155f5ffffffffffff000000
PLMNsel: fff11fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PLMNwAcT: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
OPLMNwAcT: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
HPLMNAcT: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PLMNwAcT:
fff11fffff # MCC: 1651 MNC: 151 AcT: UTRAN, E-UTRAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused

OPLMNwAcT:
fff11fffff # MCC: 1651 MNC: 151 AcT: UTRAN, E-UTRAN, GSM, GSM COMPACT, cdma2000 HRPD, cdma2000 1xRTT
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused
ffffff0000 # unused

HPLMNAcT:
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused
ffffffffff # unused

ACC: 0008
MSISDN: Not available
AD: 00000002
Expand Down

0 comments on commit 851e9c0

Please sign in to comment.