der: Correct context-specific skipping algorithm
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_numbertag.number() != tag_number
Which one is correct?
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.
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.
Sorry, it’s @.@.> name-change isues.
X.680 is likely what you want.
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
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
What was the rationale for skipping them in the first place?
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