aboutsummaryrefslogtreecommitdiffstats
path: root/pySim/utils.py
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-05-24 23:18:59 +0200
committerHarald Welte <laforge@osmocom.org>2021-05-30 19:27:37 +0200
commitf0885b1042fb89dcbe0fdddf6ada78ca1fabb72a (patch)
tree8f0ebc56fc93a9ab3083ed8da9b728af05f1a4e4 /pySim/utils.py
parent6912b1b67d3410e1049d26a4c09ea0cdc110fe92 (diff)
utils: Add bertlv_encode_tag()
We so far had decoders for BER-TLV tags, but no encoder yet. Change-Id: I4183546bed9d6232ddcefad764f4e67afcf8b2ed
Diffstat (limited to 'pySim/utils.py')
-rw-r--r--pySim/utils.py45
1 files changed, 45 insertions, 0 deletions
diff --git a/pySim/utils.py b/pySim/utils.py
index 74655d4..777638c 100644
--- a/pySim/utils.py
+++ b/pySim/utils.py
@@ -212,6 +212,51 @@ def bertlv_parse_tag(binary:bytes) -> Tuple[dict, bytes]:
i += 1
return ({'class':cls, 'constructed':constructed, 'tag':tag}, binary[i:])
+def bertlv_encode_tag(t) -> bytes:
+ """Encode a single Tag value according to ITU-T X.690 8.1.2
+ """
+ def get_top7_bits(inp:int) -> Tuple[int, int]:
+ """Get top 7 bits of integer. Returns those 7 bits as integer and the remaining LSBs."""
+ remain_bits = inp.bit_length()
+ if remain_bits >= 7:
+ bitcnt = 7
+ else:
+ bitcnt = remain_bits
+ outp = inp >> (remain_bits - bitcnt)
+ remainder = inp & ~ (inp << (remain_bits - bitcnt))
+ return outp, remainder
+
+ if isinstance(t, int):
+ # FIXME: multiple byte tags
+ tag = t & 0x1f
+ constructed = True if t & 0x20 else False
+ cls = t >> 6
+ else:
+ tag = t['tag']
+ constructed = t['constructed']
+ cls = t['class']
+ if tag <= 30:
+ t = tag & 0x1f
+ if constructed:
+ t |= 0x20
+ t |= (cls & 3) << 6
+ return bytes([t])
+ else: # multi-byte tag
+ t = 0x1f;
+ if constructed:
+ t |= 0x20
+ t |= (cls & 3) << 6
+ tag_bytes = bytes([t])
+ remain = tag
+ while True:
+ t, remain = get_top7_bits(remain)
+ if remain:
+ t |= 0x80
+ tag_bytes += bytes([t])
+ if not remain:
+ break
+ return tag_bytes
+
def bertlv_parse_len(binary:bytes) -> Tuple[int, bytes]:
"""Parse a single Length value according to ITU-T X.690 8.1.3;
only the definite form is supported here.