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.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LCSClientID optional field cannot be set in an EMM message because of error during ber-encoding

Marc-Egli opened this issue · comments

Hello,

I am currently working on generating some NAS packets and I observed some strange behavior when setting the LCSClientID optional field inside an EMMCSServiceNotification message.

From the below code, I concluded that I needed to generate an LCSClientID message using the ASN.1 specifications.

LCSClientId = wrapper.gen_ber_wrapper(MAP.MAP_LCS_DataTypes.LCS_ClientID,
                                          asn_map_acquire,
                                          asn_map_release)

I obtained the below LCSClientID message which is correctly decoded and encoded. All values are random but conform to the specifications.

{'lcsClientType': 'emergencyServices', 'lcsClientExternalID': {'externalAddress': b'J', 'extensionContainer': {'privateExtensionList': [{'extId': (179, 17, 158, 19), 'extType': ('BOOLEAN', True)}], 'pcs-Extensions': {}}}, 'lcsClientDialedByMS': b'"\xed', 'lcsClientInternalID': 'o-andM-VPLMN', 'lcsClientName': {'dataCodingScheme': b'\x11', 'nameString': b'h\xecQ\xc9\x89@U\x03X\xaf\xda\xcd\\\x8c\xfc\xc3B\xea'}}

I then use this dictionary to set the value of the LCSClientID in the EMMCSServiceNotification message.
When doing so I get the following error :

File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/wrapper.py", line 123, in set_val
    self._buf = self.OBJ.to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1680, in to_ber
    return pack_val(*self._to_ber())[0]
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1629, in _to_ber
    pc, lval, V = self._encode_ber_cont()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj_construct.py", line 2205, in _encode_ber_cont
    comp_tlv = Comp._to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1629, in _to_ber
    pc, lval, V = self._encode_ber_cont()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj_construct.py", line 2205, in _encode_ber_cont
    comp_tlv = Comp._to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1629, in _to_ber
    pc, lval, V = self._encode_ber_cont()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj_construct.py", line 2205, in _encode_ber_cont
    comp_tlv = Comp._to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1629, in _to_ber
    pc, lval, V = self._encode_ber_cont()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj_construct.py", line 3156, in _encode_ber_cont
    tlv = Comp._to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1629, in _to_ber
    pc, lval, V = self._encode_ber_cont()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj_construct.py", line 2205, in _encode_ber_cont
    comp_tlv = Comp._to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1629, in _to_ber
    pc, lval, V = self._encode_ber_cont()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj_ext.py", line 582, in _encode_ber_cont
    TLV = Obj._to_ber()
  File "/usr/local/lib/python3.10/dist-packages/pycrate-0.5.5-py3.10.egg/pycrate_asn1rt/asnobj.py", line 1630, in _to_ber
    if not self._tagc:
AttributeError: 'BOOL' object has no attribute '_tagc'. Did you mean: '_tag'?

I traced back the error to the privateExtensionList field that contains an extId and a extType. The issue is that the type I provide cannot be ber encoded because of the missing _tagc attribute. I verified the definition of the extType, which is an ASN.1 OpenType, I should be able to provide any type to this field. The LCSClientID packet is valid but the encoding to put it into the EMMCSServiceNotification message fails.

Thank you in advance.

commented

Thanks for the report. Can you share a code snippet to reproduce the issue ?

Sure, here is a small example:

from pycrate_mobile.NAS import *

lcs_packet = MAP.MAP_LCS_DataTypes.LCS_ClientID
lcs_fields = {'lcsClientType': 'lawfulInterceptServices', 'lcsClientExternalID': {'externalAddress': b'\xaa\x8e\xa9\xdaqg', 'extensionContainer': { 'privateExtensionList': [{'extId': (0,1,2,3,4), 'extType' : ('BOOLEAN', True)}],'pcs-Extensions': {}}}, 'lcsClientDialedByMS': b'[\x129\x10\xd47\x02w\x10\xbb\xe0\x1fM\xc8\xc9', 'lcsClientInternalID': 'o-andM-HPLMN', 'lcsClientName': {'dataCodingScheme': b';', 'nameString': b'\x97\xfe6yh<\xbe\\Q\x91\x14\xbaVT\xa3'}}           
lcs_packet.set_val(lcs_fields)

# Detect invalid format by encoding and decoding
try:
    lcs = MAP.MAP_LCS_DataTypes.LCS_ClientID
    lcs.from_uper(lcs_packet.to_uper())
except Exception as err:
    print("Decoding failed")
    exit(0)

# Set LCSClientID fields in EMMCSServiceNotification message
val = {'LCSClientId' : lcs_fields}
msg = EMMCSServiceNotification(val=val)

This code snippet crashes when the LCSClientID field is set in the EMMCSServiceNotification message.

commented

Here is a shorter code snippet that exhibits the issue:

from pycrate_asn1dir.MAP import *
p = MAP_LCS_DataTypes.LCS_ClientID
v = {'lcsClientType': 'lawfulInterceptServices', 'lcsClientExternalID': {'externalAddress': b'\xaa\x8e\xa9\xdaqg', 'extensionContainer': { 'privateExtensionList': [{'extId': (0,1,2,3,4), 'extType': ('BOOLEAN', True)}],'pcs-Extensions': {}}}, 'lcsClientDialedByMS': b'[\x129\x10\xd47\x02w\x10\xbb\xe0\x1fM\xc8\xc9', 'lcsClientInternalID': 'o-andM-HPLMN', 'lcsClientName': {'dataCodingScheme': b';', 'nameString': b'\x97\xfe6yh<\xbe\\Q\x91\x14\xbaVT\xa3'}}
p.set_val(v)
p.to_ber()

One remark with your code: you use from_uper() and to_uper() with the MAP object, which is incorrect, as MAP relies on the BER codec. The issue lies in the use of an arbitrary object (here, a raw boolean) in the privateExtensionList which contains OPEN objects, together with the BER encoding which requires object tagging. I'll need to check more carefully on how to address the issue properly.

Thank you very much for looking into this issue and also for the explanation about the incorrect function calls from_uper() and to_uper() on the MAP object.

commented

I just pushed 581a50f, that should fix the issue you reported. Can you test it on your side and give me a feedback ?
Thanks for your help.

I just tested on my side and the fix works for me.
Thank you very much for having looked into it and finding a patch !