<p>lazlo has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/12123">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">utils: add EF [H|O]PLMNwAcT decoding.<br><br>Allow decoding and pretty printing of PLMNwAcT, HPLMNwAcT and OPLMNwAct.<br><br>Includes unit tests for the added functions.<br><br>Change-Id: I9b8ca6ffd98f665690b84239d9a228e2c72c6ff9<br>---<br>M pySim-read.py<br>M pySim/utils.py<br>A pySim/utils_test.py<br>3 files changed, 153 insertions(+), 4 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/23/12123/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/pySim-read.py b/pySim-read.py</span><br><span>index 4356453..70d3f14 100755</span><br><span>--- a/pySim-read.py</span><br><span>+++ b/pySim-read.py</span><br><span>@@ -37,7 +37,7 @@</span><br><span>   import simplejson as json</span><br><span> </span><br><span> from pySim.commands import SimCardCommands</span><br><span style="color: hsl(0, 100%, 40%);">-from pySim.utils import h2b, swap_nibbles, rpad, dec_imsi, dec_iccid</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.utils import h2b, swap_nibbles, rpad, dec_imsi, dec_iccid, format_xplmn_w_act</span><br><span> </span><br><span> </span><br><span> def parse_options():</span><br><span>@@ -129,7 +129,7 @@</span><br><span>         try:</span><br><span>              (res, sw) = scc.read_binary(EF['PLMNwAcT'])</span><br><span>          if sw == '9000':</span><br><span style="color: hsl(0, 100%, 40%);">-                        print("PLMNwAcT: %s" % (res))</span><br><span style="color: hsl(120, 100%, 40%);">+                       print("PLMNwAcT: %s" % (format_xplmn_w_act(res)))</span><br><span>          else:</span><br><span>                        print("PLMNwAcT: Can't read, response code = %s" % (sw,))</span><br><span>      except Exception as e:</span><br><span>@@ -139,7 +139,7 @@</span><br><span>         try:</span><br><span>                 (res, sw) = scc.read_binary(EF['OPLMNwAcT'])</span><br><span>                 if sw == '9000':</span><br><span style="color: hsl(0, 100%, 40%);">-                        print("OPLMNwAcT: %s" % (res))</span><br><span style="color: hsl(120, 100%, 40%);">+                      print("OPLMNwAcT: %s" % (format_xplmn_w_act(res)))</span><br><span>                 else:</span><br><span>                        print("OPLMNwAcT: Can't read, response code = %s" % (sw,))</span><br><span>     except Exception as e:</span><br><span>@@ -149,7 +149,7 @@</span><br><span>         try:</span><br><span>                 (res, sw) = scc.read_binary(EF['HPLMNAcT'])</span><br><span>          if sw == '9000':</span><br><span style="color: hsl(0, 100%, 40%);">-                        print("HPLMNAcT: %s" % (res))</span><br><span style="color: hsl(120, 100%, 40%);">+                       print("HPLMNAcT: %s" % (format_xplmn_w_act(res)))</span><br><span>          else:</span><br><span>                        print("HPLMNAcT: Can't read, response code = %s" % (sw,))</span><br><span>      except Exception as e:</span><br><span>diff --git a/pySim/utils.py b/pySim/utils.py</span><br><span>index ba94702..3ea543f 100644</span><br><span>--- a/pySim/utils.py</span><br><span>+++ b/pySim/utils.py</span><br><span>@@ -113,6 +113,79 @@</span><br><span>   if oplmn_disp: byte1 = byte1|0x02</span><br><span>    return i2h([byte1])+s2h(name)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def hexstr_to_fivebytearr(s):</span><br><span style="color: hsl(120, 100%, 40%);">+      return [s[i:i+10] for i in range(0, len(s), 10) ]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# Accepts hex string representing three bytes</span><br><span style="color: hsl(120, 100%, 40%);">+def dec_mcc_from_plmn(plmn):</span><br><span style="color: hsl(120, 100%, 40%);">+      ia = h2i(plmn)</span><br><span style="color: hsl(120, 100%, 40%);">+        digit1 = ia[0] & 0x0F               # 1st byte, LSB</span><br><span style="color: hsl(120, 100%, 40%);">+       digit2 = (ia[0] & 0xF0) >> 4  # 1st byte, MSB</span><br><span style="color: hsl(120, 100%, 40%);">+       digit3 = ia[1] & 0x0F               # 2nd byte, LSB</span><br><span style="color: hsl(120, 100%, 40%);">+       if digit3 == 0xF and digit2 == 0xF and digit1 == 0xF:</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0xFFF # 4095</span><br><span style="color: hsl(120, 100%, 40%);">+   mcc = digit1 * 100</span><br><span style="color: hsl(120, 100%, 40%);">+    mcc += digit2 * 10</span><br><span style="color: hsl(120, 100%, 40%);">+    mcc += digit3</span><br><span style="color: hsl(120, 100%, 40%);">+ return mcc</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def dec_mnc_from_plmn(plmn):</span><br><span style="color: hsl(120, 100%, 40%);">+    ia = h2i(plmn)</span><br><span style="color: hsl(120, 100%, 40%);">+        digit1 = ia[2] & 0x0F               # 3rd byte, LSB</span><br><span style="color: hsl(120, 100%, 40%);">+       digit2 = (ia[2] & 0xF0) >> 4  # 3rd byte, MSB</span><br><span style="color: hsl(120, 100%, 40%);">+       digit3 = (ia[1] & 0xF0) >> 4  # 2nd byte, MSB</span><br><span style="color: hsl(120, 100%, 40%);">+       if digit3 == 0xF and digit2 == 0xF and digit1 == 0xF:</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0xFFF # 4095</span><br><span style="color: hsl(120, 100%, 40%);">+   mnc = 0</span><br><span style="color: hsl(120, 100%, 40%);">+       # signifies two digit MNC</span><br><span style="color: hsl(120, 100%, 40%);">+     if digit3 == 0xF:</span><br><span style="color: hsl(120, 100%, 40%);">+             mnc += digit1 * 10</span><br><span style="color: hsl(120, 100%, 40%);">+            mnc += digit2</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+         mnc += digit1 * 100</span><br><span style="color: hsl(120, 100%, 40%);">+           mnc += digit2 * 10</span><br><span style="color: hsl(120, 100%, 40%);">+            mnc += digit3</span><br><span style="color: hsl(120, 100%, 40%);">+ return mnc</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def dec_act(twohexbytes):</span><br><span style="color: hsl(120, 100%, 40%);">+       act_list = [</span><br><span style="color: hsl(120, 100%, 40%);">+          {'bit': 15, 'name': "UTRAN"},</span><br><span style="color: hsl(120, 100%, 40%);">+               {'bit': 14, 'name': "E-UTRAN"},</span><br><span style="color: hsl(120, 100%, 40%);">+             {'bit':  7, 'name': "GSM"},</span><br><span style="color: hsl(120, 100%, 40%);">+         {'bit':  6, 'name': "GSM COMPACT"},</span><br><span style="color: hsl(120, 100%, 40%);">+         {'bit':  5, 'name': "cdma2000 HRPD"},</span><br><span style="color: hsl(120, 100%, 40%);">+               {'bit':  4, 'name': "cdma2000 1xRTT"},</span><br><span style="color: hsl(120, 100%, 40%);">+      ]</span><br><span style="color: hsl(120, 100%, 40%);">+     ia = h2i(twohexbytes)</span><br><span style="color: hsl(120, 100%, 40%);">+ u16t = (ia[0] << 8)|ia[1]</span><br><span style="color: hsl(120, 100%, 40%);">+       sel = []</span><br><span style="color: hsl(120, 100%, 40%);">+      for a in act_list:</span><br><span style="color: hsl(120, 100%, 40%);">+            if u16t & (1 << a['bit']):</span><br><span style="color: hsl(120, 100%, 40%);">+                  sel.append(a['name'])</span><br><span style="color: hsl(120, 100%, 40%);">+ return sel</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def dec_xplmn_w_act(fivehexbytes):</span><br><span style="color: hsl(120, 100%, 40%);">+      res = {'mcc': 0, 'mnc': 0, 'act': []}</span><br><span style="color: hsl(120, 100%, 40%);">+ plmn_chars = 6</span><br><span style="color: hsl(120, 100%, 40%);">+        act_chars = 4</span><br><span style="color: hsl(120, 100%, 40%);">+ plmn_str = fivehexbytes[:plmn_chars]                            # first three bytes (six ascii hex chars)</span><br><span style="color: hsl(120, 100%, 40%);">+     act_str = fivehexbytes[plmn_chars:plmn_chars + act_chars]       # two bytes after first three bytes</span><br><span style="color: hsl(120, 100%, 40%);">+   res['mcc'] = dec_mcc_from_plmn(plmn_str)</span><br><span style="color: hsl(120, 100%, 40%);">+      res['mnc'] = dec_mnc_from_plmn(plmn_str)</span><br><span style="color: hsl(120, 100%, 40%);">+      res['act'] = dec_act(act_str)</span><br><span style="color: hsl(120, 100%, 40%);">+ return res</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def format_xplmn_w_act(hexstr):</span><br><span style="color: hsl(120, 100%, 40%);">+ s = ""</span><br><span style="color: hsl(120, 100%, 40%);">+      for rec_data in hexstr_to_fivebytearr(hexstr):</span><br><span style="color: hsl(120, 100%, 40%);">+                rec_info = dec_xplmn_w_act(rec_data)</span><br><span style="color: hsl(120, 100%, 40%);">+          if rec_info['mcc'] == 0xFFF and rec_info['mnc'] == 0xFFF:</span><br><span style="color: hsl(120, 100%, 40%);">+                     rec_str = "unused"</span><br><span style="color: hsl(120, 100%, 40%);">+          else:</span><br><span style="color: hsl(120, 100%, 40%);">+                 rec_str = "MCC: %3s MNC: %3s AcT: %s" % (rec_info['mcc'], rec_info['mnc'], ", ".join(rec_info['act']))</span><br><span style="color: hsl(120, 100%, 40%);">+            s += "%s # %s\n" % (rec_data, rec_str)</span><br><span style="color: hsl(120, 100%, 40%);">+      return s</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def derive_milenage_opc(ki_hex, op_hex):</span><br><span>       """</span><br><span>   Run the milenage algorithm to calculate OPC from Ki and OP</span><br><span>diff --git a/pySim/utils_test.py b/pySim/utils_test.py</span><br><span>new file mode 100644</span><br><span>index 0000000..ff028da</span><br><span>--- /dev/null</span><br><span>+++ b/pySim/utils_test.py</span><br><span>@@ -0,0 +1,76 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/pyton</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+import utils </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class DecTestCase(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     def testSplitHexStringToListOf5ByteEntries(self):</span><br><span style="color: hsl(120, 100%, 40%);">+             input_str = "ffffff0003ffffff0002ffffff0001"</span><br><span style="color: hsl(120, 100%, 40%);">+                expected = [</span><br><span style="color: hsl(120, 100%, 40%);">+                  "ffffff0003",</span><br><span style="color: hsl(120, 100%, 40%);">+                       "ffffff0002",</span><br><span style="color: hsl(120, 100%, 40%);">+                       "ffffff0001",</span><br><span style="color: hsl(120, 100%, 40%);">+               ]</span><br><span style="color: hsl(120, 100%, 40%);">+             self.assertEqual(utils.hexstr_to_fivebytearr(input_str), expected)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  def testDecMCCfromPLMN(self):</span><br><span style="color: hsl(120, 100%, 40%);">+         self.assertEqual(utils.dec_mcc_from_plmn("92f501"), 295)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  def testDecMCCfromPLMN_unused(self):</span><br><span style="color: hsl(120, 100%, 40%);">+          self.assertEqual(utils.dec_mcc_from_plmn("ff0f00"), 4095)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def testDecMNCfromPLMN_twoDigitMNC(self):</span><br><span style="color: hsl(120, 100%, 40%);">+             self.assertEqual(utils.dec_mnc_from_plmn("92f501"), 10)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   def testDecMNCfromPLMN_threeDigitMNC(self):</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(utils.dec_mnc_from_plmn("031263"), 361)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  def testDecMNCfromPLMN_unused(self):</span><br><span style="color: hsl(120, 100%, 40%);">+          self.assertEqual(utils.dec_mnc_from_plmn("00f0ff"), 4095)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def testDecAct_noneSet(self):</span><br><span style="color: hsl(120, 100%, 40%);">+         self.assertEqual(utils.dec_act("0000"), [])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       def testDecAct_onlyUtran(self):</span><br><span style="color: hsl(120, 100%, 40%);">+               self.assertEqual(utils.dec_act("8000"), ["UTRAN"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      def testDecAct_onlyEUtran(self):</span><br><span style="color: hsl(120, 100%, 40%);">+              self.assertEqual(utils.dec_act("4000"), ["E-UTRAN"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def testDecAct_onlyGsm(self):</span><br><span style="color: hsl(120, 100%, 40%);">+         self.assertEqual(utils.dec_act("0080"), ["GSM"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        def testDecAct_onlyGsmCompact(self):</span><br><span style="color: hsl(120, 100%, 40%);">+          self.assertEqual(utils.dec_act("0040"), ["GSM COMPACT"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        def testDecAct_onlyCdma2000HRPD(self):</span><br><span style="color: hsl(120, 100%, 40%);">+                self.assertEqual(utils.dec_act("0020"), ["cdma2000 HRPD"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      def testDecAct_onlyCdma20001xRTT(self):</span><br><span style="color: hsl(120, 100%, 40%);">+               self.assertEqual(utils.dec_act("0010"), ["cdma2000 1xRTT"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     def testDecAct_allSet(self):</span><br><span style="color: hsl(120, 100%, 40%);">+          self.assertEqual(utils.dec_act("ffff"), ["UTRAN", "E-UTRAN", "GSM", "GSM COMPACT", "cdma2000 HRPD", "cdma2000 1xRTT"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        def testDecxPlmn_w_act(self):</span><br><span style="color: hsl(120, 100%, 40%);">+         expected = {'mcc': 295, 'mnc': 10, 'act': ["UTRAN"]}</span><br><span style="color: hsl(120, 100%, 40%);">+                self.assertEqual(utils.dec_xplmn_w_act("92f5018000"), expected)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   def testFormatxPlmn_w_act(self):</span><br><span style="color: hsl(120, 100%, 40%);">+              input_str = "92f501800092f5508000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000ffffff0000"</span><br><span style="color: hsl(120, 100%, 40%);">+          expected = '''92f5018000 # MCC: 295 MNC:  10 AcT: UTRAN</span><br><span style="color: hsl(120, 100%, 40%);">+92f5508000 # MCC: 295 MNC:   5 AcT: UTRAN</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+ffffff0000 # unused</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+               self.assertEqual(utils.format_xplmn_w_act(input_str), expected)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+       unittest.main()</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/12123">change 12123</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/12123"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: pysim </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I9b8ca6ffd98f665690b84239d9a228e2c72c6ff9 </div>
<div style="display:none"> Gerrit-Change-Number: 12123 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: lazlo <dlsitzer@gmail.com> </div>