gvij
gvij

Reputation: 447

ASN.1 unmarshalling wireshark hex code using go structs

I am trying to decode the following hex code from a tcp dump. 18001c3080a080800106830200e20000a28080010181010d00008301650000

The ASN.1 definition that I am trying to decode is of the following format:

ConnectionEstablishedReply  ::= SEQUENCE {
message         MessageFields,
nackReason      NackReason OPTIONAL,
interfaceVersion    InterfaceVersion,
mediatorId      INTEGER (1..65535),
waitForCommit       BOOLEAN OPTIONAL,
...
}

MessageFields       ::= SEQUENCE {
messageSequence     INTEGER (1..65535),
bsId    INTEGER (1..65535) OPTIONAL,
neID        INTEGER(0..16777216) OPTIONAL, -- unsigned int
nelementID  INTEGER(0..16777216) OPTIONAL, -- unsigned int
...
}

InterfaceVersion        ::= SEQUENCE {
major           INTEGER (1..100),
minor           INTEGER (0..100)
}

As I understand, the tag or type for ConnectionEstablishedReply from the tcp dump is 24, whereas the tag for a sequence is 16. The mismatch in these tags is what is causing the error:

Error while unmarshalling: asn1: structure error: tags don't match (16 vs {class:0 tag:24 length:0 isCompound:false}) {optional:false explicit:false application:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} ConnectionEstablishedReply @2

The go structs corresponding to these elements are:

type ConnectionEstablishedReply struct {
    Message          MessageFields    
    NackReason       NackReason       `asn1:"optional"`
    InterfaceVersion InterfaceVersion 
    MediatorId       int              
    WaitForCommit    bool             `asn1:"optional"`
}

and likewise for other elements.

Unmarshalling code:

res := structs.ConnectionEstablishedReply{}
data, _ := hex.DecodeString("18001c3080a080800106830200e20000a28080010181010d00008301650000")
_, err := asn1.Unmarshal(data, &res)
if err != nil {
    fmt.Println("Error while unmarshalling: ", err)
}
fmt.Println(res)

In a previous question (ASN.1 Unmarshalling using go structs gives tags don't match error) with a similar problem, I was told that I should be using implicit asn.1 tags with these structs. However, these tags don't work for these application specific elements.

FYI, when only 3080a080800106830200e20000a28080010181010d00008301650000 (message part) of the above mentioned hex stream is fed into http://asn1-playground.oss.com/, the decoding is successful. Whereas, the same stream when used in go code gives:

indefinite length found (not DER)

Which asn.1 tags should be used in these go structs so that unmarshalling is successful?

Upvotes: 0

Views: 806

Answers (1)

YaFred
YaFred

Reputation: 10008

It's not a problem with tags. It's a problem with the ability of your lib to decode indefinite length. For constructed types (such as sequences) you can either use:

Tag Length Value (also called definite length form)

or

Tag '80'H Value '0000'H (also called indefinite length form)

The message you receive uses indefinite length for all sequences. Your lib does not support it because it sticks to Distinguished Encoding Rules (DER) where this form is not allowed. If it was supported by your lib, your message part would be decoded like this ...

T: 30 (CONSTRUCTED_UNIVERSAL_16) 
L: 80 (indefinite)   
   T: a0 (CONSTRUCTED_CONTEXT_0)
   L: 80 (indefinite)
     T: 80 (PRIMITIVE_CONTEXT_0)
     L: 1
     V: 06
     T: 83 (PRIMITIVE_CONTEXT_3)
     L: 2
     V: 00 e2
   0000: end of content

   T: a2 (CONSTRUCTED_CONTEXT_2)   
   L: 80 (indefinite)
      T: 80 (PRIMITIVE_CONTEXT_0)
      L: 1
      V: 01
      T: 81 (PRIMITIVE_CONTEXT_1)
      L: 1
      V: 0d
   0000: end of content 

   T: 83 (PRIMITIVE_CONTEXT_3)   
   L: 1   
   V: 65 
0000: end of content

Upvotes: 1

Related Questions