ASN.1
Previous: Structured Types Up: Abstract Syntax Notation Next: Useful Types


Tagged Types

Every ASN.1 type has a tag. In Basic Encoding Rules (BER, X.690), tags serve as type identifiers, and every value is encoded with a tag. In Octet Encoding Rules (OER, X.696), tags are similarly used, but only for the purpose of identifying which alternative in a CHOICE is present. For the most part, tags are otherwise irrelevant, only being used for things users really don't need to worry about, such as determining the canonical ordering for the (otherwise unordered) SET and SET OF types, when canonical encoding rules are being used (e.g. CER, DER, canonical PER, canonical XER). Still, even if tags are irrelevant in your case, you can't entirely ignore them because the base ASN.1 specification (X.680) imposes certain requirements on SEQUENCE, SET and CHOICE types relative to tagging. However, as we'll see, specifying automatic tagging for your ASN.1 module is a very easy way to ensure those requirements are satisfied, and then you really can forget about tagging.

Syntactically, a TaggedType is a Type that consists of a tag and a type. The new type created by this construct, aside from the tag, is entirely equivalent to the type being tagged. The notation consists of three elements: a user-defined tag, possibly followed by IMPLICIT or EXPLICIT, followed by the Type being tagged.

The user-defined tag consists of a class and a class number, contained in braces. The class is UNIVERSAL, APPLICATION, PRIVATE, or empty (the "context-specific" class). The UNIVERSAL class is restricted to the ASN.1 built-in types. It defines an application-independent data type that must be distinguishable from all other data types. The other three classes are user defined. The APPLICATION class distinguishes data types that have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within a particular organization or country. The context-specific class distinguishes members of a sequence or set, or the alternatives of a CHOICE.

Here are some TaggedType examples:

		PrivateType ::= [PRIVATE 5] SEQUENCE { ... }
		
		TagExample ::= [APPLICATION 9] IMPLICIT SEQUENCE {
			elem1 [0] INTEGER,              -- "context-specific" class
			elem2 [1] EXPLICIT INTEGER,     -- use of EXPLICIT with tag
			elem3 [2] IMPLICIT INTEGER      -- use of IMPLICIT with tag
		}
	

Explicit vs. Implicit Tags and the Tag Default

Consider again TagExample above. elem2 uses EXPLICIT. What does that mean? It basically has meaning only for BER, where it means that the original tag (which is UNIVERSAL 2, for INTEGER) should still be explicitly encoded, so that elem2's encoding will first have a CONTEXT-SPECIFIC 1 tag, and then a UNIVERSAL 2 tag. By constrast, elem3 uses IMPLICIT, which means that in BER the original tag will NOT be encoded - we'll implicitly know the type is INTEGER without having the UNIVERSAL 2 tag encoded. The implicit vs. explicit distinction is basically irrelevant unless BER is being used.

What about elem1? It has neither EXPLICIT nor IMPLICIT. In this case, the module's TagDefault comes into play. The following examples show the four ways to specify the TagDefault in a module definition:

  1. MyModule DEFINITIONS ::= BEGIN 
    Tags without IMPLICIT or EXPLICIT are treated as if EXPLICIT were specified.
  2. MyModule DEFINITIONS EXPLICIT TAGS ::= BEGIN 
    Tags without IMPLICIT or EXPLICIT are treated as if EXPLICIT were specified.
  3. MyModule DEFINITIONS IMPLICIT TAGS ::= BEGIN 
    Tags without IMPLICIT or EXPLICIT are treated as if IMPLICIT were specified, except in a few special cases where EXPLICIT is required.
  4. MyModule DEFINITIONS AUTOMATIC TAGS ::= BEGIN 
    Tags without IMPLICIT or EXPLICIT are treated as if IMPLICIT were specified, except in a few special cases where EXPLICIT is required.

    Components of SEQUENCE, SET and CHOICE are automatically assigned tags that satisfy tag requirements imposed on those types, as if they were written with IMPLICIT except when EXPLICIT is required.

Particularly if you are not using BER, and probably even if you are, the simplest thing to do is to use automatic tagging.

Illustration Of Tagging Requirements

Suppose seats in AirlineFlight of the previous Section were of type SET rather than sequence. Four different ways to write seats with (or without tags) are shown below.

  a)  -- Valid?? 
  	seats  SET
         {
          maximum    INTEGER,
          occupied   INTEGER,
          vacant     INTEGER
         }

  b)   seats  SET
         {
          maximum   [APPLICATION 0] INTEGER,
          occupied  [APPLICATION 1] INTEGER,
          vacant    [APPLICATION 2] INTEGER
         }

  c)   seats  SET
         {
          maximum   [APPLICATION 0] IMPLICIT INTEGER,
          occupied  [APPLICATION 1] IMPLICIT INTEGER,
          vacant    [APPLICATION 2] IMPLICIT INTEGER
         }

  d)   seats  SET
         {
          maximum   [0] INTEGER,
          occupied  [1] INTEGER,
          vacant    [2] INTEGER
         }

Figure: Using tagging to specify SET components.

The components of a SET must have unique tags, since encoding rules might allow encoding the components in any order. Examples b-d clearly satisfy that requirement. Example a) satisfies the requirement only if automatic tagging was specified for the module, otherwise, since each component has the same type, each component would have the same tag, and there would be ambiguity.

Considerations For Choosing EXPLICIT vs. IMPLICIT Tags



Previous: Structured Types Up: Abstract Syntax Notation Next: Useful Types


This site was developed from:
Computer Networks and Open Systems
An Application Development Perspective

by
Lillian N. Cassel
Richard H. Austing

Jones & Bartlett Publisher
ISBN 0-7637-1122-5

This site is hosted by:


Real World ASN.1 and XML Solutions