ASN.1
Previous:
Structured Types Up:
Abstract Syntax Notation
Next: Useful 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 }
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:
MyModule DEFINITIONS ::= BEGINTags without
IMPLICIT
or EXPLICIT
are treated as if EXPLICIT
were specified.
MyModule DEFINITIONS EXPLICIT TAGS ::= BEGINTags without
IMPLICIT
or EXPLICIT
are treated as if EXPLICIT
were specified.
MyModule DEFINITIONS IMPLICIT TAGS ::= BEGINTags without
IMPLICIT
or EXPLICIT
are treated as if IMPLICIT
were specified, except
in a few special cases where EXPLICIT
is required.
MyModule DEFINITIONS AUTOMATIC TAGS ::= BEGINTags 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.
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.
EXPLICIT
vs. IMPLICIT
TagsIMPLICIT
makes for a smaller BER encoding, because it omits tags.
However, omitting those tags means that the ASN.1 schema is definitely
required to know what type some values are.
Consistent use of EXPLICIT
means the BER encoding preserves
all of the UNIVERSAL
tags. That means that more
information can be gleaned from the encoding even without the ASN.1
schema. It also means certain kinds of errors (e.g. value of an
incorrect type) can be detected.
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 |