P1sec / pycrate

A Python library to ease the development of encoders and decoders for various protocols and file formats; contains ASN.1 and CSN.1 compilers.
GNU Lesser General Public License v2.1
385 stars 129 forks source link

ASN.1 bit string encoding #65

Closed KenWhitesell closed 5 years ago

KenWhitesell commented 5 years ago

I believe there may be an issue with the encoding of bit strings. Minimal sample ASN (created as a very narrow extract from the 2016 J2735 asn.):

DSRC DEFINITIONS AUTOMATIC TAGS::= BEGIN 
Lane ::= SEQUENCE {
   directionalUse  LaneDirection
   }

LaneDirection ::= BIT STRING {
   ingressPath     (0), 
   egressPath      (1)
   } (SIZE (2))

END

The intent of the size specification in the first LaneDirection element is to identify the total size of the field, regardless of the number of bits enumerated. (For the elements using it in the J2735 spec, the extra bits are reserved for regional use or future expansion.) This file creates the following objects in the .py file for those two elements.

#-----< LaneDirection >-----#
 LaneDirection = BIT_STR(name='LaneDirection', mode=MODE_TYPE)
 LaneDirection._cont = ASN1Dict([('ingressPath', 0), ('egressPath', 1)])
 LaneDirection._const_sz = ASN1Set(rv=[2], rr=[], ev=None, er=[])

The issue, in so far as I'm able to follow it so far, is that the rv parameter in the _const_sz attribute is used by the rt code when checking constraints, and it's looking to see if the value being supplied is in the rv list rather than being bounded by it.

The relevant chunk of code is in pycrate_asn1rt/asnobj_str.py, the function _safechk_bnd, around line 142 in the current master:

if isinstance(val[0], integer_types):
    # check val against potential constraints
    ASN1Obj._safechk_bnd(self, val)
    if self._const_sz and \
    self._const_sz.ext is None and \
    val[1] not in self._const_sz:
         raise(ASN1ObjErr('{0}: value out of size constraint, {1!r}'\
              .format(self.fullname(), val)))

(Third line from the bottom is the conditional that is failing.)

(Note: I'm willing to take a stab at fixing this, but I'd like some ideas or guidance as to where the appropriate place might be to address it, and what you think an appropriate fix might look like.)

p1-bmu commented 5 years ago

Thanks for this feedback. Could you please indicate the exact encoding issue / failing you found with a concrete example ?

KenWhitesell commented 5 years ago

I've attached a file which is a terminal session walking through the complete set of steps to recreate the problem identified here. Please let me know if you have any questions or need any further information.

Xterm.log.tskww-HP-1.txt

p1-bmu commented 5 years ago

OK, thanks. This is also related to passing ASN.1 BIT STRING values as named offsets. Here, the bug is that when there is a SIZE constraint that is not respected by encoding the given named offsets in the minimum number of bits, the runtime raises instead of extending the BIT STRING value up to the constraint. A patch should be done somewhere here: https://github.com/P1sec/pycrate/blob/5e7406d99346c2130b0e01f23c7c39a4756e857b/pycrate_asn1rt/asnobj_str.py#L223

I will work on it when I have some time, maybe next week or so.

p1-bmu commented 5 years ago

This commit should solve the issue: https://github.com/P1sec/pycrate/commit/afc9849c4c895ef8924c7c9dc77d0274bc6e735b

KenWhitesell commented 5 years ago

Fixed! Thank you!