<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/11073">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">utils: fix encoding/decoding of IMSI value<br><br>When programming or reading a SIM with an IMSI shorter than 15, the IMSI<br>value is incorrectly encoded/decoded.<br><br>The code pads the the IMSI value with 0xF from the left but padding from<br>the right would be correct.<br><br>It also encodes the length as half the number of digits in the IMSI<br>(rounded up). This isn't correct for even length IMSIs. With even length<br>IMSIs, the odd/even parity bit bumps the last digit into an extra byte,<br>which should be counted as well.<br><br>- Fix endcoding of IMSI value<br>- Fix decoding of IMSI value<br><br>Change-Id: I9ae4ca4eb7c2965e601a7108843d052ff613beb9<br>Patch-by: Ben Foxmoore<br>Closes: SYS#3552<br>---<br>M pySim/utils.py<br>1 file changed, 26 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/73/11073/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/pySim/utils.py b/pySim/utils.py</span><br><span>index 17dc693..ba94702 100644</span><br><span>--- a/pySim/utils.py</span><br><span>+++ b/pySim/utils.py</span><br><span>@@ -49,11 +49,29 @@</span><br><span> def lpad(s, l, c='f'):</span><br><span>      return c * (l - len(s)) + s</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def half_round_up(n):</span><br><span style="color: hsl(120, 100%, 40%);">+        return (n + 1)//2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# IMSI encoded format:</span><br><span style="color: hsl(120, 100%, 40%);">+# For IMSI 0123456789ABCDE:</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# |     byte 1      | 2 upper | 2 lower  | 3 upper | 3 lower | ... | 9 upper | 9 lower |</span><br><span style="color: hsl(120, 100%, 40%);">+# | length in bytes |    0    | odd/even |    2    |    1    | ... |    E    |    D    |</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# If the IMSI is less than 15 characters, it should be padded with 'f' from the end.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# The length is the total number of bytes used to encoded the IMSI. This includes the odd/even</span><br><span style="color: hsl(120, 100%, 40%);">+# parity bit. E.g. an IMSI of length 14 is 8 bytes long, not 7, as it uses bytes 2 to 9 to</span><br><span style="color: hsl(120, 100%, 40%);">+# encode itself.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Because of this, an odd length IMSI fits exactly into len(imsi) + 1 // 2 bytes, whereas an</span><br><span style="color: hsl(120, 100%, 40%);">+# even length IMSI only uses half of the last byte.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def enc_imsi(imsi):</span><br><span>     """Converts a string imsi into the value of the EF"""</span><br><span style="color: hsl(0, 100%, 40%);">-     l = (len(imsi) + 1) // 2        # Required bytes</span><br><span style="color: hsl(120, 100%, 40%);">+      l = half_round_up(len(imsi) + 1)        # Required bytes - include space for odd/even indicator</span><br><span>      oe = len(imsi) & 1                  # Odd (1) / Even (0)</span><br><span style="color: hsl(0, 100%, 40%);">-    ei = '%02x' % l + swap_nibbles(lpad('%01x%s' % ((oe<<3)|1, imsi), 16))</span><br><span style="color: hsl(120, 100%, 40%);">+  ei = '%02x' % l + swap_nibbles('%01x%s' % ((oe<<3)|1, rpad(imsi, 15)))</span><br><span>         return ei</span><br><span> </span><br><span> def dec_imsi(ef):</span><br><span>@@ -61,13 +79,15 @@</span><br><span>     if len(ef) < 4:</span><br><span>           return None</span><br><span>  l = int(ef[0:2], 16) * 2                # Length of the IMSI string</span><br><span style="color: hsl(0, 100%, 40%);">-     swapped = swap_nibbles(ef[2:])</span><br><span style="color: hsl(120, 100%, 40%);">+        l = l - 1                                               # Encoded length byte includes oe nibble</span><br><span style="color: hsl(120, 100%, 40%);">+      swapped = swap_nibbles(ef[2:]).rstrip('f')</span><br><span>   oe = (int(swapped[0])>>3) & 1 # Odd (1) / Even (0)</span><br><span style="color: hsl(0, 100%, 40%);">-    if oe:</span><br><span style="color: hsl(120, 100%, 40%);">+        if not oe:</span><br><span style="color: hsl(120, 100%, 40%);">+            # if even, only half of last byte was used</span><br><span>           l = l-1</span><br><span style="color: hsl(0, 100%, 40%);">- if l+1 > len(swapped):</span><br><span style="color: hsl(120, 100%, 40%);">+     if l != len(swapped) - 1:</span><br><span>            return None</span><br><span style="color: hsl(0, 100%, 40%);">-     imsi = swapped[1:l+2]</span><br><span style="color: hsl(120, 100%, 40%);">+ imsi = swapped[1:]</span><br><span>   return imsi</span><br><span> </span><br><span> def dec_iccid(ef):</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11073">change 11073</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/11073"/><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: I9ae4ca4eb7c2965e601a7108843d052ff613beb9 </div>
<div style="display:none"> Gerrit-Change-Number: 11073 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>