Skip to content
This repository has been archived by the owner on Mar 8, 2024. It is now read-only.

Boilerplate Tuple for ASN1 object? #127

Closed
nickvsnetworking opened this issue Dec 16, 2020 · 8 comments
Closed

Boilerplate Tuple for ASN1 object? #127

nickvsnetworking opened this issue Dec 16, 2020 · 8 comments
Assignees
Labels

Comments

@nickvsnetworking
Copy link

nickvsnetworking commented Dec 16, 2020

Hi folks,

Apologies in advance for what may very well be a dumb question, I've had a read over the Wiki and the outputted code and it's still not clear to me:

I'm playing with the 3GPP SBc Interface which is ASN.1 encoded,

Using the magic of Pycrate I've created a Python file from the ASN1 definition and using it I'm able to take hex data containing an encoded ASN.1 message and turn it into a Python tuple - fantastic.

##Decoding ASN.1 encoded Hex SBc data to a tuple
import binascii
import SBC
sbc_hex = '000240080000010001400105'

sbc_asn1_object = SBC.SBC_AP_PDU_Descriptions.SBC_AP_PDU
sbc_asn1_object.from_aper(binascii.unhexlify(sbc_hex))
sbc_decoded = sbc_asn1_object.get_val()
print(sbc_decoded)

And I'm also able to encode a tuple back into ASN.1 using the set_val() function:

##Encoding a Tuple to ASN.1 encoded Hex SBc data
value = ('initiatingMessage', {'procedureCode': 2, 'criticality': 'ignore', 'value': ('Error-Indication', {'protocolIEs': [{'id': 1, 'criticality': 'ignore', 'value': ('Cause', 5)}]})})
sbc_asn1_object.set_val(value)
print(str(binascii.hexlify(sbc_asn1_object.to_aper())))

Considering the ASN.1 definition defines what elements need to be present and which are optional, I'm wondering if there is a function to generate list the required elements to be fed into set_val?

Manually populating the tuples from the elements in the spec seems above what my mind can process at this point in the year,

SBC.asn.txt
SBC.py.txt

@p1-bmu
Copy link
Contributor

p1-bmu commented Dec 16, 2020

You may re-read https://github.com/P1sec/pycrate/wiki/Using-the-pycrate-asn1-runtime#rrc-3g : I just added a short section on attributes indicating optional components of constructed types. Besides of this, there is no magic however, as a protocol developer, you are required to know the content of the message structures to fill them appropriately.

Moreover, those 2 exiting issues may be related to yours:
#104
#83
They were unfortunately never solved or completed.

Sorry to say, but maybe your development can wait till January.

@p1-bmu
Copy link
Contributor

p1-bmu commented Dec 16, 2020

Maybe you could already contribute to the project by submitting the SBC-AP ASN.1 protocol definition to the pycrate_asn1dir subdirectory ? That would be very nice.
Also apart from this, thank you for all the valuable information you provide on your blog !

@p1-bmu p1-bmu self-assigned this Dec 16, 2020
@nickvsnetworking
Copy link
Author

Thanks @p1-bmu ,

I'll send a PR with the latest ASN1 definition for SBc-AP and some examples when I've got this working.

As you suggested calling the names returned a list of what I needed to populate which is exactly what I was after:
>>> SBC.SBC_AP_PDU_Contents.Write_Replace_Warning_Indication_IEs

<Write-Replace-Warning-Indication-IEs ([SBC-AP-PROTOCOL-IES] CLASS): ASN1Set(root=[{'id': 5, 'criticality': 'reject', 'Value': <Value ([Message-Identifier] BIT STRING)>, 'presence': 'mandatory'}, {'id': 11, 'criticality': 'reject', 'Value': <Value ([Serial-Number] BIT STRING)>, 'presence': 'mandatory'}, {'id': 23, 'criticality': 'reject', 'Value': <Value ([Broadcast-Scheduled-Area-List] SEQUENCE)>, 'presence': 'optional'}], ext=[])>

And with fresh eyes and another read over the documentation I managed to make some progress!

To create a Write-Replace-Warning-Request I need to include the two mandatory protocolIEs which are:

  • Message-Identifier (ID 5 & type BIT STRING size 16)
  • Serial-Number (ID 11 & type BIT STRING size 16)

Which I set in a list named protocol_ies and try and compile using the set_val() function:

import SBC
sbc_asn1_object = SBC.SBC_AP_PDU_Descriptions.SBC_AP_PDU
#id 5 [Message-Identifier] BIT STRING
#id 11 [Serial-Number] BIT STRING
#Contents generated from running: SBC.SBC_AP_PDU_Contents.Write_Replace_Warning_Indication_IEs
protocol_ies = []                                                                #Empty list to store protocol IEs
protocol_ies.append({'id': 5, u'Value': (int(4379), 16)})                        #Message-Identifier
protocol_ies.append({'id': 11, u'Value': (int(4379), 16)})                       #Serial-Number

value = ('initiatingMessage', \
         {'procedureCode': 0, 'criticality': 'ignore', \
          'value': ('Write-Replace-Warning-Request', {'protocolIEs': protocol_ies  })})

sbc_asn1_object.set_val(value)
sbc_hex_out = binascii.hexlify(sbc_asn1_object.to_aper())
sbc_hex_out = sbc_hex_out.decode("utf-8")

However when I try to run it I get the below, which I think relates to the BIT STRING encoding on the Message-Identifier, which I think I've got correct? (With (int(4379), 16) being a 2-tuple of positive int (bit string uint value, bit string length) as per the docs)

    self._cont._safechk_val(v)
  File "/usr/local/lib/python3.8/dist-packages/pycrate-0.4-py3.8.egg/pycrate_asn1rt/asnobj_construct.py", line 748, in _safechk_val
    raise(ASN1ObjErr('{0}: invalid value, {1!r}'.format(self.fullname(), val)))
pycrate_asn1rt.err.ASN1ObjErr: Write-Replace-Warning-Request.protocolIEs._item_: invalid value, {'id': 5, 'Value': (4379, 16)}

Any pointers? I know it's probably something dead simple. (The upper case V in value is used in the SBC.py library, which is compiled from the ASN1 definition attached to the first post.

I parsed some S1 messages with some of the example code, and looked at the Maco-eNodeB-ID as that's also encoded as BIT STRING and confirmed the way I'm formatting it is the same as on the S1 messages, so I'm a bit out of ideas?

PyCrate_issue_127_SBc.py.txt
SBC.py.txt
SBC.asn.txt

@p1-bmu
Copy link
Contributor

p1-bmu commented Jan 12, 2021

This is a special case with all RAN protocols, where the Value field of each ProtocolIE is an OPEN type, and then depend of its id. So you need to provide the reference to the specific type you put in Value:

protocol_ies.append({'id': 5, 'Value': ('Message-Identifier', (4379, 16))})
protocol_ies.append({'id': 11, 'Value': ('Serial-Number', (4379, 16))})

@nickvsnetworking
Copy link
Author

Thanks again @p1-bmu ,

That makes sense we need to define the reference to the type of value,

I just tried running it with the changes you specified, same result though:

File "/usr/local/lib/python3.8/dist-packages/pycrate-0.4-py3.8.egg/pycrate_asn1rt/asnobj_construct.py", line 748, in _safechk_val
    raise(ASN1ObjErr('{0}: invalid value, {1!r}'.format(self.fullname(), val)))

pycrate_asn1rt.err.ASN1ObjErr: Write-Replace-Warning-Request.protocolIEs._item_: invalid value, {'id': 5, 'Value': ('Message-Identifier', (4379, 16))}

Is there something else I'm missing?

I've attached the simplified Python script and contents of SBc.py generated by PyCrate for the ASN.1 dict,

I'd appreciate any pointers, I know I've got a lot more IEs to populate after this, but hopefully once I know how to format one I can format all the others accordingly.

Issue_127.zip

@p1-bmu
Copy link
Contributor

p1-bmu commented Jan 13, 2021

I guess you need to set also the criticality component in each protocolIE (see the definition of the ProtocolIE-Field object).

@p1-bmu
Copy link
Contributor

p1-bmu commented Mar 28, 2022

Any additional feedback @nickvsnetworking ? Or I'll close this.

@nickvsnetworking
Copy link
Author

Hi!
I got there in the end with this, here's the code I used for anyone trying this themselves:

##Write-Replace-Warning-Request
list_of_tais = [\
    {'tai': {'pLMNidentity': bytes.fromhex(plmn_hex), 'tAC': b'\x4BB'}}]

warning_area_list = ('cell-ID-List', [{'pLMNidentity':  bytes.fromhex(plmn_hex), 'cell-ID': (167772161, 28)}, {'pLMNidentity':  bytes.fromhex(plmn_hex), 'cell-ID': (167772162, 28), 'iE-Extensions': [{'id': 199, 'criticality': 'reject', 'extensionValue': ('_unk_004', b'\x99\x99\x99\x99')}]}])
value = ('initiatingMessage', {'procedureCode': 0, 'criticality': 'reject', 'value': \
                               ('Write-Replace-Warning-Request', {'protocolIEs': [\
                                   {'id': 5, 'criticality': 'reject', 'value': ('Message-Identifier', (4370, 16))}, \
                                   {'id': 11, 'criticality': 'reject', 'value': ('Serial-Number', (43995, 16))}, \
                                   #{'id': 14, 'criticality': 'reject', 'value': ('List-of-TAIs', list_of_tais)}, \
                                   #{'id': 15, 'criticality': 'ignore', 'value': ('Warning-Area-List', warning_area_list)}, \
                                   {'id': 10, 'criticality': 'reject', 'value': ('Repetition-Period', 30)}, \
                                   #{'id': 21, 'criticality': 'reject', 'value': ('Extended-Repetition-Period', 8192)}, \
                                   {'id': 7, 'criticality': 'reject', 'value': ('Number-of-Broadcasts-Requested', 1)}, \
                                   {'id': 18, 'criticality': 'ignore', 'value': ('Warning-Type', b'\x01\x02')}, \
                                   #{'id': 17, 'criticality': 'ignore', 'value': ('Warning-Security-Information', b'\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1')}, \
                                   #{'id': 3, 'criticality': 'ignore', 'value': ('Data-Coding-Scheme', (85, 8))}, \
                                   #{'id': 16, 'criticality': 'ignore', 'value': ('Warning-Message-Content', b'\x01' + b'Test Alert Message - Please ignore')}, \
                                   #The phrase Emergency!
                                   {'id': 16, 'criticality': 'ignore', 'value': ('Warning-Message-Content', bytes.fromhex('01c576597e2ebbc7f950a8d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d1000a'))}, \
                                   
                                   #{'id': 19, 'criticality': 'ignore', 'value': ('Omc-Id', b'\x01')}, \
                                   #{'id': 20, 'criticality': 'reject', 'value': ('Concurrent-Warning-Message-Indicator', 'true')}\
                                   ]})})
sbc_asn1_object.set_val(value)
sbc_hex_out = binascii.hexlify(sbc_asn1_object.to_aper())
sbc_hex_out = sbc_hex_out.decode("utf-8")

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants