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

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">utils: COMPREHENSION-TLV support<br><br>Change-Id: I8d969382b73fa152ee09c456fa4aee428fb36285<br>---<br>M pySim/utils.py<br>M tests/test_utils.py<br>2 files changed, 66 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 3d96580..d96d05a 100644</span><br><span>--- a/pySim/utils.py</span><br><span>+++ b/pySim/utils.py</span><br><span>@@ -90,6 +90,50 @@</span><br><span>         return (n + 1)//2</span><br><span> </span><br><span> #########################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# poor man's COMPREHENSION-TLV decoder.</span><br><span style="color: hsl(120, 100%, 40%);">+#########################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def comprehensiontlv_parse_tag(binary:bytes) -> Tuple[dict, 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[1] & 0x7f) << 8</span><br><span style="color: hsl(120, 100%, 40%);">+        tag |= binary[2]</span><br><span style="color: hsl(120, 100%, 40%);">+        compr = True if binary[1] & 0x80 else False</span><br><span style="color: hsl(120, 100%, 40%);">+        return ({'comprehension': compr, 'tag': tag}, binary[3:])</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] & 0x7f</span><br><span style="color: hsl(120, 100%, 40%);">+        compr = True if binary[0] & 0x80 else False</span><br><span style="color: hsl(120, 100%, 40%);">+        return ({'comprehension': compr, 'tag': tag}, binary[1:])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def comprehensiontlv_encode_tag(tag) -> bytes:</span><br><span style="color: hsl(120, 100%, 40%);">+    """Encode a single Tag according to ETSI TS 101 220 Section 7.1.1"""</span><br><span style="color: hsl(120, 100%, 40%);">+    # permit caller to specify tag also as integer value</span><br><span style="color: hsl(120, 100%, 40%);">+    if isinstance(tag, int):</span><br><span style="color: hsl(120, 100%, 40%);">+        compr = True if tag < 0xff and tag & 0x80 else False</span><br><span style="color: hsl(120, 100%, 40%);">+        tag = {'tag': tag, 'comprehension': compr}</span><br><span style="color: hsl(120, 100%, 40%);">+    compr = tag.get('comprehension', False)</span><br><span style="color: hsl(120, 100%, 40%);">+    if tag['tag'] in [0x00, 0x80, 0xff] or tag['tag'] > 0xff:</span><br><span style="color: hsl(120, 100%, 40%);">+        # 3-byte format</span><br><span style="color: hsl(120, 100%, 40%);">+        byte3 = tag['tag'] & 0xff;</span><br><span style="color: hsl(120, 100%, 40%);">+        byte2 = (tag['tag'] >> 8) & 0x7f</span><br><span style="color: hsl(120, 100%, 40%);">+        if compr:</span><br><span style="color: hsl(120, 100%, 40%);">+            byte2 |= 0x80</span><br><span style="color: hsl(120, 100%, 40%);">+        return b'\x7f' + byte2.to_bytes(1, 'big') + byte3.to_bytes(1, 'big')</span><br><span style="color: hsl(120, 100%, 40%);">+    else:</span><br><span style="color: hsl(120, 100%, 40%);">+        # 1-byte format</span><br><span style="color: hsl(120, 100%, 40%);">+        ret = tag['tag']</span><br><span style="color: hsl(120, 100%, 40%);">+        if compr:</span><br><span style="color: hsl(120, 100%, 40%);">+            ret |= 0x80</span><br><span style="color: hsl(120, 100%, 40%);">+        return ret.to_bytes(1, 'big')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# length value coding is equal to BER-TLV</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#########################################################################</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>diff --git a/tests/test_utils.py b/tests/test_utils.py</span><br><span>index 17a9300..ed22eff 100755</span><br><span>--- a/tests/test_utils.py</span><br><span>+++ b/tests/test_utils.py</span><br><span>@@ -179,6 +179,28 @@</span><br><span>         res = utils.bertlv_parse_one(b'\x81\x01\x01');</span><br><span>         self.assertEqual(res, ({'tag':1, 'constructed':False, 'class':2}, 1, b'\x01', b''))</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+class TestComprTlv(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+    def test_ComprTlvTagDec(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        res = utils.comprehensiontlv_parse_tag(b'\x12\x23')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, ({'tag': 0x12, 'comprehension': False}, b'\x23'))</span><br><span style="color: hsl(120, 100%, 40%);">+        res = utils.comprehensiontlv_parse_tag(b'\x92')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, ({'tag': 0x12, 'comprehension': True}, b''))</span><br><span style="color: hsl(120, 100%, 40%);">+        res = utils.comprehensiontlv_parse_tag(b'\x7f\x12\x34')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, ({'tag': 0x1234, 'comprehension': False}, b''))</span><br><span style="color: hsl(120, 100%, 40%);">+        res = utils.comprehensiontlv_parse_tag(b'\x7f\x82\x34\x56')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, ({'tag': 0x234, 'comprehension': True}, b'\x56'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def test_ComprTlvTagEnc(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        res  = utils.comprehensiontlv_encode_tag(0x12)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, b'\x12')</span><br><span style="color: hsl(120, 100%, 40%);">+        res  = utils.comprehensiontlv_encode_tag({'tag': 0x12})</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, b'\x12')</span><br><span style="color: hsl(120, 100%, 40%);">+        res  = utils.comprehensiontlv_encode_tag({'tag': 0x12, 'comprehension':True})</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, b'\x92')</span><br><span style="color: hsl(120, 100%, 40%);">+        res  = utils.comprehensiontlv_encode_tag(0x1234)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, b'\x7f\x12\x34')</span><br><span style="color: hsl(120, 100%, 40%);">+        res  = utils.comprehensiontlv_encode_tag({'tag': 0x1234, 'comprehension':True})</span><br><span style="color: hsl(120, 100%, 40%);">+        self.assertEqual(res, b'\x7f\x92\x34')</span><br><span> </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/+/24448">change 24448</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/+/24448"/><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: I8d969382b73fa152ee09c456fa4aee428fb36285 </div>
<div style="display:none"> Gerrit-Change-Number: 24448 </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>