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
382 stars 132 forks source link

How to set IEs for pycrate_mobile #215

Closed tariromukute closed 1 year ago

tariromukute commented 1 year ago

Thank you very much for open sourcing your project. It has made the learning curve smoother.

I am struggling with setting IEs for some of the pycrate_mobile procedures. I tried referring to the documentation but I think i am missing something. I am trying to create a 5GMMSecurityModeComplete NAS PDU. I can't successfully set the IMEISV. From configuration, the value of IMEISV is 0035609204079514.

I have tried setting it in the following ways (guess working really)

# Attempt 1
IEs = {}
IEs['5GMMHeader'] = { 'EPD': 126, 'spare': 0, 'SecHdr': 0 }
IEs['IMEISV'] = { 'V': u'0035609204079514' }
Msg = FGMMSecurityModeComplete(val=IEs)

Following a 'similar' operation on the Wiki

# Attempt 1
IEs = {}
IEs['5GMMHeader'] = { 'EPD': 126, 'spare': 0, 'SecHdr': 0 }
Msg = FGMMSecurityModeComplete(val=IEs)
Msg['IMEISV'].set_IE(val={'type': 1, 'ident': u'035609204079514'})

My question is what the correct way to set IEs in these cases? I am also having a similar challenge in setting NSSAI on 5GMMRegistrationRequest.

p1-bmu commented 1 year ago

The 5GS ID is a complex structure, mapped on the definition from the TS 24.501 specification. The resulting code is here: https://github.com/P1sec/pycrate/blob/b3184d74629c3a90a4961049d56154b6e5201a1b/pycrate_mobile/TS24501_IE.py#L433

You can import all the IE-specific structures from the TS24501_IE module and do the following test:

In [1]: from pycrate_mobile.TS24501_IE import *

In [2]: FGSIDTYPE_IMEISV                                                                                                                                                                                    
Out[2]: 5

In [3]: imei = FGSID(val={'Type': FGSIDTYPE_IMEISV, 'Digit1': 0, 'Digits': '035609204079514'})                                                                                                                 

In [4]: print(imei.show())                                                                                                                                                                                     
### 5GSID ###
 <Digit1 : 0>
 <Odd : 0>
 <Type : 5 (IMEISV)>
 <Digits : 035609204079514>

From there, you can simply pass the IMEISV value dictionnary at message instantiation:

IEs = {'IMEISV': {'Type': FGSIDTYPE_IMEISV, 'Digit1': 0, 'Digits': '035609204079514'}}
Msg = FGMMSecurityModeComplete(val=IEs)

I understand this does not look very friendly (especially the 1st digit being split from the rest of the BCD-encoded string), but this is how identities are encoded since almost the beginning of cellular networks. I still have this TODO in the code, in case you are interested in contributing: https://github.com/P1sec/pycrate/blob/b3184d74629c3a90a4961049d56154b6e5201a1b/pycrate_mobile/TS24501_IE.py#L708

tariromukute commented 1 year ago

Thank you @p1-bmu, it worked 👍 . However, I don't think I have understood the conventions of it yet though. I see that for IMEISV there is: https://github.com/P1sec/pycrate/blob/09d21d796d988797aec21b49fd98e5bfd0be1d60/pycrate_mobile/TS24501_FGMM.py#L697

From your answer and the line above seems like to create IMEISV we use the IEs for FGSID. Can't seem to win with the NSSAI. I am trying to pass the IEs for SNSSAI without luck or creating the NSSAI. I see that the two have different definitions. NSSAI class references L_NSSAI here https://github.com/P1sec/pycrate/blob/b3184d74629c3a90a4961049d56154b6e5201a1b/pycrate_mobile/TS24501_IE.py#L1277. I don't know what this implies from definition perspective. How do I define it?

I will be more than happy to contribute! I will create an issue and you can assist me in defining and understanding the expected behaviour of the functions encode(), decode() and repr().

p1-bmu commented 1 year ago

In the 5G NAS specification, the Single-NSSAI can be 1, 4, 5 or 8 bytes. So, the 3GPP has defined the Length-prefixed Single-NSSAI (called L_NSSAI in pycrate). And this is what is used in the NSSAI. The NSSAI is basically a sequence of Network Slice identifier, which is defined as a sequence of L_NSSAI in pycrate. The source code is commented with all the references to the specification, so you should be able to understand what classes in pycrate correspond to what structure from the 3GPP specification.