Change in pysim[master]: utils: fix encoding/decoding of IMSI value

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Wed Sep 26 17:38:10 UTC 2018


Harald Welte has submitted this change and it was merged. ( https://gerrit.osmocom.org/11073 )

Change subject: utils: fix encoding/decoding of IMSI value
......................................................................

utils: fix encoding/decoding of IMSI value

When programming or reading a SIM with an IMSI shorter than 15, the IMSI
value is incorrectly encoded/decoded.

The code pads the the IMSI value with 0xF from the left but padding from
the right would be correct.

It also encodes the length as half the number of digits in the IMSI
(rounded up). This isn't correct for even length IMSIs. With even length
IMSIs, the odd/even parity bit bumps the last digit into an extra byte,
which should be counted as well.

- Fix endcoding of IMSI value
- Fix decoding of IMSI value

Change-Id: I9ae4ca4eb7c2965e601a7108843d052ff613beb9
Patch-by: Ben Foxmoore
Closes: SYS#3552
---
M pySim/utils.py
1 file changed, 26 insertions(+), 6 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/pySim/utils.py b/pySim/utils.py
index 17dc693..ba94702 100644
--- a/pySim/utils.py
+++ b/pySim/utils.py
@@ -49,11 +49,29 @@
 def lpad(s, l, c='f'):
 	return c * (l - len(s)) + s
 
+def half_round_up(n):
+	return (n + 1)//2
+
+# IMSI encoded format:
+# For IMSI 0123456789ABCDE:
+#
+# |     byte 1      | 2 upper | 2 lower  | 3 upper | 3 lower | ... | 9 upper | 9 lower |
+# | length in bytes |    0    | odd/even |    2    |    1    | ... |    E    |    D    |
+#
+# If the IMSI is less than 15 characters, it should be padded with 'f' from the end.
+#
+# The length is the total number of bytes used to encoded the IMSI. This includes the odd/even
+# parity bit. E.g. an IMSI of length 14 is 8 bytes long, not 7, as it uses bytes 2 to 9 to
+# encode itself.
+#
+# Because of this, an odd length IMSI fits exactly into len(imsi) + 1 // 2 bytes, whereas an
+# even length IMSI only uses half of the last byte.
+
 def enc_imsi(imsi):
 	"""Converts a string imsi into the value of the EF"""
-	l = (len(imsi) + 1) // 2	# Required bytes
+	l = half_round_up(len(imsi) + 1)	# Required bytes - include space for odd/even indicator
 	oe = len(imsi) & 1			# Odd (1) / Even (0)
-	ei = '%02x' % l + swap_nibbles(lpad('%01x%s' % ((oe<<3)|1, imsi), 16))
+	ei = '%02x' % l + swap_nibbles('%01x%s' % ((oe<<3)|1, rpad(imsi, 15)))
 	return ei
 
 def dec_imsi(ef):
@@ -61,13 +79,15 @@
 	if len(ef) < 4:
 		return None
 	l = int(ef[0:2], 16) * 2		# Length of the IMSI string
-	swapped = swap_nibbles(ef[2:])
+	l = l - 1						# Encoded length byte includes oe nibble
+	swapped = swap_nibbles(ef[2:]).rstrip('f')
 	oe = (int(swapped[0])>>3) & 1	# Odd (1) / Even (0)
-	if oe:
+	if not oe:
+		# if even, only half of last byte was used
 		l = l-1
-	if l+1 > len(swapped):
+	if l != len(swapped) - 1:
 		return None
-	imsi = swapped[1:l+2]
+	imsi = swapped[1:]
 	return imsi
 
 def dec_iccid(ef):

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

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I9ae4ca4eb7c2965e601a7108843d052ff613beb9
Gerrit-Change-Number: 11073
Gerrit-PatchSet: 2
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder (1000002)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180926/a72a1937/attachment.htm>


More information about the gerrit-log mailing list