Change in pysim[master]: utils: fix encoding of EF.MSISDN

dexter gerrit-no-reply at lists.osmocom.org
Tue Apr 20 21:27:16 UTC 2021


dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/23819 )


Change subject: utils: fix encoding of EF.MSISDN
......................................................................

utils: fix encoding of EF.MSISDN

The encoding of EF.MSISDN is a bit unstrutured. The encoder function
does not return a valid result since it lacks the parameters
Capability/Configuration2 Record Identifier and Extension5 Record
Identifier, which are mandatory but can be set to 0xFF. Also the
encoder gets its input from pySim-shell, so it should have some
more input validation, especially when the user encodes an empty
string. The encoder and decoder function also do not have unit-tests.

Since the encoder now adds the missing two bytes by isself this does
not have to be done manually anymore, so cards.py needs to be
re-aligned.

For pySim-shell.py the encoder is used from ts_51_011.py. Unfortunately
it is used wrongly there. The optional Alpha Identifier is required
here as well.

Related: OS#4963
Change-Id: Iee5369b3e3ba7fa1155facc8fa824bc60e33b55b
---
M pySim/cards.py
M pySim/ts_51_011.py
M pySim/utils.py
M tests/test_utils.py
4 files changed, 46 insertions(+), 6 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/19/23819/1

diff --git a/pySim/cards.py b/pySim/cards.py
index 9a19eed..719bf0c 100644
--- a/pySim/cards.py
+++ b/pySim/cards.py
@@ -963,7 +963,7 @@
 		# TODO: Extension1 Record Identifier
 		if p.get('msisdn') is not None:
 			msisdn = enc_msisdn(p['msisdn'])
-			data = 'ff' * 20 + msisdn + 'ff' * 2
+			data = 'ff' * 20 + msisdn
 
 			r = self._scc.select_path(['3f00', '7f10'])
 			data, sw = self._scc.update_record('6F40', 1, data, force_len=True)
@@ -1356,7 +1356,7 @@
 		# TODO: Extension1 Record Identifier
 		if p.get('msisdn') is not None:
 			msisdn = enc_msisdn(p['msisdn'])
-			content = 'ff' * 20 + msisdn + 'ff' * 2
+			content = 'ff' * 20 + msisdn
 
 			r = self._scc.select_path(['3f00', '7f10'])
 			data, sw = self._scc.update_record('6F40', 1, content, force_len=True)
diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py
index 48649cd..9123330 100644
--- a/pySim/ts_51_011.py
+++ b/pySim/ts_51_011.py
@@ -377,11 +377,13 @@
 # TS 51.011 Section 10.5.5
 class EF_MSISDN(LinFixedEF):
     def __init__(self, fid='6f40', sfid=None, name='EF.MSISDN', desc='MSISDN'):
-        super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len={15, None})
+        super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len={15, 34})
     def _decode_record_hex(self, raw_hex_data):
         return {'msisdn': dec_msisdn(raw_hex_data)}
     def _encode_record_hex(self, abstract):
-        return enc_msisdn(abstract['msisdn'])
+        encoded_msisdn = enc_msisdn(abstract['msisdn'])
+        alpha_identifier = (list(self.rec_len)[0] - len(encoded_msisdn) // 2) * "ff"
+        return alpha_identifier + encoded_msisdn
 
 # TS 51.011 Section 10.5.6
 class EF_SMSP(LinFixedEF):
diff --git a/pySim/utils.py b/pySim/utils.py
index a0da03a..e4feac3 100644
--- a/pySim/utils.py
+++ b/pySim/utils.py
@@ -400,18 +400,27 @@
 def enc_msisdn(msisdn:str, npi:int=0x01, ton:int=0x03) -> Hexstr:
 	"""
 	Encode MSISDN as LHV so it can be stored to EF.MSISDN.
-	See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3.
+	See 3GPP TS 31.102, section 4.2.26 and 4.4.2.3. (The result
+	will not contain the optional Alpha Identifier at the beginning.)
 
 	Default NPI / ToN values:
 	  - NPI: ISDN / telephony numbering plan (E.164 / E.163),
 	  - ToN: network specific or international number (if starts with '+').
 	"""
 
+	# If no MSISDN is supplied then encode the file contents as all "ff"
+	if not msisdn or msisdn == "" or msisdn == "+":
+		return "ff" * 14
+
 	# Leading '+' indicates International Number
 	if msisdn[0] == '+':
 		msisdn = msisdn[1:]
 		ton = 0x01
 
+	# Truncate overlong MSISDN
+	if len(msisdn) > 20:
+		msisdn = msisdn[0:20]
+
 	# Append 'f' padding if number of digits is odd
 	if len(msisdn) % 2 > 0:
 		msisdn += 'f'
@@ -421,7 +430,8 @@
 	npi_ton = (npi & 0x0f) | ((ton & 0x07) << 4) | 0x80
 	bcd = rpad(swap_nibbles(msisdn), 10 * 2) # pad to 10 octets
 
-	return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd
+	return ('%02x' % bcd_len) + ('%02x' % npi_ton) + bcd + ("ff" * 2)
+
 
 def dec_st(st, table="sim") -> str:
 	"""
diff --git a/tests/test_utils.py b/tests/test_utils.py
index badde55..c8a5cb0 100755
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -109,5 +109,33 @@
 		encoded = suci_calc_info._encode_hex(self.decoded_testfile_suci)
 		self.assertEqual(encoded.lower(), self.testfile_suci_calc_info.lower())
 
+	def testEnc_msisdn(self):
+		msisdn_encoded = utils.enc_msisdn("+4916012345678", npi=0x01, ton=0x03)
+		self.assertEqual(msisdn_encoded, "0891946110325476f8ffffffffff")
+		msisdn_encoded = utils.enc_msisdn("123456", npi=0x01, ton=0x03)
+		self.assertEqual(msisdn_encoded, "04b1214365ffffffffffffffffff")
+		msisdn_encoded = utils.enc_msisdn("12345678901234567890", npi=0x01, ton=0x03)
+		self.assertEqual(msisdn_encoded, "0bb121436587092143658709ffff")
+		msisdn_encoded = utils.enc_msisdn("", npi=0x01, ton=0x03)
+		self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")
+		msisdn_encoded = utils.enc_msisdn("+", npi=0x01, ton=0x03)
+		self.assertEqual(msisdn_encoded, "ffffffffffffffffffffffffffff")
+		msisdn_encoded = utils.enc_msisdn("1234567890123456789012345678901234567890", npi=0x01, ton=0x03)
+		self.assertEqual(msisdn_encoded, "0bb121436587092143658709ffff")
+
+	def testDec_msisdn(self):
+		msisdn_decoded = utils.dec_msisdn("0891946110325476f8ffffffffff")
+		self.assertEqual(msisdn_decoded, (1, 1, "+4916012345678"))
+		msisdn_decoded = utils.dec_msisdn("04b1214365ffffffffffffffffff")
+		self.assertEqual(msisdn_decoded, (1, 3, "123456"))
+		msisdn_decoded = utils.dec_msisdn("0bb121436587092143658709ffff")
+		self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
+		msisdn_decoded = utils.dec_msisdn("ffffffffffffffffffffffffffff")
+		self.assertEqual(msisdn_decoded, None)
+		msisdn_decoded = utils.dec_msisdn("00112233445566778899AABBCCDDEEFF001122330bb121436587092143658709ffff")
+		self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
+		msisdn_decoded = utils.dec_msisdn("ffffffffffffffffffffffffffffffffffffffff0bb121436587092143658709ffff")
+		self.assertEqual(msisdn_decoded, (1, 3, "12345678901234567890"))
+
 if __name__ == "__main__":
 	unittest.main()

-- 
To view, visit https://gerrit.osmocom.org/c/pysim/+/23819
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Iee5369b3e3ba7fa1155facc8fa824bc60e33b55b
Gerrit-Change-Number: 23819
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210420/8ed573aa/attachment-0001.htm>


More information about the gerrit-log mailing list