<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/pysim/+/23819">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">utils: fix encoding of EF.MSISDN<br><br>The encoding of EF.MSISDN is a bit unstrutured. The encoder function<br>does not return a valid result since it lacks the parameters<br>Capability/Configuration2 Record Identifier and Extension5 Record<br>Identifier, which are mandatory but can be set to 0xFF. Also the<br>encoder gets its input from pySim-shell, so it should have some<br>more input validation, especially when the user encodes an empty<br>string. The encoder and decoder function also do not have unit-tests.<br><br>Since the encoder now adds the missing two bytes by isself this does<br>not have to be done manually anymore, so cards.py needs to be<br>re-aligned.<br><br>For pySim-shell.py the encoder is used from ts_51_011.py. Unfortunately<br>it is used wrongly there. The optional Alpha Identifier is required<br>here as well.<br><br>Related: OS#4963<br>Change-Id: Iee5369b3e3ba7fa1155facc8fa824bc60e33b55b<br>---<br>M pySim/cards.py<br>M pySim/ts_51_011.py<br>M pySim/utils.py<br>M tests/test_utils.py<br>4 files changed, 46 insertions(+), 6 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/19/23819/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/pySim/cards.py b/pySim/cards.py</span><br><span>index 9a19eed..719bf0c 100644</span><br><span>--- a/pySim/cards.py</span><br><span>+++ b/pySim/cards.py</span><br><span>@@ -963,7 +963,7 @@</span><br><span>           # TODO: Extension1 Record Identifier</span><br><span>                 if p.get('msisdn') is not None:</span><br><span>                      msisdn = enc_msisdn(p['msisdn'])</span><br><span style="color: hsl(0, 100%, 40%);">-                        data = 'ff' * 20 + msisdn + 'ff' * 2</span><br><span style="color: hsl(120, 100%, 40%);">+                  data = 'ff' * 20 + msisdn</span><br><span> </span><br><span>                        r = self._scc.select_path(['3f00', '7f10'])</span><br><span>                  data, sw = self._scc.update_record('6F40', 1, data, force_len=True)</span><br><span>@@ -1356,7 +1356,7 @@</span><br><span>          # TODO: Extension1 Record Identifier</span><br><span>                 if p.get('msisdn') is not None:</span><br><span>                      msisdn = enc_msisdn(p['msisdn'])</span><br><span style="color: hsl(0, 100%, 40%);">-                        content = 'ff' * 20 + msisdn + 'ff' * 2</span><br><span style="color: hsl(120, 100%, 40%);">+                       content = 'ff' * 20 + msisdn</span><br><span> </span><br><span>                     r = self._scc.select_path(['3f00', '7f10'])</span><br><span>                  data, sw = self._scc.update_record('6F40', 1, content, force_len=True)</span><br><span>diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py</span><br><span>index 48649cd..9123330 100644</span><br><span>--- a/pySim/ts_51_011.py</span><br><span>+++ b/pySim/ts_51_011.py</span><br><span>@@ -377,11 +377,13 @@</span><br><span> # TS 51.011 Section 10.5.5</span><br><span> class EF_MSISDN(LinFixedEF):</span><br><span>     def __init__(self, fid='6f40', sfid=None, name='EF.MSISDN', desc='MSISDN'):</span><br><span style="color: hsl(0, 100%, 40%);">-        super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len={15, None})</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len={15, 34})</span><br><span>     def _decode_record_hex(self, raw_hex_data):</span><br><span>         return {'msisdn': dec_msisdn(raw_hex_data)}</span><br><span>     def _encode_record_hex(self, abstract):</span><br><span style="color: hsl(0, 100%, 40%);">-        return enc_msisdn(abstract['msisdn'])</span><br><span style="color: hsl(120, 100%, 40%);">+        encoded_msisdn = enc_msisdn(abstract['msisdn'])</span><br><span style="color: hsl(120, 100%, 40%);">+        alpha_identifier = (list(self.rec_len)[0] - len(encoded_msisdn) // 2) * "ff"</span><br><span style="color: hsl(120, 100%, 40%);">+        return alpha_identifier + encoded_msisdn</span><br><span> </span><br><span> # TS 51.011 Section 10.5.6</span><br><span> class EF_SMSP(LinFixedEF):</span><br><span>diff --git a/pySim/utils.py b/pySim/utils.py</span><br><span>index a0da03a..e4feac3 100644</span><br><span>--- a/pySim/utils.py</span><br><span>+++ b/pySim/utils.py</span><br><span>@@ -400,18 +400,27 @@</span><br><span> def enc_msisdn(msisdn:str, npi:int=0x01, ton:int=0x03) -> Hexstr:</span><br><span>       """</span><br><span>   Encode MSISDN as LHV so it can be stored to EF.MSISDN.</span><br><span style="color: hsl(0, 100%, 40%);">-  See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3.</span><br><span style="color: hsl(120, 100%, 40%);">+       See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3. (The result</span><br><span style="color: hsl(120, 100%, 40%);">+   will not contain the optional Alpha Identifier at the beginning.)</span><br><span> </span><br><span>        Default NPI / ToN values:</span><br><span>      - NPI: ISDN / telephony numbering plan (E.164 / E.163),</span><br><span>      - ToN: network specific or international number (if starts with '+').</span><br><span>      """</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        # If no MSISDN is supplied then encode the file contents as all "ff"</span><br><span style="color: hsl(120, 100%, 40%);">+        if not msisdn or msisdn == "" or msisdn == "+":</span><br><span style="color: hsl(120, 100%, 40%);">+           return "ff" * 14</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         # Leading '+' indicates International Number</span><br><span>         if msisdn[0] == '+':</span><br><span>                 msisdn = msisdn[1:]</span><br><span>          ton = 0x01</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        # Truncate overlong MSISDN</span><br><span style="color: hsl(120, 100%, 40%);">+    if len(msisdn) > 20:</span><br><span style="color: hsl(120, 100%, 40%);">+               msisdn = msisdn[0:20]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      # Append 'f' padding if number of digits is odd</span><br><span>      if len(msisdn) % 2 > 0:</span><br><span>           msisdn += 'f'</span><br><span>@@ -421,7 +430,8 @@</span><br><span>  npi_ton = (npi & 0x0f) | ((ton & 0x07) << 4) | 0x80</span><br><span>    bcd = rpad(swap_nibbles(msisdn), 10 * 2) # pad to 10 octets</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd</span><br><span style="color: hsl(120, 100%, 40%);">+  return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> def dec_st(st, table="sim") -> str:</span><br><span>        """</span><br><span>diff --git a/tests/test_utils.py b/tests/test_utils.py</span><br><span>index badde55..c8a5cb0 100755</span><br><span>--- a/tests/test_utils.py</span><br><span>+++ b/tests/test_utils.py</span><br><span>@@ -109,5 +109,33 @@</span><br><span>           encoded = suci_calc_info._encode_hex(self.decoded_testfile_suci)</span><br><span>             self.assertEqual(encoded.lower(), self.testfile_suci_calc_info.lower())</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   def testEnc_msisdn(self):</span><br><span style="color: hsl(120, 100%, 40%);">+             msisdn_encoded = utils.enc_msisdn("+4916012345678", npi=0x01, ton=0x03)</span><br><span style="color: hsl(120, 100%, 40%);">+             self.assertEqual(msisdn_encoded, "0891946110325476f8ffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_encoded = utils.enc_msisdn("123456", npi=0x01, ton=0x03)</span><br><span style="color: hsl(120, 100%, 40%);">+             self.assertEqual(msisdn_encoded, "04b1214365ffffffffffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_encoded = utils.enc_msisdn("12345678901234567890", npi=0x01, ton=0x03)</span><br><span style="color: hsl(120, 100%, 40%);">+               self.assertEqual(msisdn_encoded, "0bb121436587092143658709ffff")</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_encoded = utils.enc_msisdn("", npi=0x01, ton=0x03)</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_encoded = utils.enc_msisdn("+", npi=0x01, ton=0x03)</span><br><span style="color: hsl(120, 100%, 40%);">+          self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_encoded = utils.enc_msisdn("1234567890123456789012345678901234567890", npi=0x01, ton=0x03)</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_encoded, "0bb121436587092143658709ffff")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  def testDec_msisdn(self):</span><br><span style="color: hsl(120, 100%, 40%);">+             msisdn_decoded = utils.dec_msisdn("0891946110325476f8ffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_decoded, (1, 1, "+4916012345678"))</span><br><span style="color: hsl(120, 100%, 40%);">+          msisdn_decoded = utils.dec_msisdn("04b1214365ffffffffffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_decoded, (1, 3, "123456"))</span><br><span style="color: hsl(120, 100%, 40%);">+          msisdn_decoded = utils.dec_msisdn("0bb121436587092143658709ffff")</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_decoded = utils.dec_msisdn("ffffffffffffffffffffffffffff")</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_decoded, None)</span><br><span style="color: hsl(120, 100%, 40%);">+                msisdn_decoded = utils.dec_msisdn("00112233445566778899AABBCCDDEEFF001122330bb121436587092143658709ffff")</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn_decoded = utils.dec_msisdn("ffffffffffffffffffffffffffffffffffffffff0bb121436587092143658709ffff")</span><br><span style="color: hsl(120, 100%, 40%);">+           self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if __name__ == "__main__":</span><br><span>         unittest.main()</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/pysim/+/23819">change 23819</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/+/23819"/><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: Iee5369b3e3ba7fa1155facc8fa824bc60e33b55b </div>
<div style="display:none"> Gerrit-Change-Number: 23819 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>