Asn.1 Choice

0 views
Skip to first unread message

Nu Alessio

unread,
Aug 3, 2024, 11:26:07 AM8/3/24
to scummisgecom

The 80 there (at offset 0x27) seems to represent that choice. Fair enough - and I get that (per _Encoding_Rules#BER_encoding) the last bit is set in order to indicate that it's "context specific" (i.e. defined by this application/protocol) But how would I know if this is a "simple" or "sasl" auth? What indicates which option of the choice is being used? In this case it looks like the next byte (0x0a) is the length of the string - so this could be an OctetString or something of the sort - but I don't see anything here that indicates what the actual is other than 0x80...

Below you can see output of openssl asn1parse command. The CHOICE members are encoded using so called context specific tags - which means normal tag value is replaced with the one specified in ASN.1 definition for respective item in the CHOICE. The tag has value 0 which implicates the first item in CHOICE is selected. The first choice item is of type OCTET STRING. The value 0 of context specific tag gives you the information about the value type. If there was no context tag, normal OCTET STRING tag would be used.

The '80'H in the encoded message above is called the "identifier octets" (in general it may be more than one octet). This value of the identifier octet(s) indicates that the selected alternative of the CHOICE is "simple", because the five low-order bits of '80'H are '00000'B, which matches the tag number of the tag of "simple" ([0]).

If the sender had selected the "sasl" alternative, the identifier octet would be 'A3'H instead of '80'H. The '3'H in 'A3'H (the five low-order bits) is the tag number of the tag of "sasl" ([3]). The two highest-order bits of the identifier octet are set to '10'B for both alternatives because both [0] and [3] are "context-specific" tags (this just means that these tags don't contain the APPLICATION keyword or the PRIVATE keyword). The next bit of the identifier octet (the "constructed" bit) is set to '0' for "simple" but is set to '1' for "sasl", because the encoding of "sasl" contains nested tags whereas the encoding of "simple" does not contain any nested tags.

The ASN.1 CHOICE type is used when you need to define a type whose value can be one of several different types, depending on which of those types is needed at a particular time. The alternatives in a CHOICE type's list of choices are similar to the elements in a SEQUENCE: identifiers are followed by a type name.

In the following example, the type MessageType is defined as a choice of either an IA5String called text or an INTEGER called codedNumeric. Since IA5String and INTEGER have different tags, the receiver of a value of this type can tell which choice has been made.

In the next example, type Division is defined as a choice of manufacturing, r-and-d, or unassigned. The alternatives include two SEQUENCEs. Because the first two alternatives are both SEQUENCEs, the standard type's tags are replaced with user-defined context-specific tags.

Is there any situation during ASN.1 decoding where you read a tag number and instead of looking if your schema has this tag number on the level of the structure you are in, you look if any nested element has this tag?

Basically, it's a structure with two elements: A choice and a string, both of which are optional. The key to the example is that the choice element contains an element with a tag number equal to the tag number of the optional string.

When using the JAC parser, it will correctly read the tag number 2 in the message and then iterates over the elements in the schema to find the element to associate it with. However, with choice elements it has some extra logic:

Instead of saying "params has tag 1, which is not 2, so this value does not correspond to it", it goes "params has tag 1, which is not 2, but it is a choice element and it contains an element with tag 2, so this has got to be the element I am looking for".

A comment in the parser logic says that this is for cases of untagged choice elements. But this confuses me: According to everything I read, untagged choice elements don't have a default tag but will instead be tagged explicitly; moreover, a choice can never be tagged implicitly.

c. the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or an untagged "DummyReference" (see ITU-T Rec. X.683 ISO/IEC 8824-4, 8.3).

8.9.2 The contents octets shall consist of the complete encoding of one data value from each of the types listed in the ASN.1 definition of the sequence type, in the order of their appearance in the definition, unless the type was referenced with the keyword OPTIONAL or the keyword DEFAULT.

8.9.3 The encoding of a data value may, but need not, be present for a type which was referenced with the keyword OPTIONAL or the keyword DEFAULT. If present, it shall appear in the encoding at the point corresponding to the appearance of the type in the ASN.1 definition.

The ASN.1 CHOICE type is converted into a C or C++ structured type containing an integer for the choice tag value (t) followed by a union (u) of all of the equivalent types that make up the CHOICE elements.

The tag value is simply a sequential number starting at one for each alternative in the CHOICE. A #define constant is generated for each of these values. The format of this constant is T__ where is the name of the ASN.1 production and is the name of the CHOICE alternative. If a CHOICE alternative is not given an explicit name, then is automatically generated by taking the type name and making the first letter lowercase (this is the same as was done for the ASN.1 SEQUENCE type with unnamed elements). If the generated name is not unique, a sequential number is appended to make it unique.

The union of choice alternatives is made of the equivalent C or C++ type definition followed by the element name for each of the elements. The rules for element generation are essentially the same as was described for SEQUENCE above. Constructed types or elements that map to C structured types are pulled out and temporary types are created. Unnamed elements names are automatically generated from the type name by making the first character of the name lowercase.

and are the equivalent C types representing the ASN.1 types and respectively. and represent the names of temporary types that may have been generated as the result of using nested constructed types within the definition.

Choice alternatives may be unnamed, in which case is derived from by making the first letter lowercase. One needs to be careful when nesting CHOICE structures at different levels within other nested ASN.1 structures (SEQUENCEs, SETs, or other CHOICEs). A problem arises when CHOICE element names at different levels are not unique (this is likely when elements are unnamed). The problem is that generated tag constants are not guaranteed to be unique since only the production and end element names are used.

The compiler gets around this problem by checking for duplicates. If the generated name is not unique, a sequential number is appended to make it unique. The compiler outputs an informational message when it does this.

Populating generated CHOICE structures is more complex then for other generated types due to the use of pointers within the union construct. As previously mentioned, the use of pointers with C can be prevented by using the -static command line option. If this is done, the elements within the union construct will be standard inline variable declarations and can be populated directly. Otherwise, the methods listed below can be used to populate the variables.

The recommended way to populate the pointer elements is to declare variables of the embedded type to be used on the stack prior to populating the CHOICE structure. The embedded variable would then be populated with the data to be encoded and then the address of this variable would be plugged into the CHOICE union pointer field.

It is also possible to allocate dynamic memory for the CHOICE union option variable; but one must be careful to release this memory when done with the structure. If the built in memory-management functions/macros are used (rtxMem), all memory used for the variables is automatically released when rtxMemFree is called.

In general everything about parsing is driven by providing different typeparameters to Parser.read_element. Some types implement theAsn1Readable trait directly on a basic type, as seen with u64 or&[u8] (OCTET STRING), while others use wrapper types which simplyprovide ASN.1 encoding and decoding for some other type (PrintableStringor UtcTime). There are also types such as Implicit and Explicit forhandling tagged values, Choice1, Choice2, and Choice3 available forchoices, and Option for handling OPTIONAL values.

This document introduces the ASN.1 (Abstract Syntax Notation) framework delivered as part of the Harmony classlibrary. This document provides an overview of ASN.1 types and encoding rules with focus on the characteristics of the current implementation. The document gives details on the framework design and provides an overall description of the ASN.1 package.

The target audience for the document includes a wide community of engineers interested in using ASN.1 and in further work with the product to contribute to its development. The document assumes that readers are familiar with the ASN.1 notation and the Java* programming language.

ASN.1 (Abstract Syntax Notation One) is an international standard of notation used to specify data structures with a high level of abstraction, which is reflected in the ASN.1 specification [2]. ASN.1 is fully platform- and language-independent. ASN.1 goes with the encoding rules, which determine how to represent a value of an abstract type as a string of octets [3].

c80f0f1006
Reply all
Reply to author
Forward
0 new messages