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
380 stars 130 forks source link

CipherKeyData is not parsed correctly from bytes. #235

Closed Marc-Egli closed 1 year ago

Marc-Egli commented 1 year ago

Hello,

I am currently trying to generate a valid CipherKeyData field in an EMMTrackingAreaUpdateAccept message defined in pycrate_mobile/TS24301_EMM.py but I am facing a decoding error when the IE contains more than 1 element (it is a sequence).

If it contains only one element there is no error

from pycrate_mobile.NAS import *
from pycrate_mobile import *

# One element
e1 = {'CipherSetID': 9328, 'CipherKey': b'\x99 \xee\xe9\x95V\xd2j\x94\x92>\xfe\xc6\x11\x96\xc5', 'spare': 0, 'C0Len': 28, 'C0': b'Z\xa2\x8aN\x8b\x1e\xd2\x88\xc5\xf6\xe5\xc7\xf1\x94mp\xe0\x94l\xe9\xba\x12\xa9E\xfc\xf4\xbf\xa8', 'PosSIBType11': 1, 'PosSIBType12': 1, 'PosSIBType13': 1, 'PosSIBType14': 0, 'PosSIBType15': 1, 'PosSIBType16': 1, 'PosSIBType17': 0, 'PosSIBType21': 1, 'PosSIBType22': 0, 'PosSIBType23': 1, 'PosSIBType24': 1, 'PosSIBType25': 1, 'PosSIBType26': 1, 'PosSIBType27': 0, 'PosSIBType28': 0, 'PosSIBType29': 1, 'PosSIBType210': 1, 'PosSIBType211': 0, 'PosSIBType212': 1, 'PosSIBType213': 0, 'PosSIBType214': 0, 'PosSIBType215': 1, 'PosSIBType216': 0, 'PosSIBType217': 0, 'PosSIBType218': 1, 'PosSIBType219': 1, 'PosSIBType31': 1, 'ValidityStartTime': {'Year': [9, 5], 'Mon': [0, 0], 'Day': [6, 1], 'Hour': [6, 1], 'Min': [3, 4]}, 'ValidityDuration': 47609, 'TAIList': [{'Type': 2, 'TAIValues': {0: ('141244', 29130), 1: ('867870', 2785), 2: ('374480', 26778), 3: ('975385', 28236), 4: ('943105', 18146), 5: (
    '323038', 42805), 6: ('707112', 40629), 7: ('244860', 44753), 8: ('975249', 40293), 9: ('481625', 58339), 10: ('825629', 3382)}}]}

val = {'CipherKeyData': (e1,)}

msg = EMMTrackingAreaUpdateAccept(val=val)

show(msg)

# Encode and decode
decoded_msg, err = parse_NASLTE_MT(msg.to_bytes())

if err != 0:
    print('Decoding error')
    print(err)

show(decoded_msg)

The error occurs when CipherKeyData contains 2 or more elements.

from pycrate_mobile.NAS import *
from pycrate_mobile import *

# Two elements
e1 = {'CipherSetID': 9328, 'CipherKey': b'\x99 \xee\xe9\x95V\xd2j\x94\x92>\xfe\xc6\x11\x96\xc5', 'spare': 0, 'C0Len': 28, 'C0': b'Z\xa2\x8aN\x8b\x1e\xd2\x88\xc5\xf6\xe5\xc7\xf1\x94mp\xe0\x94l\xe9\xba\x12\xa9E\xfc\xf4\xbf\xa8', 'PosSIBType11': 1, 'PosSIBType12': 1, 'PosSIBType13': 1, 'PosSIBType14': 0, 'PosSIBType15': 1, 'PosSIBType16': 1, 'PosSIBType17': 0, 'PosSIBType21': 1, 'PosSIBType22': 0, 'PosSIBType23': 1, 'PosSIBType24': 1, 'PosSIBType25': 1, 'PosSIBType26': 1, 'PosSIBType27': 0, 'PosSIBType28': 0, 'PosSIBType29': 1, 'PosSIBType210': 1, 'PosSIBType211': 0, 'PosSIBType212': 1, 'PosSIBType213': 0, 'PosSIBType214': 0, 'PosSIBType215': 1, 'PosSIBType216': 0, 'PosSIBType217': 0, 'PosSIBType218': 1, 'PosSIBType219': 1, 'PosSIBType31': 1, 'ValidityStartTime': {'Year': [9, 5], 'Mon': [0, 0], 'Day': [6, 1], 'Hour': [6, 1], 'Min': [3, 4]}, 'ValidityDuration': 47609, 'TAIList': [{'Type': 2, 'TAIValues': {0: ('141244', 29130), 1: ('867870', 2785), 2: ('374480', 26778), 3: ('975385', 28236), 4: ('943105', 18146), 5: (
    '323038', 42805), 6: ('707112', 40629), 7: ('244860', 44753), 8: ('975249', 40293), 9: ('481625', 58339), 10: ('825629', 3382)}}]}

e2 = {'CipherSetID': 28013, 'CipherKey': b',\xaa\x9eH\xc1\x00,\x84\x11\x9a3\xa4\x94*\xd2@', 'spare': 0, 'C0Len': 17, 'C0': b'\x1b\xb5\xc0\x16\x04\x13\x16\xd0\x8b\xc8R\x83\xa8`\x15\x03\xd6', 'PosSIBType11': 1, 'PosSIBType12': 0, 'PosSIBType13': 0, 'PosSIBType14': 0, 'PosSIBType15': 0, 'PosSIBType16': 1, 'PosSIBType17': 1, 'PosSIBType21': 0, 'PosSIBType22': 1, 'PosSIBType23': 0, 'PosSIBType24': 0, 'PosSIBType25': 0, 'PosSIBType26': 1, 'PosSIBType27': 1,
      'PosSIBType28': 1, 'PosSIBType29': 1, 'PosSIBType210': 1, 'PosSIBType211': 1, 'PosSIBType212': 1, 'PosSIBType213': 1, 'PosSIBType214': 1, 'PosSIBType215': 0, 'PosSIBType216': 0, 'PosSIBType217': 1, 'PosSIBType218': 1, 'PosSIBType219': 1, 'PosSIBType31': 1, 'ValidityStartTime': {'Year': [5, 5], 'Mon': [0, 0], 'Day': [8, 1], 'Hour': [6, 0], 'Min': [5, 4]}, 'ValidityDuration': 33538, 'TAIList': [{'Type': 2, 'TAIValues': {0: ('643219', 59086)}}]}

val = {'CipherKeyData': (e1, e2,)}

msg = EMMTrackingAreaUpdateAccept(val=val)

show(msg)

# Encode and decode
decoded_msg, err = parse_NASLTE_MT(msg.to_bytes())

if err != 0:
    print('Decoding error')
    print(err)

# Decoded message is not shown properly
show(decoded_msg)

The error when running the second code snippet is CipherKeyData, _from_char: unable to decode IE, CipherKeyData. I am not sure of the real reason behind the error but I was able to trace it back to the call to _from_char in pycrate_mobile/TS24007.py:298

Thank you in advance.

p1-bmu commented 1 year ago

Thanks for reporting. Actually, there was an issue in the CipherKeyData structure: it was missing the TAIList length prefix. The last commit fixes that, and additionally simplify the TAIList structure and align it on the way it's implemented in the TS24501_IE.py file (for 5G). You now need to set TAIList instances with values like the following:

v1 = [{'Type': 2,
   'PTAI': {'TAIs': {0: ('141244', 29130),
     1: ('867870', 2785),
     2: ('374480', 26778),
     3: ('975385', 28236),
     4: ('943105', 18146),
     5: ('323038', 42805),
     6: ('707112', 40629),
     7: ('244860', 44753),
     8: ('975249', 40293),
     9: ('481625', 58339),
     10: ('825629', 3382)}}}]
v2 = [{'Type': 2, 
   'PTAI': {'TAIs': {0: ('643219', 59086)}}}]
Marc-Egli commented 1 year ago

Thank you very much for the fix ! Everything works fine for me now.