<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/pysim/+/18649">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add support for ADF_USIM/EF_EHPLMN<br><br>If the EF.EHPLMN exists, it contains the "Equivalent Home PLMN List".<br>The odd part of that list is that it is not just a list of additional<br>PLMN identities, but if the first digits of the IMSI are *not* listed<br>in EF.EHPLMN, then the MCC/MNC of the IMSI prefix is suddently no<br>longer considered the home network, but the subscriber is roaming.<br><br>See TS 23.122: "If the HPLMN code derived from the IMSI is not present<br>in the EHPLMN list, then it shall be treated as a Visited PLMN for PLMN<br>selection purposes."<br><br>Change-Id: I22d96ab4a424ec5bc1fb02f5e80165c646a748d3<br>---<br>M pySim-read.py<br>M pySim/cards.py<br>M pySim/utils.py<br>3 files changed, 51 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/49/18649/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 b23e6ee..92fbd7b 100755</span><br><span>--- a/pySim-read.py</span><br><span>+++ b/pySim-read.py</span><br><span>@@ -241,6 +241,15 @@</span><br><span>       # Check whether we have th AID of USIM, if so select it by its AID</span><br><span>   # EF.UST - File Id in ADF USIM : 6f38</span><br><span>        if '9000' == card.select_adf_by_aid():</span><br><span style="color: hsl(120, 100%, 40%);">+                # EF.EHPLMN</span><br><span style="color: hsl(120, 100%, 40%);">+           try:</span><br><span style="color: hsl(120, 100%, 40%);">+                  (res, sw) = card.read_ehplmn()</span><br><span style="color: hsl(120, 100%, 40%);">+                        if sw == '9000':</span><br><span style="color: hsl(120, 100%, 40%);">+                              print("EHPLMN:\n%s" % (res))</span><br><span style="color: hsl(120, 100%, 40%);">+                        else:</span><br><span style="color: hsl(120, 100%, 40%);">+                         print("EHPLMN: Can't read, response code = %s" % (sw,))</span><br><span style="color: hsl(120, 100%, 40%);">+         except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+                        print("EHPLMN: Can't read file -- " + str(e))</span><br><span>          # EF.UST</span><br><span>             (res, sw) = card.read_binary(EF_USIM_ADF_map['UST'])</span><br><span>                 if sw == '9000':</span><br><span>diff --git a/pySim/cards.py b/pySim/cards.py</span><br><span>index 808fde1..302c886 100644</span><br><span>--- a/pySim/cards.py</span><br><span>+++ b/pySim/cards.py</span><br><span>@@ -24,6 +24,7 @@</span><br><span> #</span><br><span> </span><br><span> from pySim.ts_51_011 import EF, DF</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.ts_31_102 import EF_USIM_ADF_map</span><br><span> from pySim.utils import *</span><br><span> from smartcard.util import toBytes</span><br><span> </span><br><span>@@ -77,6 +78,20 @@</span><br><span>            else:</span><br><span>                        return (None, sw)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ def read_ehplmn(self):</span><br><span style="color: hsl(120, 100%, 40%);">+                (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'])</span><br><span style="color: hsl(120, 100%, 40%);">+          if sw == '9000':</span><br><span style="color: hsl(120, 100%, 40%);">+                      return (format_xplmn(res), sw)</span><br><span style="color: hsl(120, 100%, 40%);">+                else:</span><br><span style="color: hsl(120, 100%, 40%);">+                 return (None, sw)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   def update_ehplmn(self, mcc, mnc):</span><br><span style="color: hsl(120, 100%, 40%);">+            data = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'], length=None, offset=0)</span><br><span style="color: hsl(120, 100%, 40%);">+                size = len(data[0]) // 2</span><br><span style="color: hsl(120, 100%, 40%);">+              ehplmn = enc_plmn(mcc, mnc)</span><br><span style="color: hsl(120, 100%, 40%);">+           data, sw = self._scc.update_binary(EF_USIM_ADF_map['EHPLMN'], ehplmn)</span><br><span style="color: hsl(120, 100%, 40%);">+         return sw</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  def update_hplmn_act(self, mcc, mnc, access_tech='FFFF'):</span><br><span>            """</span><br><span>           Update Home PLMN with access technology bit-field</span><br><span>@@ -1144,16 +1159,20 @@</span><br><span>                  if p.get('opc'):</span><br><span>                             self._scc.update_binary('af20', p['opc'], 17)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-               # update EF-USIM_AUTH_KEY in ADF.USIM</span><br><span>                self._scc.select_file(['3f00'])</span><br><span>              aid = self.read_aid()</span><br><span>                if (aid):</span><br><span style="color: hsl(120, 100%, 40%);">+                     # update EF-USIM_AUTH_KEY in ADF.USIM</span><br><span>                        self._scc.select_adf(aid)</span><br><span>                    if p.get('ki'):</span><br><span>                              self._scc.update_binary('af20', p['ki'], 1)</span><br><span>                  if p.get('opc'):</span><br><span>                             self._scc.update_binary('af20', p['opc'], 17)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+                     # update EF.EHPLMN in ADF.USIM</span><br><span style="color: hsl(120, 100%, 40%);">+                        if p.get('mcc') and p.get('mnc'):</span><br><span style="color: hsl(120, 100%, 40%);">+                             sw = self.update_ehplmn(p['mcc'], p['mnc'])</span><br><span style="color: hsl(120, 100%, 40%);">+                           # igoring any error as the file may not be present depending on the profile.</span><br><span>                 return</span><br><span> </span><br><span> </span><br><span>diff --git a/pySim/utils.py b/pySim/utils.py</span><br><span>index 496b918..d7ff617 100644</span><br><span>--- a/pySim/utils.py</span><br><span>+++ b/pySim/utils.py</span><br><span>@@ -125,6 +125,9 @@</span><br><span> def hexstr_to_fivebytearr(s):</span><br><span>   return [s[i:i+10] for i in range(0, len(s), 10) ]</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def hexstr_to_threebytearr(s):</span><br><span style="color: hsl(120, 100%, 40%);">+ return [s[i:i+6] for i in range(0, len(s), 6) ]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # Accepts hex string representing three bytes</span><br><span> def dec_mcc_from_plmn(plmn):</span><br><span>   ia = h2i(plmn)</span><br><span>@@ -183,6 +186,25 @@</span><br><span>                s += "\t%s # %s\n" % (rec_data, rec_str)</span><br><span>   return s</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def dec_xplmn(threehexbytes):</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%);">+        plmn_str = threehexbytes[:plmn_chars]                           # first three bytes (six ascii hex chars)</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%);">+      return res</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def format_xplmn(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_threebytearr(hexstr):</span><br><span style="color: hsl(120, 100%, 40%);">+               rec_info = dec_xplmn(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: %03d MNC: %03d" % (rec_info['mcc'], rec_info['mnc'])</span><br><span style="color: hsl(120, 100%, 40%);">+                s += "\t%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></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/pysim/+/18649">change 18649</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/c/pysim/+/18649"/><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-Change-Id: I22d96ab4a424ec5bc1fb02f5e80165c646a748d3 </div>
<div style="display:none"> Gerrit-Change-Number: 18649 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>