X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=pyderasn.py;h=b3ee318ae7f03cecbe120f8173e4de1a580e8eb6;hb=3906f3ed9567496401ada4ba71a342215b8785f1;hp=a048f4d3990c85e899f10a1f96179a89217da7aa;hpb=3ef2a2faa140bac2bbf3b024e827a7db63b5e38d;p=pyderasn.git diff --git a/pyderasn.py b/pyderasn.py index a048f4d..b3ee318 100755 --- a/pyderasn.py +++ b/pyderasn.py @@ -608,7 +608,7 @@ class NotEnoughData(DecodeError): pass -class LenIndefiniteForm(DecodeError): +class LenIndefForm(DecodeError): pass @@ -803,6 +803,11 @@ def len_encode(l): def len_decode(data): + """Decode length + + :returns: (decoded length, length's length, remaining data) + :raises LenIndefForm: if indefinite form encoding is met + """ if len(data) == 0: raise NotEnoughData("no data at all") first_octet = byte2int(data) @@ -812,7 +817,7 @@ def len_decode(data): if octets_num + 1 > len(data): raise NotEnoughData("encoded length is longer than data") if octets_num == 0: - raise LenIndefiniteForm() + raise LenIndefForm() if byte2int(data[1:]) == 0: raise DecodeError("leading zeros") l = 0 @@ -849,8 +854,9 @@ class Obj(object): "offset", "llen", "vlen", + "lenindef", + "expl_lenindef", "bered", - "expl_bered", ) def __init__( @@ -872,8 +878,9 @@ class Obj(object): self.optional = optional self.offset, self.llen, self.vlen = _decoded self.default = None + self.lenindef = False + self.expl_lenindef = False self.bered = False - self.expl_bered = False @property def ready(self): # pragma: no cover @@ -984,7 +991,7 @@ class Obj(object): ) try: l, llen, v = len_decode(lv) - except LenIndefiniteForm as err: + except LenIndefForm as err: if not ctx.get("bered", False): raise err.__class__( msg=err.msg, @@ -1012,7 +1019,7 @@ class Obj(object): offset=offset, ) obj.vlen += EOC_LEN - obj.expl_bered = True + obj.expl_lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -1054,7 +1061,7 @@ class Obj(object): @property def expl_llen(self): - if self.expl_bered: + if self.expl_lenindef: return 1 return len(len_encode(self.tlvlen)) @@ -1824,6 +1831,8 @@ class BitString(Obj): >>> b.bit_len 88 + >>> BitString("'0A3B5F291CD'H") + BIT STRING 44 bits 0a3b5f291cd0 >>> b = BitString("'010110000000'B") BIT STRING 12 bits 5800 >>> b.bit_len @@ -1912,21 +1921,25 @@ class BitString(Obj): if isinstance(value, (string_types, binary_type)): if ( isinstance(value, string_types) and - value.startswith("'") and - value.endswith("'B") + value.startswith("'") ): - value = value[1:-2] - if not set(value) <= set(("0", "1")): - raise ValueError("B's coding contains unacceptable chars") - return self._bits2octets(value) + if value.endswith("'B"): + value = value[1:-2] + if not set(value) <= set(("0", "1")): + raise ValueError("B's coding contains unacceptable chars") + return self._bits2octets(value) + elif value.endswith("'H"): + value = value[1:-2] + return ( + len(value) * 4, + hexdec(value + ("" if len(value) % 2 == 0 else "0")), + ) + else: + raise InvalidValueType((self.__class__, string_types, binary_type)) elif isinstance(value, binary_type): return (len(value) * 8, value) else: - raise InvalidValueType(( - self.__class__, - string_types, - binary_type, - )) + raise InvalidValueType((self.__class__, string_types, binary_type)) if isinstance(value, tuple): if ( len(value) == 2 and @@ -2121,12 +2134,12 @@ class BitString(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) - except LenIndefiniteForm: + except LenIndefForm: llen, l, v = 1, 0, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -2141,7 +2154,7 @@ class BitString(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected and l == 0: + if not lenindef and l == 0: raise NotEnoughData( "zero length", klass=self.__class__, @@ -2152,7 +2165,7 @@ class BitString(Obj): sub_offset = offset + tlen + llen vlen = 0 while True: - if eoc_expected: + if lenindef: if v[:EOC_LEN].tobytes() == EOC: break else: @@ -2210,10 +2223,11 @@ class BitString(Obj): default=self.default, optional=self.optional, _specs=self.specs, - _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)), + _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) + obj.lenindef = lenindef obj.bered = True - return obj, v[EOC_LEN if eoc_expected else 0:] + return obj, (v[EOC_LEN:] if lenindef else v) raise TagMismatch( klass=self.__class__, decode_path=decode_path, @@ -2472,12 +2486,12 @@ class OctetString(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) - except LenIndefiniteForm: + except LenIndefForm: llen, l, v = 1, 0, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -2492,7 +2506,7 @@ class OctetString(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected and l == 0: + if not lenindef and l == 0: raise NotEnoughData( "zero length", klass=self.__class__, @@ -2503,7 +2517,7 @@ class OctetString(Obj): sub_offset = offset + tlen + llen vlen = 0 while True: - if eoc_expected: + if lenindef: if v[:EOC_LEN].tobytes() == EOC: break else: @@ -2548,7 +2562,7 @@ class OctetString(Obj): expl=self._expl, default=self.default, optional=self.optional, - _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)), + _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) except DecodeError as err: raise DecodeError( @@ -2564,8 +2578,9 @@ class OctetString(Obj): decode_path=decode_path, offset=offset, ) + obj.lenindef = lenindef obj.bered = True - return obj, v[EOC_LEN if eoc_expected else 0:] + return obj, (v[EOC_LEN:] if lenindef else v) raise TagMismatch( klass=self.__class__, decode_path=decode_path, @@ -3236,6 +3251,10 @@ class CommonString(OctetString): tlen=self.tlen, llen=self.llen, vlen=self.vlen, + expl_offset=self.expl_offset if self.expled else None, + expl_tlen=self.expl_tlen if self.expled else None, + expl_llen=self.expl_llen if self.expled else None, + expl_vlen=self.expl_vlen if self.expled else None, ) @@ -3424,6 +3443,10 @@ class UTCTime(CommonString): tlen=self.tlen, llen=self.llen, vlen=self.vlen, + expl_offset=self.expl_offset if self.expled else None, + expl_tlen=self.expl_tlen if self.expled else None, + expl_llen=self.expl_llen if self.expled else None, + expl_vlen=self.expl_vlen if self.expled else None, ) @@ -3895,7 +3918,7 @@ class Any(Obj): ) try: l, llen, v = len_decode(lv) - except LenIndefiniteForm as err: + except LenIndefForm as err: if not ctx.get("bered", False): raise err.__class__( msg=err.msg, @@ -3915,7 +3938,7 @@ class Any(Obj): optional=self.optional, _decoded=(offset, 0, tlvlen), ) - obj.bered = True + obj.lenindef = True obj.tag = t return obj, v[EOC_LEN:] else: @@ -4275,10 +4298,10 @@ class Sequence(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) - except LenIndefiniteForm as err: + except LenIndefForm as err: if not ctx.get("bered", False): raise err.__class__( msg=err.msg, @@ -4287,7 +4310,7 @@ class Sequence(Obj): offset=offset, ) l, llen, v = 0, 1, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -4302,15 +4325,15 @@ class Sequence(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected: + if not lenindef: v, tail = v[:l], v[l:] vlen = 0 sub_offset = offset + tlen + llen values = {} for name, spec in self.specs.items(): if spec.optional and ( - (eoc_expected and v[:EOC_LEN].tobytes() == EOC) or - len(v) == 0 + (lenindef and v[:EOC_LEN].tobytes() == EOC) or + len(v) == 0 ): continue sub_decode_path = decode_path + (name,) @@ -4403,7 +4426,7 @@ class Sequence(Obj): abs_decode_path(sub_decode_path[:-1], rel_path), (value, defined), )) - if eoc_expected: + if lenindef: if v[:EOC_LEN].tobytes() != EOC: raise DecodeError( "no EOC", @@ -4429,8 +4452,7 @@ class Sequence(Obj): _decoded=(offset, llen, vlen), ) obj._value = values - if eoc_expected: - obj.bered = True + obj.lenindef = lenindef return obj, tail def __repr__(self): @@ -4501,10 +4523,10 @@ class Set(Sequence): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) - except LenIndefiniteForm as err: + except LenIndefForm as err: if not ctx.get("bered", False): raise err.__class__( msg=err.msg, @@ -4513,7 +4535,7 @@ class Set(Sequence): offset=offset, ) l, llen, v = 0, 1, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -4527,14 +4549,14 @@ class Set(Sequence): klass=self.__class__, offset=offset, ) - if not eoc_expected: + if not lenindef: v, tail = v[:l], v[l:] vlen = 0 sub_offset = offset + tlen + llen values = {} specs_items = self.specs.items while len(v) > 0: - if eoc_expected and v[:EOC_LEN].tobytes() == EOC: + if lenindef and v[:EOC_LEN].tobytes() == EOC: break for name, spec in specs_items(): sub_decode_path = decode_path + (name,) @@ -4576,7 +4598,7 @@ class Set(Sequence): expl=self._expl, default=self.default, optional=self.optional, - _decoded=(offset, llen, vlen + (EOC_LEN if eoc_expected else 0)), + _decoded=(offset, llen, vlen + (EOC_LEN if lenindef else 0)), ) obj._value = values if not obj.ready: @@ -4586,10 +4608,8 @@ class Set(Sequence): decode_path=decode_path, offset=offset, ) - if eoc_expected: - obj.bered = True - tail = v[EOC_LEN:] - return obj, tail + obj.lenindef = lenindef + return obj, (v[EOC_LEN:] if lenindef else tail) class SequenceOf(Obj): @@ -4790,10 +4810,10 @@ class SequenceOf(Obj): ) if tag_only: return - eoc_expected = False + lenindef = False try: l, llen, v = len_decode(lv) - except LenIndefiniteForm as err: + except LenIndefForm as err: if not ctx.get("bered", False): raise err.__class__( msg=err.msg, @@ -4802,7 +4822,7 @@ class SequenceOf(Obj): offset=offset, ) l, llen, v = 0, 1, lv[1:] - eoc_expected = True + lenindef = True except DecodeError as err: raise err.__class__( msg=err.msg, @@ -4817,14 +4837,14 @@ class SequenceOf(Obj): decode_path=decode_path, offset=offset, ) - if not eoc_expected: + if not lenindef: v, tail = v[:l], v[l:] vlen = 0 sub_offset = offset + tlen + llen _value = [] spec = self.spec while len(v) > 0: - if eoc_expected and v[:EOC_LEN].tobytes() == EOC: + if lenindef and v[:EOC_LEN].tobytes() == EOC: break value, v_tail = spec.decode( v, @@ -4848,10 +4868,8 @@ class SequenceOf(Obj): optional=self.optional, _decoded=(offset, llen, vlen), ) - if eoc_expected: - obj.bered = True - tail = v[EOC_LEN:] - return obj, tail + obj.lenindef = lenindef + return obj, (v[EOC_LEN:] if lenindef else tail) def __repr__(self): return "%s[%s]" % (