<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/pysim/+/24449">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">utils: Add 'raw' version of TLV tag decoders<br><br>The existing {comprehension,ber}tlv_parse_tag() functions are<br>decoding the tag to a high level of detail.  However, all the 3GPP<br>specs seem to deal with the 'raw' version, i.e something like<br>0xD1 as a single-byte tag with the class + constructed fields already<br>shifted next to the actual tag value.<br><br>Let's accommodate that with new *_parse_tag_raw() functions.<br><br>Change-Id: Ib50946bfb3b3ecd7942c423ac0f98b6c07649224<br>---<br>M pySim/utils.py<br>1 file changed, 52 insertions(+), 0 deletions(-)<br><br></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 d96d05a..74655d4 100644</span><br><span>--- a/pySim/utils.py</span><br><span>+++ b/pySim/utils.py</span><br><span>@@ -93,6 +93,21 @@</span><br><span> # poor man's COMPREHENSION-TLV decoder.</span><br><span> #########################################################################</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def comprehensiontlv_parse_tag_raw(binary:bytes) -> Tuple[int, bytes]:</span><br><span style="color: hsl(120, 100%, 40%);">+    """Parse a single Tag according to ETSI TS 101 220 Section 7.1.1"""</span><br><span style="color: hsl(120, 100%, 40%);">+    if binary[0] in [0x00, 0x80, 0xff]:</span><br><span style="color: hsl(120, 100%, 40%);">+        raise ValueError("Found illegal value 0x%02x in %s" % (binary[0], binary))</span><br><span style="color: hsl(120, 100%, 40%);">+    if binary[0] == 0x7f:</span><br><span style="color: hsl(120, 100%, 40%);">+        # three-byte tag</span><br><span style="color: hsl(120, 100%, 40%);">+        tag = binary[0] << 16 | binary[1] << 8 | binary[2]</span><br><span style="color: hsl(120, 100%, 40%);">+        return (tag, binary[3:])</span><br><span style="color: hsl(120, 100%, 40%);">+    elif binary[0] == 0xff:</span><br><span style="color: hsl(120, 100%, 40%);">+        return None, binary</span><br><span style="color: hsl(120, 100%, 40%);">+    else:</span><br><span style="color: hsl(120, 100%, 40%);">+        # single byte tag</span><br><span style="color: hsl(120, 100%, 40%);">+        tag = binary[0]</span><br><span style="color: hsl(120, 100%, 40%);">+        return (tag, binary[1:])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def comprehensiontlv_parse_tag(binary:bytes) -> Tuple[dict, bytes]:</span><br><span>     """Parse a single Tag according to ETSI TS 101 220 Section 7.1.1"""</span><br><span>     if binary[0] in [0x00, 0x80, 0xff]:</span><br><span>@@ -132,11 +147,48 @@</span><br><span> </span><br><span> # length value coding is equal to BER-TLV</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def comprehensiontlv_parse_one(binary:bytes) -> (dict, int, bytes, bytes):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Parse a single TLV IE at the start of the given binary data.</span><br><span style="color: hsl(120, 100%, 40%);">+        Args:</span><br><span style="color: hsl(120, 100%, 40%);">+         binary : binary input data of BER-TLV length field</span><br><span style="color: hsl(120, 100%, 40%);">+    Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+              Tuple of (tag:dict, len:int, remainder:bytes)</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+    (tagdict, remainder) = comprehensiontlv_parse_tag(binary)</span><br><span style="color: hsl(120, 100%, 40%);">+     (length, remainder) = bertlv_parse_len(remainder)</span><br><span style="color: hsl(120, 100%, 40%);">+     value = remainder[:length]</span><br><span style="color: hsl(120, 100%, 40%);">+    remainder = remainder[length:]</span><br><span style="color: hsl(120, 100%, 40%);">+        return (tagdict, length, value, remainder)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> #########################################################################</span><br><span> # poor man's BER-TLV decoder. To be a more sophisticated OO library later</span><br><span> #########################################################################</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def bertlv_parse_tag_raw(binary:bytes) -> Tuple[int, bytes]:</span><br><span style="color: hsl(120, 100%, 40%);">+    """Get a single raw Tag from start of input according to ITU-T X.690 8.1.2</span><br><span style="color: hsl(120, 100%, 40%);">+     Args:</span><br><span style="color: hsl(120, 100%, 40%);">+         binary : binary input data of BER-TLV length field</span><br><span style="color: hsl(120, 100%, 40%);">+    Returns:</span><br><span style="color: hsl(120, 100%, 40%);">+        Tuple of (tag:int, remainder:bytes)</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+    if binary[0] == 0xff:</span><br><span style="color: hsl(120, 100%, 40%);">+         return None, binary</span><br><span style="color: hsl(120, 100%, 40%);">+   tag = binary[0] & 0x1f</span><br><span style="color: hsl(120, 100%, 40%);">+    if tag <= 30:</span><br><span style="color: hsl(120, 100%, 40%);">+              return binary[0], binary[1:]</span><br><span style="color: hsl(120, 100%, 40%);">+  else: # multi-byte tag</span><br><span style="color: hsl(120, 100%, 40%);">+                tag = binary[0]</span><br><span style="color: hsl(120, 100%, 40%);">+               i = 1</span><br><span style="color: hsl(120, 100%, 40%);">+         last = False</span><br><span style="color: hsl(120, 100%, 40%);">+          while not last:</span><br><span style="color: hsl(120, 100%, 40%);">+                       last = False if binary[i] & 0x80 else True</span><br><span style="color: hsl(120, 100%, 40%);">+                        tag <<= 8</span><br><span style="color: hsl(120, 100%, 40%);">+                       tag |= binary[i]</span><br><span style="color: hsl(120, 100%, 40%);">+                      i += 1</span><br><span style="color: hsl(120, 100%, 40%);">+                return tag, binary[i:]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def bertlv_parse_tag(binary:bytes) -> Tuple[dict, bytes]:</span><br><span>     """Parse a single Tag value according to ITU-T X.690 8.1.2</span><br><span>    Args:</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/pysim/+/24449">change 24449</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/+/24449"/><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: Ib50946bfb3b3ecd7942c423ac0f98b6c07649224 </div>
<div style="display:none"> Gerrit-Change-Number: 24449 </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-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>