]> Cypherpunks.ru repositories - pyderasn.git/blobdiff - pyderasn.py
Fix invalid DEFINED BY offset calculation for EXPL tagged objects
[pyderasn.git] / pyderasn.py
index b4a10d9fc04ba14fcf91a86ce21f2490cf5c41fb..cd96a33200a1a6a7a801bc29b6aa95ca48b860cf 100755 (executable)
@@ -207,6 +207,7 @@ decoding process.
 Currently available context options:
 
 * :ref:`defines_by_path <defines_by_path_ctx>`
+* :ref:`strict_default_existence <strict_default_existence_ctx>`
 
 .. _pprinting:
 
@@ -3641,6 +3642,8 @@ class Sequence(Obj):
     >>> tbs = TBSCertificate()
     >>> tbs["version"] = Version("v2") # no need to explicitly add ``expl``
 
+    Assign ``None`` to remove value from sequence.
+
     You can know if value exists/set in the sequence and take its value:
 
     >>> "extnID" in ext, "extnValue" in ext, "critical" in ext
@@ -3660,13 +3663,18 @@ class Sequence(Obj):
 
     All defaulted values are always optional.
 
+    .. _strict_default_existence_ctx:
+
     .. warning::
 
        When decoded DER contains defaulted value inside, then
-       technically this is not valid DER encoding. But we allow
-       and pass it. Of course reencoding of that kind of DER will
+       technically this is not valid DER encoding. But we allow and pass
+       it **by default**. Of course reencoding of that kind of DER will
        result in different binary representation (validly without
-       defaulted value inside).
+       defaulted value inside). You can enable strict defaulted values
+       existence validation by setting ``"strict_default_existence":
+       True`` :ref:`context <ctx>` option -- decoding process will raise
+       an exception if defaulted value is met.
 
     Two sequences are equal if they have equal specification (schema),
     implicit/explicit tagging and the same values.
@@ -3867,7 +3875,10 @@ class Sequence(Obj):
                         )
                         defined_value, defined_tail = defined_spec.decode(
                             memoryview(bytes(_value)),
-                            sub_offset + value.tlen + value.llen,
+                            sub_offset + (
+                                (value.tlen + value.llen + value.expl_tlen + value.expl_llen)
+                                if value.expled else (value.tlen + value.llen)
+                            ),
                             leavemm=True,
                             decode_path=sub_sub_decode_path,
                             ctx=ctx,
@@ -3883,7 +3894,10 @@ class Sequence(Obj):
                 else:
                     defined_value, defined_tail = defined_spec.decode(
                         memoryview(bytes(value)),
-                        sub_offset + value.tlen + value.llen,
+                        sub_offset + (
+                            (value.tlen + value.llen + value.expl_tlen + value.expl_llen)
+                            if value.expled else (value.tlen + value.llen)
+                        ),
                         leavemm=True,
                         decode_path=sub_decode_path + (decode_path_defby(defined_by),),
                         ctx=ctx,
@@ -3900,9 +3914,15 @@ class Sequence(Obj):
             sub_offset += (value.expl_tlvlen if value.expled else value.tlvlen)
             v = v_tail
             if spec.default is not None and value == spec.default:
-                # Encoded default values are not valid in DER,
-                # but we allow that anyway
-                continue
+                if ctx.get("strict_default_existence", False):
+                    raise DecodeError(
+                        "DEFAULT value met",
+                        klass=self.__class__,
+                        decode_path=sub_decode_path,
+                        offset=sub_offset,
+                    )
+                else:
+                    continue
             values[name] = value
 
             spec_defines = getattr(spec, "defines", ())