aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-05-24 23:16:44 +0200
committerHarald Welte <laforge@osmocom.org>2021-05-29 22:21:38 +0200
commit6912b1b67d3410e1049d26a4c09ea0cdc110fe92 (patch)
tree9edfad3390e56e649c2c2f74e8709a008aad1209
parent9f3b44d6ff1b8f8968c5399374433439ac0fbb5b (diff)
utils: Add 'raw' version of TLV tag decoders
The existing {comprehension,ber}tlv_parse_tag() functions are decoding the tag to a high level of detail. However, all the 3GPP specs seem to deal with the 'raw' version, i.e something like 0xD1 as a single-byte tag with the class + constructed fields already shifted next to the actual tag value. Let's accommodate that with new *_parse_tag_raw() functions. Change-Id: Ib50946bfb3b3ecd7942c423ac0f98b6c07649224
-rw-r--r--pySim/utils.py52
1 files changed, 52 insertions, 0 deletions
diff --git a/pySim/utils.py b/pySim/utils.py
index d96d05a..74655d4 100644
--- a/pySim/utils.py
+++ b/pySim/utils.py
@@ -93,6 +93,21 @@ def half_round_up(n:int) -> int:
# poor man's COMPREHENSION-TLV decoder.
#########################################################################
+def comprehensiontlv_parse_tag_raw(binary:bytes) -> Tuple[int, bytes]:
+ """Parse a single Tag according to ETSI TS 101 220 Section 7.1.1"""
+ if binary[0] in [0x00, 0x80, 0xff]:
+ raise ValueError("Found illegal value 0x%02x in %s" % (binary[0], binary))
+ if binary[0] == 0x7f:
+ # three-byte tag
+ tag = binary[0] << 16 | binary[1] << 8 | binary[2]
+ return (tag, binary[3:])
+ elif binary[0] == 0xff:
+ return None, binary
+ else:
+ # single byte tag
+ tag = binary[0]
+ return (tag, binary[1:])
+
def comprehensiontlv_parse_tag(binary:bytes) -> Tuple[dict, bytes]:
"""Parse a single Tag according to ETSI TS 101 220 Section 7.1.1"""
if binary[0] in [0x00, 0x80, 0xff]:
@@ -132,11 +147,48 @@ def comprehensiontlv_encode_tag(tag) -> bytes:
# length value coding is equal to BER-TLV
+def comprehensiontlv_parse_one(binary:bytes) -> (dict, int, bytes, bytes):
+ """Parse a single TLV IE at the start of the given binary data.
+ Args:
+ binary : binary input data of BER-TLV length field
+ Returns:
+ Tuple of (tag:dict, len:int, remainder:bytes)
+ """
+ (tagdict, remainder) = comprehensiontlv_parse_tag(binary)
+ (length, remainder) = bertlv_parse_len(remainder)
+ value = remainder[:length]
+ remainder = remainder[length:]
+ return (tagdict, length, value, remainder)
+
+
#########################################################################
# poor man's BER-TLV decoder. To be a more sophisticated OO library later
#########################################################################
+def bertlv_parse_tag_raw(binary:bytes) -> Tuple[int, bytes]:
+ """Get a single raw Tag from start of input according to ITU-T X.690 8.1.2
+ Args:
+ binary : binary input data of BER-TLV length field
+ Returns:
+ Tuple of (tag:int, remainder:bytes)
+ """
+ if binary[0] == 0xff:
+ return None, binary
+ tag = binary[0] & 0x1f
+ if tag <= 30:
+ return binary[0], binary[1:]
+ else: # multi-byte tag
+ tag = binary[0]
+ i = 1
+ last = False
+ while not last:
+ last = False if binary[i] & 0x80 else True
+ tag <<= 8
+ tag |= binary[i]
+ i += 1
+ return tag, binary[i:]
+
def bertlv_parse_tag(binary:bytes) -> Tuple[dict, bytes]:
"""Parse a single Tag value according to ITU-T X.690 8.1.2
Args: