laforge has uploaded this change for review. (
https://gerrit.osmocom.org/c/pysim/+/37435?usp=email )
Change subject: pySim.tlv: Add COMPACT_TLV_IE TLV variant
......................................................................
pySim.tlv: Add COMPACT_TLV_IE TLV variant
the COMPACT-TLV variant is a TLV variant that ISO7816 uses for encoding
tag and length into a single octet. This is used (for example) in ATR
historical bytes.
Let's add support for this to our pySim TLV encoder/decoder.
Change-Id: I9e98d150b97317ae0c6be2366bdaaeaeddf8031c
---
M pySim/tlv.py
M tests/test_tlv.py
2 files changed, 68 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/35/37435/1
diff --git a/pySim/tlv.py b/pySim/tlv.py
index 3d7a420..e93462f 100644
--- a/pySim/tlv.py
+++ b/pySim/tlv.py
@@ -246,6 +246,35 @@
return dec, remainder
+class COMPACT_TLV_IE(TLV_IE):
+ """TLV_IE formatted as COMPACT-TLV described in ISO
7816"""
+
+ @classmethod
+ def _parse_tag_raw(cls, do: bytes) -> Tuple[int, bytes]:
+ return do[0] >> 4, do
+
+ @classmethod
+ def _decode_tag(cls, do: bytes) -> Tuple[dict, bytes]:
+ rawtag, remainder = cls._parse_tag_raw(do)
+ return {'tag': rawtag}, remainder
+
+ @classmethod
+ def _parse_len(cls, do: bytes) -> Tuple[int, bytes]:
+ return do[0] & 0xf, do[1:]
+
+ def _encode_tag(self) -> bytes:
+ """Not needed as we override the to_tlv() method to encode
tag+length into one byte."""
+ raise NotImplementedError
+
+ def _encode_len(self):
+ """Not needed as we override the to_tlv() method to encode
tag+length into one byte."""
+ raise NotImplementedError
+
+ def to_tlv(self, context: dict = {}):
+ val = self.to_bytes(context=context)
+ return bytes([(self.tag << 4) | (len(val) & 0xF)]) + val
+
+
class BER_TLV_IE(TLV_IE):
"""TLV_IE formatted as ASN.1 BER described in ITU-T X.690
8.1.2."""
diff --git a/tests/test_tlv.py b/tests/test_tlv.py
index 0e73ab1..3dc3a89 100644
--- a/tests/test_tlv.py
+++ b/tests/test_tlv.py
@@ -17,8 +17,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
-from construct import Int8ub
+from construct import Int8ub, GreedyBytes
from pySim.tlv import *
+from pySim.utils import h2b
class TestUtils(unittest.TestCase):
def test_camel_to_snake(self):
@@ -117,5 +118,27 @@
self.assertEqual(ie.to_bytes(), b'\x42')
self.assertEqual(ie.to_ie(), b'\x42')
+class TestCompact(unittest.TestCase):
+ class IE_3(COMPACT_TLV_IE, tag=0x3):
+ _construct = GreedyBytes
+ class IE_7(COMPACT_TLV_IE, tag=0x7):
+ _construct = GreedyBytes
+ class IE_5(COMPACT_TLV_IE, tag=0x5):
+ _construct = GreedyBytes
+ class IE_Coll(TLV_IE_Collection, nested=[IE_3, IE_7, IE_5]):
+ _construct = GreedyBytes
+ def test_ATR(self):
+ atr = h2b("31E073FE211F5745437531301365")
+ c = self.IE_Coll()
+ c.from_tlv(atr)
+ self.assertEqual(c.children[0].tag, 3)
+ self.assertEqual(c.children[0].to_bytes(), b'\xe0')
+ self.assertEqual(c.children[1].tag, 7)
+ self.assertEqual(c.children[1].to_bytes(), b'\xfe\x21\x1f')
+ self.assertEqual(c.children[2].tag, 5)
+ self.assertEqual(c.children[2].to_bytes(),
b'\x45\x43\x75\x31\x30\x13\x65')
+ self.assertEqual(c.to_tlv(), atr)
+
+
if __name__ == "__main__":
unittest.main()
--
To view, visit
https://gerrit.osmocom.org/c/pysim/+/37435?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I9e98d150b97317ae0c6be2366bdaaeaeddf8031c
Gerrit-Change-Number: 37435
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: newchange