asn.1derber

Encoding of implicit and explicit tags in ASN.1


I am trying to understand how IMPLICIT and EXPLICIT tags are actually encoded in the DER binary form.

The basic examples are clear. Plain integer,

x INTEGER ::= 5

is encoded as a TLV triple 02 01 05. In

x [2] IMPLICIT INTEGER ::= 5

implicit tag 82 replaces the existing tag 02 and forms another TLV: 82 01 05, and in

x [3] EXPLICIT INTEGER ::= 5

a wrapper is added around the original TLV: A3 03 02 01 05.

Now I am looking at a more complicated case

30 42 A1 40 30 0D 82 0B  77 77 77 2E 62 61 64 2E
6F 72 67 30 09 82 07 62  61 64 2E 63 6F 6D 30 0D
81 0B 62 61 64 40 62 61  64 2E 6F 72 67 30 09 81
07 62 61 64 2E 63 6F 6D  30 0A 87 08 0A 00 00 00
FF 00 00 00

which gets decoded into

SEQUENCE {
  [1] {
    SEQUENCE {
      [2] www.bad.org
    }
    SEQUENCE {
      [2] bad.com
    }
    SEQUENCE {
      [1] bad@bad.org
    }
    SEQUENCE {
      [1] bad.com
    }
    SEQUENCE {
      [7] 0A000000FF000000
    }
  }
}

My question is, how do I know whether A1 is an implicit tag [1] IMPLICIT SEQUENCE, which replaced the original tag 10, and which contains five TLV elements (sequences), or an explicit tag that wraps around these five elements? What is A1?

Can explicit tag wrap several TLV elements?

Is this correct that the "constructed" flag (bit 6) indicates whether the tag is explicit or implicit? Or do I need to look at the lengths of the wrapper and the thing being wrapped?

I am not assuming that the binary data is correct, so another possibility is that A1 40 wraps around the following sequence 30 0D ..., the length does not match and the data must be rejected.


Solution

  • You are asking several questions, but each of them deserves a separate answer.

    A tag is not implicit or explicit per se. "Tagging" (the operation that adds a tag to a type) is either implicit or explicit.

    Consider the fact that in ASN.1 each primitive type (e.g., INTEGER, BOOLEAN) or type constructor except CHOICE (e.g., SEQUENCE) has a built-in "universal" tag. For example, the type INTEGER has the built-in tag UNIVERSAL 2, the type OBJECT IDENTIFIER has the built-in tag UNIVERSAL 6, every SEQUENCE type has the built-in tag UNIVERSAL 16, and so on. This is not specific to BER/DER. It's a property of the types themselves.

    When a type occurs as a component of another type (e.g., SEQUENCE or CHOICE), it often (but not always) gets assigned another tag. The new tag can either replace the existing tag or be inserted before the existing tag. This is what implicit tagging and explicit tagging are. In implicit tagging, the new tag replaces the existing tag of the type to which it's applied. In explicit tagging, the new tag is prefixed to the existing tag. This is also not specific to BER/DER, it's a feature of ASN.1. Some encoding rules (BER, DER, and OER to a limited extent) use the tags in the encodings, while other encoding rules (PER, JER) don't include the tags in the encodings. Still, the tags exist independently of the encoding rules being used.

    Whether implicit or explicit tagging is used for a given type depends on a few things. First, there is the default tagging specified in the module header (EXPLICIT TAGS, IMPLICIT TAGS, AUTOMATIC TAGS), which establishes a default tagging mode for the types present in the module. (The "default default" is explicit tagging.) Second, one can override the default tagging of the module for a particular type by using the keyword IMPLICIT or EXPLICIT after the ']'. Third, in some cases the tagging is necessarily explicit.

    If you specify AUTOMATIC TAGS in the module header, a process will generate and apply consecutive tags, starting from "context-specific" 0, to each component of every sequence type, set type, and choice type, that doesn't contain a literal tag in any of its components. The automatic tagging process applies implicit tagging, which means that each generated tag will replace the existing tag.

    There are a few restrictions and some special cases. One is that CHOICE types don't have a universal tag of their own, so it's impossible to apply implicit tagging to a CHOICE type that is not preceded by a literal tag (there is no tag to replace). If you don't use AUTOMATIC TAGS and don't add a new tag to a choice type, the choice type will remain without a tag of its own. In BER/DER, the decoder can still detect the presence of an untagged choice type by looking at the upcoming tag, which belongs to the choice alternative that is present.

    The above shows that there is no possible ambiguity in how a BER/DER decoder will interpret the next tag within an encoding. The tagging process assigns well defined tags (usually one or two tags, or possibly none in the case of an untagged choice type) to each type in the module, including the component types of a complex type. As stated above, those tags are a property of each type present in the ASN.1 schema. In BER and DER, the encoder will just insert all the tags of the type of each value that it is encoding. If the type of the value has one tag, the encoder will produce one TLV. If the type of the value has two tags, the encoder will produce two nested TLVs. It's actually pretty simple. The decoder will know what to expect.