formats icon indicating copy to clipboard operation
formats copied to clipboard

der: Correct context-specific skipping algorithm

Open dishmaker opened this issue 9 months ago • 8 comments

Looks like currently tag numbers lower than requested are skipped.

Decoder breaks only on higher than expected tag numbers: if !tag.is_context_specific() || tag.number() > tag_number { break }

Commit history: https://github.com/RustCrypto/formats/commit/448d5fb186c1819b0b63bec233094bd551a344d0?diff=unified#diff-7bb94c63666ed02733ba218c24281358f540200bd845b247f1a84a0f95021234R90

https://github.com/RustCrypto/formats/blame/d87ed96b253e1af95533234804a224cbb408099d/der/src/decoder.rs#L195

However, python asn1tools would not skip lower tags when decoding.

In my example the decoder just stops on tag [1] and does not decode [4].

foo.asn

Foo DEFINITIONS ::= BEGIN

    SequenceA ::= SEQUENCE {
        question  IA5String,
        context1  [1] IA5String OPTIONAL,
        context4  [4] IA5String OPTIONAL
    }

    SequenceB ::= SEQUENCE {
        question  IA5String,
        context4  [4] IA5String OPTIONAL
    }

END
import asn1tools
foo = asn1tools.compile_files('foo.asn')
encoded = foo.encode('SequenceA', {
    'question': '0',
    'context1': '1',
    'context4': '4',
    })
print(encoded.hex(' '))

decoded = foo.decode('SequenceB', encoded)
print(decoded)
$ python test_foo.py 
30 0d 16 01 30 a1 03 16 01 31 a4 03 16 01 34
{'question': '0'}

And btw it works when SequenceA is decoded as SequenceA:

$ python test_foo.py 
30 0d 16 01 30 a1 03 16 01 31 a4 03 16 01 34
{'question': '0', 'context1': '1', 'context4': '4'}

So there are 2 possible algorithms:

  • tag.number() > tag_number
  • tag.number() != tag_number

Which one is correct?

dishmaker avatar Mar 15 '25 20:03 dishmaker

I can't find a citation in ITU X.690, which includes surprisingly little information on context-specific fields in general. Perhaps there's a different document I should be consulting.

This situation arises when there are lower-numbered unknown context-specific tags, which seems like a somewhat odd situation to be in to begin with.

tarcieri avatar Mar 18 '25 20:03 tarcieri

I would send to the [email protected] mailing list, that's where the ASN1 folks mostly hang out. x.690 would have been my guess too.

richsalz avatar Mar 19 '25 08:03 richsalz

Sorry, it’s @.@.> name-change isues.

richsalz avatar Mar 19 '25 08:03 richsalz

X.680 is likely what you want.

carl-wallace avatar Mar 19 '25 11:03 carl-wallace

Tony looked at couldn’t find it. If anyone wants to play along, here’s the spec: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.680-202102-I!!PDF-E&type=items

richsalz avatar Mar 19 '25 11:03 richsalz

Perhaps we're not finding anything because there is no special algorithm, and they should be handled like any other tag, in which case the special logic around them should just be removed

tarcieri avatar Mar 19 '25 13:03 tarcieri

What was the rationale for skipping them in the first place?

richsalz avatar Mar 20 '25 02:03 richsalz

Looks like entire philisophy of tag.number() != tag_number in rasn crate is contained in: .ok()

https://github.com/librasn/rasn/blob/3e8e3a26048c229b32a66a48362ea476a2ddd92d/src/ber/de.rs#L747

So it ignores the Err(..) and returns Option<D>::None when tag is invalid?

https://github.com/librasn/rasn/blob/3e8e3a26048c229b32a66a48362ea476a2ddd92d/src/ber/de.rs#L707

dishmaker avatar Mar 24 '25 13:03 dishmaker