mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-26 15:28:35 +03:00
pySim.tlv: Correctly parse COMPREHENSION-TLV without comprehension bit
The uppermost bit of COMPREHENSION-TLV tags indicates whether the recipient is required to "comprehend" that IE or not. So every IE actually has two tag values: one with and one without that bit set. As all our existing TLV definitions of COMPR_TLV_IE have that bit set, let's assume this is the default, but use the same definition also for the situation where that bit is not set. Change-Id: I58d04ec13be0c12d9fb8cb3d5a0480d0defb6c95
This commit is contained in:
17
pySim/tlv.py
17
pySim/tlv.py
@@ -224,12 +224,16 @@ class TLV_IE(IE):
|
|||||||
val = self.to_bytes(context=context)
|
val = self.to_bytes(context=context)
|
||||||
return self._encode_tag() + self._encode_len(val) + val
|
return self._encode_tag() + self._encode_len(val) + val
|
||||||
|
|
||||||
|
def is_tag_compatible(self, rawtag) -> bool:
|
||||||
|
"""Is the given rawtag compatible with this class?"""
|
||||||
|
return rawtag == self._compute_tag()
|
||||||
|
|
||||||
def from_tlv(self, do: bytes, context: dict = {}):
|
def from_tlv(self, do: bytes, context: dict = {}):
|
||||||
if len(do) == 0:
|
if len(do) == 0:
|
||||||
return {}, b''
|
return {}, b''
|
||||||
(rawtag, remainder) = self.__class__._parse_tag_raw(do)
|
(rawtag, remainder) = self.__class__._parse_tag_raw(do)
|
||||||
if rawtag:
|
if rawtag:
|
||||||
if rawtag != self._compute_tag():
|
if not self.is_tag_compatible(rawtag):
|
||||||
raise ValueError("%s: Encountered tag %s doesn't match our supported tag %s" %
|
raise ValueError("%s: Encountered tag %s doesn't match our supported tag %s" %
|
||||||
(self, rawtag, self.tag))
|
(self, rawtag, self.tag))
|
||||||
(length, remainder) = self.__class__._parse_len(remainder)
|
(length, remainder) = self.__class__._parse_len(remainder)
|
||||||
@@ -283,6 +287,15 @@ class COMPR_TLV_IE(TLV_IE):
|
|||||||
def _parse_len(cls, do: bytes) -> Tuple[int, bytes]:
|
def _parse_len(cls, do: bytes) -> Tuple[int, bytes]:
|
||||||
return bertlv_parse_len(do)
|
return bertlv_parse_len(do)
|
||||||
|
|
||||||
|
def is_tag_compatible(self, rawtag: int) -> bool:
|
||||||
|
"""Override is_tag_compatible as we need to mask out the
|
||||||
|
comprehension bit when doing compares."""
|
||||||
|
ctag = self._compute_tag()
|
||||||
|
if ctag > 0xff:
|
||||||
|
return ctag & 0x7fff == rawtag & 0x7fff
|
||||||
|
else:
|
||||||
|
return ctag & 0x7f == rawtag & 0x7f
|
||||||
|
|
||||||
def _encode_tag(self) -> bytes:
|
def _encode_tag(self) -> bytes:
|
||||||
return comprehensiontlv_encode_tag(self._compute_tag())
|
return comprehensiontlv_encode_tag(self._compute_tag())
|
||||||
|
|
||||||
@@ -367,6 +380,8 @@ class TLV_IE_Collection(metaclass=TlvCollectionMeta):
|
|||||||
tag, _r = first._parse_tag_raw(remainder)
|
tag, _r = first._parse_tag_raw(remainder)
|
||||||
if tag is None:
|
if tag is None:
|
||||||
break
|
break
|
||||||
|
if issubclass(first, COMPR_TLV_IE):
|
||||||
|
tag = tag | 0x80 # HACK: always assume comprehension
|
||||||
if tag in self.members_by_tag:
|
if tag in self.members_by_tag:
|
||||||
cls = self.members_by_tag[tag]
|
cls = self.members_by_tag[tag]
|
||||||
# create an instance and parse accordingly
|
# create an instance and parse accordingly
|
||||||
|
|||||||
Reference in New Issue
Block a user