pythonasn.1pyasn1asn1tools

How to work around ASN.1 library not supporting RELATIVE-OID


I’m trying to use the asn1tools Python library to decode and encode BER messages conforming to the Ember+ standard.

That standard’s DTD uses ASN.1’s RELATIVE-OID type in some places. However, asn1tools doesn’t know about this type, probably because the underlying pyasn1 library doesn’t implement it (not yet, there’s a pull request). Which is why I can’t use that DTD in my Python program. But I really have to.

My options, as I see them, are to either create a patched version of pyasn1 with the RELATIVE-OID PR included and make asn1tools work with it, or to somehow build a workaround in the DTD.

I’ve already tried adding RELATIVE-OID ::= [UNIVERSAL 13] OCTET STRING to the DTD, but now asn1tools responds with Expected RELATIVE-OID with tag '2d' at offset 10, but got '0d'. Basically it seems to accept my definition, but makes it “universal constructed 13” while the message tags it as “universal primitive 13”.

Is there a way for me to work around this?

Here are my constraints:

My ASN.1 knowledge is limited and I’m not proficient in writing DTDs. Maybe there’s a way to force the type to being “primitive”? I’m happy for any suggestions. If you’d like to try it out for yourself, use the DTD linked above. Then, use the following Python code:

import asn1tools

spec = asn1tools.compile_files('GlowDtd.asn1')

print(spec.decode('Root', b'`\x80k\x80\xa0\x80b\x80\xa0\x03\x02\x01 \xa1\x03\x02\x01\xff\x00\x00\x00\x00\x00\x00\x00\x00'))
# should result in ('elements', [('element', ('command', {'number': 32, 'options': ('dirFieldMask', -1)}))])

print(spec.decode('Root', b'`\x80k\x80\xa0\x80j\x80\xa0\x03\r\x01\x01\xa2\x80d\x80\xa0\x80b\x80\xa0\x03\x02\x01 \xa1\x03\x02\x01\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
# doesn't work because it uses RELATIVE-OID

Solution

  • Try

    RELATIVE-OID ::= [UNIVERSAL 13] IMPLICIT OCTET STRING