]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - pyderasn.py
xrange is preferrable for dozen-elements lists
[pyderasn.git] / pyderasn.py
index 581af5f87ee2923ac183dadb5817ee2cd22ee808..1245a435792c30b33c733aba5409bdd816173d53 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # coding: utf-8
 # PyDERASN -- Python ASN.1 DER/BER codec with abstract structures
-# Copyright (C) 2017-2018 Sergey Matveev <stargrave@stargrave.org>
+# Copyright (C) 2017-2019 Sergey Matveev <stargrave@stargrave.org>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Lesser General Public License as
@@ -384,7 +384,8 @@ constructed primitive types should be parsed successfully.
 
 * If object is encoded in BER form (not the DER one), then ``ber_encoded``
   attribute is set to True. Only ``BOOLEAN``, ``BIT STRING``, ``OCTET
-  STRING``, ``SEQUENCE``, ``SET``, ``SET OF`` can contain it.
+  STRING``, ``OBJECT IDENTIFIER``, ``SEQUENCE``, ``SET``, ``SET OF``
+  can contain it.
 * If object has an indefinite length encoding, then its ``lenindef``
   attribute is set to True. Only ``BIT STRING``, ``OCTET STRING``,
   ``SEQUENCE``, ``SET``, ``SEQUENCE OF``, ``SET OF``, ``ANY`` can
@@ -1324,7 +1325,7 @@ def _colourize(what, colour, with_colours, attrs=("bold",)):
 def colonize_hex(hexed):
     """Separate hexadecimal string with colons
     """
-    return ":".join(hexed[i:i + 2] for i in range(0, len(hexed), 2))
+    return ":".join(hexed[i:i + 2] for i in six_xrange(0, len(hexed), 2))
 
 
 def pp_console_row(
@@ -1431,7 +1432,7 @@ def pp_console_blob(pp, decode_path_len_decrease=0):
         cols.append(" ." * (decode_path_len + 1))
     if isinstance(pp.blob, binary_type):
         blob = hexenc(pp.blob).upper()
-        for i in range(0, len(blob), 32):
+        for i in six_xrange(0, len(blob), 32):
             chunk = blob[i:i + 32]
             yield " ".join(cols + [colonize_hex(chunk)])
     elif isinstance(pp.blob, tuple):
@@ -1568,6 +1569,9 @@ class Boolean(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __nonzero__(self):
@@ -1824,6 +1828,9 @@ class Integer(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __int__(self):
@@ -2204,6 +2211,9 @@ class BitString(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __iter__(self):
@@ -2616,6 +2626,9 @@ class OctetString(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __bytes__(self):
@@ -2902,6 +2915,9 @@ class Null(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __eq__(self, their):
@@ -3112,6 +3128,9 @@ class ObjectIdentifier(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __iter__(self):
@@ -3223,11 +3242,17 @@ class ObjectIdentifier(Obj):
             )
         v, tail = v[:l], v[l:]
         arcs = []
+        ber_encoded = False
         while len(v) > 0:
             i = 0
             arc = 0
             while True:
                 octet = indexbytes(v, i)
+                if i == 0 and octet == 0x80:
+                    if ctx.get("bered", False):
+                        ber_encoded = True
+                    else:
+                        raise DecodeError("non normalized arc encoding")
                 arc = (arc << 7) | (octet & 0x7F)
                 if octet & 0x80 == 0:
                     arcs.append(arc)
@@ -3259,6 +3284,8 @@ class ObjectIdentifier(Obj):
             optional=self.optional,
             _decoded=(offset, llen, l),
         )
+        if ber_encoded:
+            obj.ber_encoded = True
         return obj, tail
 
     def __repr__(self):
@@ -3284,6 +3311,7 @@ class ObjectIdentifier(Obj):
             expl_llen=self.expl_llen if self.expled else None,
             expl_vlen=self.expl_vlen if self.expled else None,
             expl_lenindef=self.expl_lenindef,
+            ber_encoded=self.ber_encoded,
             bered=self.bered,
         )
         for pp in self.pps_lenindef(decode_path):
@@ -3352,6 +3380,9 @@ class Enumerated(Integer):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __call__(
@@ -3959,6 +3990,9 @@ class Choice(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         value = self._value
         if value is not None:
             obj._value = (value[0], value[1].copy())
@@ -4199,6 +4233,9 @@ class Any(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         return obj
 
     def __eq__(self, their):
@@ -4538,6 +4575,9 @@ class Sequence(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         obj._value = {k: v.copy() for k, v in self._value.items()}
         return obj
 
@@ -5115,6 +5155,9 @@ class SequenceOf(Obj):
         obj.offset = self.offset
         obj.llen = self.llen
         obj.vlen = self.vlen
+        obj.expl_lenindef = self.expl_lenindef
+        obj.lenindef = self.lenindef
+        obj.ber_encoded = self.ber_encoded
         obj._value = [v.copy() for v in self._value]
         return obj
 
@@ -5388,7 +5431,7 @@ def generic_decoder():  # pragma: no cover
     choice = PrimitiveTypes()
     choice.specs["SequenceOf"] = SequenceOf(schema=choice)
     choice.specs["SetOf"] = SetOf(schema=choice)
-    for i in range(31):
+    for i in six_xrange(31):
         choice.specs["SequenceOf%d" % i] = SequenceOf(
             schema=choice,
             expl=tag_ctxc(i),