etingof / pyasn1

Generic ASN.1 library for Python
http://snmplabs.com/pyasn1
BSD 2-Clause "Simplified" License
241 stars 118 forks source link

Trouble decoding IEC 61850 GOOSE PDU data #149

Open idahogray opened 5 years ago

idahogray commented 5 years ago

I am having trouble decoding IEC 61850 GOOSE PDU data. This data is encoded using BER. You can find the ASN.1 notation that wireshark uses here: https://github.com/boundary/wireshark/blob/master/asn1/goose/goose.asn. My repository is located on gitub: https://github.com/keith-gray-powereng/goose. The pyasn.1 classes corresponding to the ASN.1 notation live in the https://github.com/keith-gray-powereng/goose/blob/master/goose/goose_pdu.py file.

The last three tests in https://github.com/keith-gray-powereng/goose/blob/master/tests/test_goose.py are generating errors while trying to decode the data. These tests cover decoding larger pieces of the data that make use of "SEQUENCE (OF)".

One example of a failing test is as follows. The encoded_data is taken straight from a captured GOOSE packet.

from pyasn1 import debug
    debug.setLogger(debug.Debug('all'))
    encoded_data = (
        "\xa2\x12"
        "\x83\x01\x00\x84\x03\x03\x00\x00\x91\x08\x5a\xaa\xe0\xa4\x6f\xf3"
        "\x5e\x92"
    )
    expected = False
    iec61850_goose_pdu = IECGoosePDU().clone()
    all_data = iec61850_goose_pdu.getComponentByName('allData')
    data_item_1 = all_data.getComponentByPosition(0)
    structure = data_item_1.getComponentByName('structure')
    import pdb; pdb.set_trace()
    decoded_data, unprocessed_trail = decoder.decode(
        encoded_data,
        asn1Spec=Data().clone()
    )
    assert expected == decoded_data

This is expected to decode into a SEQUENCE OF a boolean, a bit-string, and a utc-time which are all members of Data.

The generated error is:

PyAsn1Error: <TagSet object at 0x9c69908 tags 128:0:3-128:32:2> not in asn1Spec: <IECGoosePDU schema object at 0x9c692b0 componentType=<NamedTypes object at 0x9c3ceb8 types <NamedType object at 0x9c32e48 type gocbRef=<VisibleString schema object at 0x9c32ef0 tagSet <TagSet object at 0x9c32f28 tags 128:0:0> encoding us-ascii>>, <NamedType object at 0x9c32e80 type timeAllowedtoLive=<Integer schema object at 0x9c3c0b8 tagSet <TagSet object at 0x9c3c0f0 tags 128:0:1>>>, <NamedType object at 0x9c3c048 type datSet=<VisibleString schema object at 0x9c3c1d0 tagSet <TagSet object at 0x9c3c208 tags 128:0:2> encoding us-ascii>>, <OptionalNamedType object at 0x9c3c160 type goID=<VisibleString schema object at 0x9c3c358 tagSet <TagSet object at 0x9c3c390 tags 128:0:3> encoding us-ascii>>, <NamedType object at 0x9c3c2e8 type t=<UtcTime schema object at 0x9c3c4a8 subtypeSpec <ValueSizeConstraint object at 0x9af64a8 consts 8, 8> tagSet <TagSet object at 0x9c3c4e0 tags 128:0:4> encoding iso-8859-1>>, <NamedType object at 0x9c3c438 type stNum=<Integer schema object at 0x9c3c5f8 tagSet <TagSet object at 0x9c3c630 tags 128:0:5>>>, <NamedType object at 0x9c3c588 type sqNum=<Integer schema object at 0x9c3c710 tagSet <TagSet object at 0x9c3c748 tags 128:0:6>>>, <NamedType object at 0x9c3c6a0 type test=<Boolean value object at 0x9c3c860 namedValues <NamedValues object 0x647d908 enums True=1, False=0> subtypeSpec <ConstraintsIntersection object at 0x647d898 consts <SingleValueConstraint object at 0x647d7f0 consts 0, 1>> tagSet <TagSet object at 0x9c3c898 tags 128:0:7> payload [False]>>, <NamedType object at 0x9c3c7f0 type confRev=<Integer schema object at 0x9c3c9b0 tagSet <TagSet object at 0x9c3c9e8 tags 128:0:8>>>, <NamedType object at 0x9c3c940 type ndsCom=<Boolean value object at 0x9c3cb00 namedValues <NamedValues object 0x647d908 enums True=1, False=0> subtypeSpec <ConstraintsIntersection object at 0x647d898 consts <SingleValueConstraint object at 0x647d7f0 consts 0, 1>> tagSet <TagSet object at 0x9c3cb38 tags 128:0:9> payload [False]>>, <NamedType object at 0x9c3ca90 type numDatSetEntries=<Integer schema object at 0x9c3cc50 tagSet <TagSet object at 0x9c3cc88 tags 128:0:10>>>, <NamedType object at 0x9c3cbe0 type allData=<AllData value object at 0x9c3cdd8 componentType=<Data schema object at 0x9c32dd8 componentType=<NamedTypes object at 0x9c226d8 types <NamedType object at 0x9c11240 type array=<SequenceOf value object at 0x9c112e8 componentType=<Data schema object at 0x9c110b8 componentType=<NamedTypes object at 0x64a4eb8 types > subtypeSpec=<ConstraintsIntersection object at 0x64a4fd0> sizeSpec=<ConstraintsIntersection object at 0x64b3080 consts <ValueSizeConstraint object at 0x64b3048 consts 1, 1>> tagSet=<TagSet object at 0x64a4e48 untagged>> tagSet=<TagSet object at 0x9c11320 tags 128:32:1> subtypeSpec=<ConstraintsIntersection object at 0x64a4550> sizeSpec=<ConstraintsIntersection object at 0x64a4588>>>, <NamedType object at 0x9c11400 type structure=<SequenceOf value object at 0x9c114a8 componentType=<Data schema object at 0x9c11278 componentType=<NamedTypes object at 0x64a4eb8 types > subtypeSpec=<ConstraintsIntersection object at 0x64a4fd0> sizeSpec=<ConstraintsIntersection object at 0x64b3080 consts <ValueSizeConstraint object at 0x64b3048 consts 1, 1>> tagSet=<TagSet object at 0x64a4e48 untagged>> tagSet=<TagSet object at 0x9c114e0 tags 128:32:2> subtypeSpec=<ConstraintsIntersection object at 0x64a4550> sizeSpec=<ConstraintsIntersection object at 0x64a4588>>>, <NamedType object at 0x9c11438 type boolean=<Boolean schema object at 0x9c115f8 namedValues <NamedValues object 0x647d908 enums True=1, False=0> subtypeSpec <ConstraintsIntersection object at 0x647d898 consts <SingleValueConstraint object at 0x647d7f0 consts 0, 1>> tagSet <TagSet object at 0x9c11630 tags 128:0:3>>>, <NamedType object at 0x9c11588 type bit-string=<BitString schema object at 0x9c11710 tagSet <TagSet object at 0x9c11748 tags 128:0:4>>>, <NamedType object at 0x9c116a0 type integer=<Integer schema object at 0x9c11898 tagSet <TagSet object at 0x9c118d0 tags 128:0:5>>>, <NamedType object at 0x9c11828 type unsigned=<Integer schema object at 0x9c119b0 tagSet <TagSet object at 0x9c119e8 tags 128:0:6>>>, <NamedType object at 0x9c11940 type floating-point=<FloatingPoint schema object at 0x9c11b00 tagSet <TagSet object at 0x9c11b38 tags 128:0:7> encoding iso-8859-1>>, <NamedType object at 0x9c11a90 type real=<Real schema object at 0x9c11c88 tagSet <TagSet object at 0x9c11cc0 tags 128:0:8>>>, <NamedType object at 0x9c11c18 type octet-string=<OctetString schema object at 0x9c11da0 tagSet <TagSet object at 0x9c11dd8 tags 128:0:9> encoding iso-8859-1>>, <NamedType object at 0x9c11d30 type visible-string=<VisibleString schema object at 0x9c11f28 tagSet <TagSet object at 0x9c11f60 tags 128:0:10> encoding us-ascii>>, <NamedType object at 0x9c11eb8 type binary-time=<TimeOfDay schema object at 0x9c220b8 subtypeSpec <ConstraintsUnion object at 0x64d1c18 consts <ValueSizeConstraint object at 0x64d1048 consts 4, 4>, <ValueSizeConstraint object at 0x64d10f0 consts 6, 6>> tagSet <TagSet object at 0x9c220f0 tags 128:0:12> encoding iso-8859-1>>, <NamedType object at 0x9c22048 type bcd=<Integer schema object at 0x9c22208 tagSet <TagSet object at 0x9c22240 tags 128:0:13>>>, <NamedType object at 0x9c22198 type booleanArray=<BitString schema object at 0x9c22320 tagSet <TagSet object at 0x9c22358 tags 128:0:14>>>, <NamedType object at 0x9c222b0 type objId=<ObjectIdentifier schema object at 0x9c224a8 tagSet <TagSet object at 0x9c224e0 tags 128:0:15>>>, <NamedType object at 0x9c22438 type mMSString=<MMSString schema object at 0x9c225c0 tagSet <TagSet object at 0x9c225f8 tags 128:0:16> encoding utf-8>>, <NamedType object at 0x9c22550 type utc-time=<UtcTime schema object at 0x9c22748 subtypeSpec <ValueSizeConstraint object at 0x9af64a8 consts 8, 8> tagSet <TagSet object at 0x9c22780 tags 128:0:17> encoding iso-8859-1>>> subtypeSpec=<ConstraintsIntersection object at 0x64a4fd0> sizeSpec=<ConstraintsIntersection object at 0x64b3080 consts <ValueSizeConstraint object at 0x64b3048 consts 1, 1>> tagSet=<TagSet object at 0x64a4e48 untagged>> tagSet=<TagSet object at 0x9c3ce10 tags 128:32:11> subtypeSpec=<ConstraintsIntersection object at 0x64a4550> sizeSpec=<ConstraintsIntersection object at 0x64a4588>>>, <OptionalNamedType object at 0x9c3cd68 type security=<OctetString schema object at 0x9c3cf28 tagSet <TagSet object at 0x9c3cf60 tags 128:0:12> encoding iso-8859-1>>> tagSet=<TagSet object at 0x9c69048 tags 64:32:1> subtypeSpec=<ConstraintsIntersection object at 0x64a4a20> sizeSpec=<ConstraintsIntersection object at 0x64a4a58>>

The following log is also generated:

> debug.py                    49 DEBUG    running pyasn1 0.4.4, debug flags all
> debug.py                    49 DEBUG    debug category 'all' enabled
> debug.py                    49 DEBUG    decoder called at scope  with state 0, working with up to 20 octets of substrate:
> 00000: A2 12 83 01 00 84 03 03 00 00 91 08 5A AA E0 A4
> 00016: 6F F3 5E 92
> debug.py                    49 DEBUG    tag decoded into <TagSet object at 0x9c69630 tags 128:32:2>, decoding length
> debug.py                    49 DEBUG    value length decoded into 18, payload substrate is:
> 00000: 83 01 00 84 03 03 00 00 91 08 5A AA E0 A4 6F F3
> 00016: 5E 92
> debug.py                    49 DEBUG    codec <none> chosen by ASN.1 spec, decoding as explicit tag
> debug.py                    49 DEBUG    codec ExplicitTagDecoder chosen, decoding value
> debug.py                    49 DEBUG    decoder called at scope ? with state 0, working with up to 18 octets of substrate:
> 00000: 83 01 00 84 03 03 00 00 91 08 5A AA E0 A4 6F F3
> 00016: 5E 92
> debug.py                    49 DEBUG    tag decoded into <TagSet object at 0x9c69908 tags 128:0:3-128:32:2>, decoding length
> debug.py                    49 DEBUG    value length decoded into 1, payload substrate is:
> 00000: 00
> debug.py                    49 DEBUG    codec <none> chosen by ASN.1 spec, decoding as explicit tag
> debug.py                    49 DEBUG    codec <none> chosen, decoding as failure

I would appreciate any help with trying to figure this out. Please let me know if there is any more information I can provide.

idahogray commented 5 years ago

Just a small update...I tried both master and the fix-constructed-default branch with no change.

CaptainKaboom commented 5 years ago

Hi, I have the same issue... Have you got any solutions ?

idahogray commented 5 years ago

I haven't found a solution.

CaptainKaboom commented 5 years ago

I found that the function decode() of the pyasn1 library has an issue to decode the type "structure" inside the "Data" field in the GOOSE message. It seems that the function can't read in a "recursive way" over the Data field.

So I found a solution for my purpose, but it is very limited. I have to create as many Data classes in the goose_pdu file as the number of structure in the datas of the GOOSE message.

Thanks for your answer, and sorry for my English.

etingof commented 4 years ago

Sorry for it has taken so long to get to this issue!

I've just cloned your repo and run the tests - none of them fail for me. My setup is Python 3.7.1 and:

$ pip freeze
-e git+https://github.com/keith-gray-powereng/goose.git@e3dcdc18976607d41359d36dd41055e8184c0582#egg=goose
pyasn1==0.4.7
scapy==2.4.3

Is this problem already solved?

kartikeyj96 commented 2 years ago

I found that the function decode() of the pyasn1 library has an issue to decode the type "structure" inside the "Data" field in the GOOSE message. It seems that the function can't read in a "recursive way" over the Data field.

So I found a solution for my purpose, but it is very limited. I have to create as many Data classes in the goose_pdu file as the number of structure in the datas of the GOOSE message.

Thanks for your answer, and sorry for my English.

Can you explain it a little bit? or if you don't mind, can you share the code?