From e95095457c4d83c02850b811fb28711c0b3d1c23 Mon Sep 17 00:00:00 2001 From: xsipewe Date: Tue, 14 Apr 2015 23:21:36 +0200 Subject: Update asn1 documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Language cleaned up by the technical writers xsipewe and tmanevik from Combitech. Proofreading and corrections by Björn Gustavsson. --- lib/asn1/doc/src/asn1_getting_started.xml | 1290 +++++++++++++++++++++++++++++ 1 file changed, 1290 insertions(+) create mode 100644 lib/asn1/doc/src/asn1_getting_started.xml (limited to 'lib/asn1/doc/src/asn1_getting_started.xml') diff --git a/lib/asn1/doc/src/asn1_getting_started.xml b/lib/asn1/doc/src/asn1_getting_started.xml new file mode 100644 index 0000000000..1a9c279191 --- /dev/null +++ b/lib/asn1/doc/src/asn1_getting_started.xml @@ -0,0 +1,1290 @@ + + + + +
+ + 19972013 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Getting Started + Kenneth Lundin + + 1999-03-25 + D + asn1_getting_started.xml +
+ +
+ Example +

The following example demonstrates the basic functionality used to + run the Erlang ASN.1 compiler.

+

Create a file named People.asn containing the following:

+
+People DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+  Person ::= SEQUENCE {
+    name PrintableString,
+    location INTEGER {home(0),field(1),roving(2)},
+    age INTEGER OPTIONAL
+  }
+END      
+

This file must be compiled before it can be used. + The ASN.1 compiler checks that the syntax is correct and that the + text represents proper ASN.1 code before generating an abstract + syntax tree. The code-generator then uses the abstract syntax + tree to generate code.

+

The generated Erlang files are placed in the current directory or + in the directory specified with option {outdir,Dir}.

+

The following shows how the compiler + can be called from the Erlang shell:

+ +
+1> asn1ct:compile("People", [ber]).
+ok
+2>      
+ +

Option verbose can be added to get information + about the generated files:

+
+2> asn1ct:compile("People", [ber,verbose]).
+Erlang ASN.1 compiling "People.asn" 
+--{generated,"People.asn1db"}--
+--{generated,"People.hrl"}--
+--{generated,"People.erl"}--
+ok
+3>      
+ +

ASN.1 module People is now accepted and the + abstract syntax tree is saved in file People.asn1db. + The generated Erlang code is compiled using the Erlang compiler + and loaded into the Erlang runtime system. There is now an API + for encode/2 and decode/2 in module + People, which is called like:

+ , )]]> +

+ or

+, )]]>

+ +

Assume that there is a network + application that receives instances of the ASN.1 defined + type Person, modifies, and sends them back again:

+ + +receive + {Port,{data,Bytes}} -> + case 'People':decode('Person',Bytes) of + {ok,P} -> + {ok,Answer} = 'People':encode('Person',mk_answer(P)), + Port ! {self(),{command,Answer}}; + {error,Reason} -> + exit({error,Reason}) + end + end, +

In this example, a series of bytes is received from an + external source and the bytes are then decoded into a valid + Erlang term. This was achieved with the call + 'People':decode('Person',Bytes), which returned + an Erlang value of the ASN.1 type Person. Then an answer was + constructed and encoded using + 'People':encode('Person',Answer), which takes an + instance of a defined ASN.1 type and transforms it to a + binary according to the BER or PER encoding rules.

+

The encoder and decoder can also be run from the shell:

+
+2> Rockstar = {'Person',"Some Name",roving,50}.
+{'Person',"Some Name",roving,50}
+3> {ok,Bin} = 'People':encode('Person',Rockstar).
+{ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,
+      2,1,50>>}
+4> {ok,Person} = 'People':decode('Person',Bin).
+{ok,{'Person',"Some Name",roving,50}}
+5>      
+ +
+ Module Dependencies +

It is common that ASN.1 modules import defined types, values, and + other entities from another ASN.1 module.

+

Earlier versions of the ASN.1 compiler required that modules + that were imported from had to be compiled before the module + that imported. This caused problems when ASN.1 modules had circular + dependencies.

+

Referenced modules are now parsed when the compiler finds an + entity that is imported. No code is generated for + the referenced module. However, the compiled modules rely on + that the referenced modules are also compiled.

+
+
+ +
+ ASN.1 Application User Interface +

The ASN.1 application provides the following two + separate user interfaces:

+ + +

The module asn1ct, which provides the compile-time functions + (including the compiler)

+
+ +

The module asn1rt_nif, which provides the runtime functions + for the ASN.1 decoder for the BER back end

+
+
+

The reason for this division of the interfaces into compile-time + and runtime + is that only runtime modules (asn1rt*) need to be loaded in + an embedded system. +

+ +
+ Compile-Time Functions +

The ASN.1 compiler can be started directly from the command line + by the erlc program. This is convenient when compiling + many ASN.1 files from the command line or when using Makefiles. + Some examples of how the erlc command can be used to start + the ASN.1 compiler:

+
+erlc Person.asn
+erlc -bper Person.asn
+erlc -bber ../Example.asn
+erlc -o ../asnfiles -I ../asnfiles -I /usr/local/standards/asn1 Person.asn
+

Useful options for the ASN.1 compiler:

+ + -b[ber | per | uper] + +

Choice of encoding rules. If omitted, ber is the + default.

+
+ -o OutDirectory + +

Where to put the generated files. Default is the current + directory.

+
+ -I IncludeDir + +

Where to search for .asn1db files and ASN.1 + source specs to resolve references to other + modules. This option can be repeated many times if there + are several places to search in. The compiler + searches the current directory first.

+
+ +der + +

DER encoding rule. Only when using option -ber.

+
+ +asn1config + +

This functionality works together with option + ber. It enables the specialized decodes, see Section + Specialized Decode.

+
+ +undec_rest + +

A buffer that holds a message being decoded can also have + trailing bytes. If those trailing bytes are important, they + can be returned along with the decoded value by compiling + the ASN.1 specification with option +undec_rest. + The return value from the decoder is + {ok,Value,Rest} where Rest is a binary + containing the trailing bytes.

+
+ +'Any Erlc Option' + +

Any option can be added to the Erlang compiler when + compiling the generated Erlang files. Any option + unrecognized by the ASN.1 compiler is passed to the + Erlang compiler.

+
+
+

For a complete description of erlc, see + ERTS Reference Manual.

+

The compiler and other compile-time functions can also be started + from the Erlang shell. Here follows a brief + description of the primary functions. For a + complete description of each function, see module asn1ct in + the ASN.1 Reference Manual.

+

The compiler is started by asn1ct:compile/1 with + default options, or asn1ct:compile/2 if explicit options + are given.

+

Example:

+
+asn1ct:compile("H323-MESSAGES.asn1").      
+

This equals:

+
+asn1ct:compile("H323-MESSAGES.asn1",[ber]).      
+

If PER encoding is wanted:

+
+asn1ct:compile("H323-MESSAGES.asn1",[per]).      
+

The generic encode and decode functions can be called + as follows:

+
+'H323-MESSAGES':encode('SomeChoiceType',{call,<<"octetstring">>}).
+'H323-MESSAGES':decode('SomeChoiceType',Bytes).      
+
+ +
+ Runtime Functions +

When an ASN.1 specification is compiled with option ber, + the asn1rt_nif module and the NIF library in + asn1/priv_dir are needed at runtime.

+

By calling function info/0 in a generated module, you + get information about which compiler options were used.

+
+ +
+ Errors +

Errors detected at + compile-time are displayed on the screen together with line + numbers indicating where in the source file the respective error + was detected. If no errors are found, an Erlang ASN.1 module is + created.

+

The runtime encoders and decoders execute within a catch and + return {ok, Data} or + {error, {asn1, Description}} where + Description is + an Erlang term describing the error.

+
+
+ +
+ + Multi-File Compilation +

There are various reasons for using multi-file compilation:

+ + To choose the name for the generated module, for + example, because you need to compile the same specs for + different encoding rules. + You want only one resulting module. + +

Specify which ASN.1 specs to compile in a module with extension + .set.asn. Choose a module name and provide the + names of the ASN.1 specs. For example, if you have the specs + File1.asn, File2.asn, and File3.asn, your + module MyModule.set.asn looks as follows:

+
+File1.asn
+File2.asn
+File3.asn    
+

If you compile with the following, the result is one merged + module MyModule.erl with the generated code from the three + ASN.1 specs:

+ +~> erlc MyModule.set.asn +
+ +
+ Remark about Tags + +

Tags used to be important for all users of ASN.1, because it + was necessary to add tags manually to certain constructs in order + for the ASN.1 specification to be valid. Example of + an old-style specification:

+ +
+Tags DEFINITIONS ::=
+BEGIN
+  Afters ::= CHOICE { cheese [0] IA5String,
+                      dessert [1] IA5String }
+END 
+ +

Without the tags (the numbers in square brackets) the ASN.1 + compiler refused to compile the file.

+ +

In 1994 the global tagging mode AUTOMATIC TAGS was introduced. + By putting AUTOMATIC TAGS in the module header, the ASN.1 + compiler automatically adds tags when needed. The following is the + same specification in AUTOMATIC TAGS mode:

+ +
+Tags DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+  Afters ::= CHOICE { cheese IA5String,
+                      dessert IA5String }
+END 
+ +

Tags are not mentioned any more in this User's Guide.

+
+ +
+ + ASN.1 Types +

This section describes the ASN.1 types including their + functionality, purpose, and how values are assigned in Erlang. +

+

ASN.1 has both primitive and constructed types:

+

+ + + Primitive Types + Constructed Types + + + BOOLEAN + SEQUENCE + + + INTEGER + SET + + + REAL + CHOICE + + + NULL + SET OF and SEQUENCE OF + + + ENUMERATED + ANY + + + BIT STRING + ANY DEFINED BY + + + OCTET STRING + EXTERNAL + + + Character Strings + EMBEDDED PDV + + + OBJECT IDENTIFIER + CHARACTER STRING + + + Object Descriptor + + + + TIME Types + + + Supported ASN.1 Types +
+ + +

The values of each ASN.1 type have their own representation in Erlang, as + described in the following sections. Users must provide + these values for encoding according to the representation, as shown in the + following example:

+
+
+Operational ::= BOOLEAN --ASN.1 definition    
+

In Erlang code it can look as follows:

+
+Val = true,
+{ok,Bytes} = MyModule:encode('Operational', Val),    
+ +
+ + BOOLEAN +

Booleans in ASN.1 express values that can be either + TRUE or FALSE. + The meanings assigned to TRUE and FALSE are outside the scope + of this text.

+

In ASN.1 it is possible to have:

+
+Operational ::= BOOLEAN
+

Assigning a value to type Operational in Erlang is possible by + using the following Erlang code:

+ +Myvar1 = true, +

Thus, in Erlang the atoms true and false are used + to encode a boolean value.

+
+ +
+ + INTEGER +

ASN.1 itself specifies indefinitely large integers. Erlang + systems with version 4.3 and higher support very large + integers, in practice indefinitely large integers.

+

The concept of subtyping can be applied to integers and + to other ASN.1 types. The details of subtyping are not + explained here; for more information, see X.680. Various + syntaxes are allowed when defining a type as an integer:

+
+T1 ::= INTEGER
+T2 ::= INTEGER (-2..7)
+T3 ::= INTEGER (0..MAX)
+T4 ::= INTEGER (0<..MAX)
+T5 ::= INTEGER (MIN<..-99)
+T6 ::= INTEGER {red(0),blue(1),white(2)}
+

The Erlang representation of an ASN.1 INTEGER is an integer or + an atom if a Named Number List (see T6 in the previous + list) is specified.

+

The following is an example of Erlang code that assigns values for the + types in the previous list:

+
+T1value = 0,
+T2value = 6,
+T6value1 = blue,
+T6value2 = 0,
+T6value3 = white
+

These Erlang variables are now bound to valid instances of + ASN.1 defined types. This style of value can be passed directly + to the encoder for transformation into a series of bytes.

+

The decoder returns an atom if the value corresponds to a + symbol in the Named Number List.

+
+ +
+ + REAL +

The following ASN.1 type is used for real numbers:

+
+R1 ::= REAL
+

It is assigned a value in Erlang as follows:

+
+R1value1 = "2.14",
+R1value2 = {256,10,-2},
+

In the last line, notice that the tuple {256,10,-2} is the real number + 2.56 in a special notation, which encodes faster than simply + stating the number as "2.56". The arity three tuple is + {Mantissa,Base,Exponent}, that is, Mantissa * Base^Exponent.

+
+ +
+ + NULL +

The type NULL is suitable where supply and recognition of a value + is important but the actual value is not.

+
+Notype ::= NULL
+

This type is assigned in Erlang as follows:

+
+N1 = 'NULL',
+

The actual value is the quoted atom 'NULL'.

+
+ +
+ + ENUMERATED +

The type ENUMERATED can be used when the value you want to + describe can only take one of a set of predefined values. Example:

+
+DaysOfTheWeek ::= ENUMERATED { 
+    sunday(1),monday(2),tuesday(3),
+    wednesday(4),thursday(5),friday(6),saturday(7) }
+

For example, to assign a weekday value in Erlang, use the same atom + as in the Enumerations of the type definition:

+
+Day1 = saturday,
+

The enumerated type is similar to an integer type, when + defined with a set of predefined values. The difference is that + an enumerated type can only have specified + values, whereas an integer can have any value.

+
+ +
+ + BIT STRING +

The type BIT STRING can be used to model information that + is made up of arbitrary length series of bits. It is intended + to be used for selection of flags, not for binary files.

+

In ASN.1, BIT STRING definitions can look as follows:

+
+Bits1 ::= BIT STRING
+Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}
+

The following two notations are available for representation of BIT + STRING values in Erlang and as input to the encode functions:

+ + A bitstring. By default, a BIT STRING with no + symbolic names is decoded to an Erlang bitstring. + A list of atoms corresponding to atoms in the NamedBitList + in the BIT STRING definition. A BIT STRING with symbolic + names is always decoded to the format shown in the following + example: + +
+Bits1Val1 = <<0:1,1:1,0:1,1:1,1:1>>,
+Bits2Val1 = [gnu,punk],
+Bits2Val2 = <<2#1110:4>>,
+Bits2Val3 = [bar,gnu,gnome],
+

Bits2Val2 and Bits2Val3 denote the same value.

+

Bits2Val1 is assigned symbolic values. The assignment means + that the bits corresponding to gnu and punk, that is, bits + 2 and 14 are set to 1, and the rest are set to 0. The symbolic values + are shown as a list of values. If a named value, which is not + specified in the type definition, is shown, a runtime error occurs.

+

BIT STRINGs can also be subtyped with, for example, a SIZE + specification:

+
+Bits3 ::= BIT STRING (SIZE(0..31))      
+

This means that no bit higher than 31 can be set.

+ +
+ Deprecated Representations for BIT STRING +

In addition to the representations described earlier, the + following deprecated representations are available if the + specification has been compiled with option + legacy_erlang_types:

+ + Aa a list of binary digits (0 or 1). This format is + accepted as input to the encode functions, and a BIT STRING + is decoded to this format if option + legacy_bit_string is given. + + As {Unused,Binary} where Unused denotes + how many trailing zero-bits 0-7 that are unused in the + least significant byte in Binary. This format is + accepted as input to the encode functions, and a BIT + STRING is decoded to this format if + compact_bit_string has been given. + + As a hexadecimal number (or an integer). Avoid this + as it is easy to misinterpret a BIT + STRING value in this format. + + +
+
+ +
+ + OCTET STRING +

OCTET STRING is the simplest of all ASN.1 types. OCTET + STRING only moves or transfers, for example, binary files or other + unstructured information complying with two rules: the + bytes consist of octets and encoding is not required.

+

It is possible to have the following ASN.1 type definitions:

+
+O1 ::= OCTET STRING
+O2 ::= OCTET STRING (SIZE(28))      
+

With the following example assignments in Erlang:

+
+O1Val = <<17,13,19,20,0,0,255,254>>,
+O2Val = <<"must be exactly 28 chars....">>,
+

By default, an OCTET STRING is always represented as + an Erlang binary. If the specification has been compiled with + option legacy_erlang_types, the encode functions + accept both lists and binaries, and the decode functions + decode an OCTET STRING to a list.

+
+ +
+ + Character Strings +

ASN.1 supports a wide variety of character sets. The main difference + between an OCTET STRING and a character string is that the + OCTET STRING has no imposed semantics on the bytes delivered.

+

However, when using, for example, IA5String (which closely + resembles ASCII), byte 65 (in decimal + notation) means character 'A'. +

+

For example, if a defined type is to be a VideotexString and + an octet is received with the unsigned integer value X, + the octet is to be interpreted as specified in standard + ITU-T T.100, T.101. +

+

The ASN.1 to Erlang compiler + does not determine the correct interpretation of each BER + string octet value with different character strings. The + application is responsible for interpretation + of octets. Therefore, from the BER + string point of view, octets are very similar to + character strings and are compiled in the same way. +

+

When PER is + used, there is a significant difference in the encoding scheme + between OCTET STRINGs and other strings. The constraints + specified for a type are especially important for PER, where + they affect the encoding. +

+

Examples:

+
+Digs ::= NumericString (SIZE(1..3))
+TextFile ::= IA5String (SIZE(0..64000))      
+

The corresponding Erlang assignments:

+
+DigsVal1 = "456",
+DigsVal2 = "123",
+TextFileVal1 = "abc...xyz...",
+TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]
+

The Erlang representation for "BMPString" and + "UniversalString" is either a list of ASCII values or a list + of quadruples. The quadruple representation associates to the + Unicode standard representation of characters. The ASCII + characters are all represented by quadruples beginning with + three zeros like {0,0,0,65} for character 'A'. When + decoding a value for these strings, the result is a list of + quadruples, or integers when the value is an ASCII character.

+ +

The following example shows how it works. Assume the following + specification is in file PrimStrings.asn1:

+
+PrimStrings DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+   BMP ::= BMPString
+END    
+ +

Encoding and decoding some strings:

+ +
+1> asn1ct:compile('PrimStrings', [ber]).
+ok
+2> {ok,Bytes1} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,45,56}]).
+{ok,<<30,4,53,54,45,56>>}
+3> 'PrimStrings':decode('BMP', Bytes1).
+{ok,[{0,0,53,53},{0,0,45,56}]}
+4> {ok,Bytes2} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,0,65}]).
+{ok,<<30,4,53,53,0,65>>}
+5> 'PrimStrings':decode('BMP', Bytes2).
+{ok,[{0,0,53,53},65]}
+6> {ok,Bytes3} = 'PrimStrings':encode('BMP', "BMP string").
+{ok,<<30,20,0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103>>}
+7> 'PrimStrings':decode('BMP', Bytes3).
+{ok,"BMP string"}      
+ +

Type UTF8String is represented as a UTF-8 encoded binary in + Erlang. Such binaries can be created directly using the binary syntax + or by converting from a list of Unicode code points using function + unicode:characters_to_binary/1.

+ +

The following shows examples of how UTF-8 encoded binaries can + be created and manipulated:

+
+1> Gs = "Мой маленький Гном".
+[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
+ 1081,32,1043,1085,1086,1084]
+2> Gbin = unicode:characters_to_binary(Gs).
+<<208,156,208,190,208,185,32,208,188,208,176,208,187,208,
+  181,208,189,209,140,208,186,208,184,208,185,32,208,147,
+  208,...>>
+3> Gbin = <<"Мой маленький Гном"/utf8>>.
+<<208,156,208,190,208,185,32,208,188,208,176,208,187,208,
+  181,208,189,209,140,208,186,208,184,208,185,32,208,147,
+  208,...>>
+4> Gs = unicode:characters_to_list(Gbin).
+[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
+ 1081,32,1043,1085,1086,1084]
+ +

For details, see the unicode + module in stdlib.

+ +

In the following example, this ASN.1 specification is used:

+
+UTF DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+   UTF ::= UTF8String
+END   
+ +

Encoding and decoding a string with Unicode characters:

+ +
+5> asn1ct:compile('UTF', [ber]).
+ok
+6> {ok,Bytes1} = 'UTF':encode('UTF', <<"Гном"/utf8>>).
+{ok,<<12,8,208,147,208,189,208,190,208,188>>}
+7> {ok,Bin1} = 'UTF':decode('UTF', Bytes1).
+{ok,<<208,147,208,189,208,190,208,188>>}
+8> io:format("~ts\n", [Bin1]).
+Гном
+ok
+9> unicode:characters_to_list(Bin1).
+[1043,1085,1086,1084]   
+
+ +
+ + OBJECT IDENTIFIER +

The type OBJECT IDENTIFIER is used whenever a unique identity is + required. An ASN.1 module, a transfer syntax, and so on, is identified + with an OBJECT IDENTIFIER. Assume the following example:

+
+Oid ::= OBJECT IDENTIFIER
+

Therefore, the following example is a valid Erlang instance of + type 'Oid':

+
+OidVal1 = {1,2,55},
+

The OBJECT IDENTIFIER value is simply a tuple with the + consecutive values, which must be integers. +

+

The first value is limited to the values 0, 1, or 2. The + second value must be in the range 0..39 when the first value + is 0 or 1. +

+

The OBJECT IDENTIFIER is an important type and it is + widely used within different standards to identify various + objects uniquely. Dubuisson: ASN.1 - Communication Between + Heterogeneous Systems includes an + easy-to-understand description of the use of + OBJECT IDENTIFIER.

+
+ +
+ + Object Descriptor +

Values of this type can be assigned a value as an ordinary string + as follows:

+ +
+      "This is the value of an Object descriptor"
+
+ +
+ + TIME Types +

Two time types are defined within ASN.1: Generalized + Time and Universal Time Coordinated (UTC). Both are assigned a + value as an ordinary string within double quotes, for example, + "19820102070533.8".

+

For DER encoding, the compiler does not check the validity + of the time values. The DER requirements upon those strings are + regarded as a matter for the application to fulfill.

+
+ +
+ + SEQUENCE +

The structured types of ASN.1 are constructed from other types + in a manner similar to the concepts of array and struct in C.

+

A SEQUENCE in ASN.1 is + comparable with a struct in C and a record in Erlang. + A SEQUENCE can be defined as follows:

+
+Pdu ::= SEQUENCE {
+   a INTEGER,
+   b REAL,
+   c OBJECT IDENTIFIER,
+   d NULL }      
+

This is a 4-component structure called Pdu. The record format + is the major format for representation of SEQUENCE in Erlang. + For each SEQUENCE and SET in an ASN.1 module an Erlang + record declaration is generated. For Pdu, a record + like the following is defined:

+
+-record('Pdu',{a, b, c, d}).      
+

The record declarations for a module M are placed in a + separate M.hrl file.

+

Values can be assigned in Erlang as follows:

+
+MyPdu = #'Pdu'{a=22,b=77.99,c={0,1,2,3,4},d='NULL'}.      
+

The decode functions return a record as result when decoding + a SEQUENCE or a SET.

+ +

A SEQUENCE and a SET can contain a component + with a DEFAULT keyword followed by the actual value, which + is the default value. The DEFAULT keyword means that the + application doing the encoding can omit encoding of the value, which + results in fewer bytes to send to the receiving application.

+ +

An application can use the atom asn1_DEFAULT to indicate + that the encoding is to be omitted for that position in + the SEQUENCE.

+ +

Depending on the encoding rules, the encoder can also compare + the given value to the default value and automatically omit the + encoding if the values are equal. How much effort the encoder makes + to compare the values depends on the encoding rules. The DER + encoding rules forbid encoding a value equal to the default value, + so it has a more thorough and time-consuming comparison than the + encoders for the other encoding rules.

+ +

In the following example, this ASN.1 specification is used:

+
+File DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+Seq1 ::= SEQUENCE {
+    a INTEGER DEFAULT 1,
+    b Seq2 DEFAULT {aa TRUE, bb 15}
+}
+
+Seq2 ::= SEQUENCE {
+    aa BOOLEAN,
+    bb INTEGER
+}
+
+Seq3 ::= SEQUENCE {
+    bs BIT STRING {a(0), b(1), c(2)} DEFAULT {a, c}
+}
+END 
+

Example where the BER encoder is able to omit encoding + of the default values:

+
+1> asn1ct:compile('File', [ber]).
+ok
+2> 'File':encode('Seq1', {'Seq1',asn1_DEFAULT,asn1_DEFAULT}).
+{ok,<<48,0>>}
+3> 'File':encode('Seq1', {'Seq1',1,{'Seq2',true,15}}).
+{ok,<<48,0>>}   
+ +

Example with a named BIT STRING where the BER + encoder does not omit the encoding:

+
+4> 'File':encode('Seq3', {'Seq3',asn1_DEFAULT).
+{ok,<<48,0>>}
+5> 'File':encode('Seq3', {'Seq3',<<16#101:3>>).
+{ok,<<48,4,128,2,5,160>>}     
+ +

The DER encoder omits the encoding for the same BIT STRING:

+
+6> asn1ct:compile('File', [ber,der]).
+ok
+7> 'File':encode('Seq3', {'Seq3',asn1_DEFAULT).
+{ok,<<48,0>>}
+8> 'File':encode('Seq3', {'Seq3',<<16#101:3>>).
+{ok,<<48,0>>}     
+
+ +
+ + SET +

In Erlang, the SET type is used exactly as SEQUENCE. + Notice that if BER or DER encoding rules are used, decoding a + SET is slower than decoding a SEQUENCE because the + components must be sorted.

+
+ +
+ Extensibility for SEQUENCE and SET +

When a SEQUENCE or SET contains an extension marker + and extension components as the following, the type can get more + components in newer versions of the ASN.1 spec:

+
+SExt ::= SEQUENCE {
+           a INTEGER,
+           ...,
+           b BOOLEAN }
+

In this case it has got a new + component b. Thus, incoming messages that are decoded + can have more or fever components than this one. +

+

The component b is treated as + an original component when encoding a message. In this case, as + it is not an optional element, it must be encoded. +

+

During decoding, the b field of the record gets the decoded + value of the b + component, if present, otherwise the value asn1_NOVALUE.

+
+ +
+ + CHOICE +

The type CHOICE is a space saver and is similar to the + concept of a 'union' in C.

+

Assume the following:

+
+SomeModuleName DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+T ::= CHOICE {
+        x REAL,
+        y INTEGER,
+        z OBJECT IDENTIFIER }
+END 
+

It is then possible to assign values as follows:

+
+TVal1 = {y,17},
+TVal2 = {z,{0,1,2}},
+

A CHOICE value is always represented as the tuple + {ChoiceAlternative, Val} where ChoiceAlternative + is an atom denoting the selected choice alternative. +

+ +
+ Extensible CHOICE +

When a CHOICE contains an extension marker and the + decoder detects an unknown alternative of the CHOICE, + the value is represented as follows:

+
+{asn1_ExtAlt, BytesForOpenType}
+

Here BytesForOpenType is a list of bytes constituting the + encoding of the "unknown" CHOICE alternative.

+
+
+ +
+ + SET OF and SEQUENCE OF +

The types SET OF and SEQUENCE OF correspond + to the concept of an array + in several programming languages. The Erlang syntax for + both types is straightforward, for example:

+
+Arr1 ::= SET SIZE (5) OF INTEGER (4..9) 
+Arr2 ::= SEQUENCE OF OCTET STRING      
+

In Erlang the following can apply:

+
+Arr1Val = [4,5,6,7,8],
+Arr2Val = ["abc",[14,34,54],"Octets"],      
+

Notice that the definition of type SET OF implies that + the order of the components is undefined, but in practice there is + no difference between SET OF and SEQUENCE OF. + The ASN.1 compiler for Erlang does not randomize the order of the + SET OF components before encoding.

+

However, for a value of type SET OF, the DER + encoding format requires the elements to be sent in ascending + order of their encoding, which implies an expensive sorting + procedure in runtime. Therefore it is recommended to + use SEQUENCE OF instead of SET OF if possible.

+
+ +
+ + ANY and ANY DEFINED BY +

The types ANY and ANY DEFINED BY have been removed + from the standard since 1994. It is recommended not to use + these types any more. They can, however, exist in some old ASN.1 + modules. The idea with this type was to leave a "hole" in a + definition where it was possible to + put unspecified data of any kind, even non-ASN.1 data.

+

A value of this type is encoded as an open type.

+

Instead of ANY and ANY DEFINED BY, it is + recommended to use + information object class, table constraints, and + parameterization. In particular the construct + TYPE-IDENTIFIER.@Type accomplish the same as the + deprecated ANY.

+

See also + Information object.

+
+ +
+ + EXTERNAL, EMBEDDED PDV, and CHARACTER STRING +

The types EXTERNAL, EMBEDDED PDV, and + CHARACTER STRING are used in presentation layer negotiation. + They are encoded according to their associated type, see X.680.

+

The type EXTERNAL had a slightly different associated type + before 1994. X.691 states that encoding must follow + the older associated type. So, generated encode/decode + functions convert values of the newer format to the older format + before encoding. This implies that it is allowed to use + EXTERNAL type values of either format for encoding. Decoded + values are always returned in the newer format.

+
+ +
+ Embedded Named Types +

The structured types previously described can have other named + types as their components. The general syntax to assign a value + to component C of a named ASN.1 type T in Erlang + is the record syntax #'T'{'C'=Value}. + Here Value can be a value of yet another type T2, + for example:

+
+EmbeddedExample DEFINITIONS AUTOMATIC TAGS ::=
+BEGIN
+B ::= SEQUENCE {
+        a Arr1,
+        b T }
+
+Arr1 ::= SET SIZE (5) OF INTEGER (4..9) 
+
+T ::= CHOICE {
+        x REAL,
+        y INTEGER,
+        z OBJECT IDENTIFIER }
+        END      
+

SEQUENCE b can be encoded as follows in Erlang:

+
+1> 'EmbeddedExample':encode('B', {'B',[4,5,6,7,8],{x,"7.77"}}).
+{ok,<<5,56,0,8,3,55,55,55,46,69,45,50>>} 
+
+
+ +
+ Naming of Records in .hrl Files +

When an ASN.1 specification is compiled, all defined types of type + SET or SEQUENCE result in a corresponding record in the + generated .hrl file. This is because the values for + SET and SEQUENCE are represented as records as + mentioned earlier.

+

Some special cases of this functionality are presented in the + next section.

+ +
+ Embedded Structured Types +

In ASN.1 it is also possible to have components that are themselves + structured types. + For example, it is possible to have the following:

+
+Emb ::= SEQUENCE {
+    a SEQUENCE OF OCTET STRING,
+    b SET {
+       a INTEGER,
+       b INTEGER DEFAULT 66},
+    c CHOICE {
+       a INTEGER,
+       b FooType } }
+
+FooType ::= [3] VisibleString      
+

The following records are generated because of type Emb:

+
+-record('Emb,{a, b, c}).
+-record('Emb_b',{a, b = asn1_DEFAULT}). % the embedded SET type 
+

Values of type Emb can be assigned as follows:

+ +V = #'Emb'{a=["qqqq",[1,2,255]], + b = #'Emb_b'{a=99}, + c ={b,"Can you see this"}}. +

For an embedded type of type SEQUENCE/SET in a + SEQUENCE/SET, the record name is extended with an + underscore and the component name. If the embedded structure is + deeper with the SEQUENCE, SET, or CHOICE + types in the line, each component name/alternative name is + added to the record name.

+

Example:

+
+Seq ::= SEQUENCE{
+    a CHOICE{
+        b SEQUENCE {
+           c  INTEGER
+        }
+    }
+}      
+

This results in the following record:

+
+-record('Seq_a_b',{c}).      
+

If the structured type has a component with an embedded + SEQUENCE OF/SET OF which embedded type in turn + is a SEQUENCE/SET, it gives a record with the + SEQUENCE OF/SET OF + addition as in the following example:

+
+Seq ::= SEQUENCE {
+    a SEQUENCE OF SEQUENCE {
+           b
+               }
+    c SET OF SEQUENCE {
+           d
+               }
+}      
+

This results in the following records:

+
+-record('Seq_a_SEQOF'{b}).
+-record('Seq_c_SETOF'{d}).      
+

A parameterized type is to be considered as an embedded + type. Each time such a type is referenced, an instance of it is + defined. Thus, in the following example a record with name + 'Seq_b' is generated in the .hrl file and is used + to hold values:

+
+Seq ::= SEQUENCE {
+    b PType{INTEGER}
+}
+
+PType{T} ::= SEQUENCE{
+    id T
+}      
+
+ +
+ Recursive Types +

Types that refer to themselves are called recursive types. + Example:

+
+Rec ::= CHOICE {
+     nothing NULL,
+     something SEQUENCE {
+          a INTEGER,
+          b OCTET STRING,
+          c Rec }}      
+

This is allowed in ASN.1 and the ASN.1-to-Erlang compiler + supports this recursive type. + A value for this type is assigned in Erlang as follows:

+
+V = {something,#'Rec_something'{a = 77, 
+                                b = "some octets here", 
+                                c = {nothing,'NULL'}}}.      
+
+
+ +
+ ASN.1 Values +

Values can be assigned to an ASN.1 type within the ASN.1 code + itself, as opposed to the actions in the previous section where + a value was assigned to an ASN.1 type in Erlang. The full value + syntax of ASN.1 is supported and X.680 describes in detail how + to assign values in ASN.1. A short example:

+
+TT ::= SEQUENCE {
+   a INTEGER,
+   b SET OF OCTET STRING }
+
+tt TT ::= {a 77,b {"kalle","kula"}}    
+

The value defined here can be used in several ways. It can, for + example, be used as the value in some DEFAULT component:

+
+SS ::= SET {
+    s OBJECT IDENTIFIER,
+    val TT DEFAULT tt }    
+

It can also be used from inside an Erlang program. If this ASN.1 + code is defined in ASN.1 module Values, the ASN.1 value + tt can be reached from Erlang as a function call to + 'Values':tt() as in the following example:

+
+1> Val = 'Values':tt().
+{'TT',77,["kalle","kula"]}
+2> {ok,Bytes} = 'Values':encode('TT',Val).
+{ok,<<48,18,128,1,77,161,13,4,5,107,97,108,108,101,4,4,
+      107,117,108,97>>}
+4> 'Values':decode('TT',Bytes).
+{ok,{'TT',77,["kalle","kula"]}}
+5>  
+

This example shows that a function is generated by the compiler + that returns a valid Erlang representation of the value, although + the value is of a complex type.

+

Furthermore, a macro is generated for each value in the .hrl + file. So, the defined value tt can also be extracted by + ?tt in application code.

+
+ +
+ Macros +

The type MACRO is not supported. It is no longer part of + the ASN.1 standard.

+
+ +
+ + ASN.1 Information Objects (X.681) +

Information Object Classes, Information Objects, and Information + Object Sets (in the following called classes, objects, and + object sets, respectively) are defined in the standard + definition X.681. Only a brief explanation is given here.

+

These constructs makes it possible to define open types, that + is, values of that type can be of any ASN.1 type. Also, + relationships can be defined between different types and + values, as classes can hold types, values, objects, object + sets, and other classes in their fields. A class can be + defined in ASN.1 as follows:

+
+GENERAL-PROCEDURE ::= CLASS {
+      &Message,
+      &Reply               OPTIONAL,
+      &Error               OPTIONAL,
+      &id          PrintableString UNIQUE
+}
+WITH SYNTAX {
+      NEW MESSAGE     &Message
+      [REPLY           &Reply]
+      [ERROR           &Error]
+      ADDRESS          &id
+}    
+

An object is an instance of a class. An object set is a set + containing objects of a specified class. A definition can look + as follows:

+
+object1 GENERAL-PROCEDURE ::= {
+    NEW MESSAGE      PrintableString
+    ADDRESS          "home"
+}
+
+object2 GENERAL-PROCEDURE ::= {
+    NEW MESSAGE INTEGER
+    ERROR INTEGER
+    ADDRESS "remote"
+}
+

The object object1 is an instance of the class + GENERAL-PROCEDURE and has one type field and one + fixed type value field. The object object2 has also an + optional field ERROR, which is a type field. The field + ADDRESS is a UNIQUE field. Objects in an object set + must have unique values in their UNIQUE field, as in + GENERAL-PROCEDURES:

+
+GENERAL-PROCEDURES GENERAL-PROCEDURE ::= {
+    object1 | object2}    
+

You cannot encode a class, object, or object set, only refer to + it when defining other ASN.1 entities. Typically you refer to a + class as well as to object sets by table constraints and component + relation constraints (X.682) in ASN.1 types, as in the following:

+
+StartMessage  ::= SEQUENCE {
+    msgId  GENERAL-PROCEDURE.&id  ({GENERAL-PROCEDURES}),
+    content GENERAL-PROCEDURE.&Message ({GENERAL-PROCEDURES}{@msgId}),
+    }    
+

In type StartMessage, the constraint following field + content tells that in a value of type + StartMessage the value in field content must + come from the same object that is chosen by field msgId.

+

So, the value + #'StartMessage'{msgId="home",content="Any Printable String"} + is legal to encode as a StartMessage value. However, the value + #'StartMessage'{msgId="remote", content="Some String"} + is illegal as the constraint in StartMessage tells that + when you have chosen a value from a specific object in object + set GENERAL-PROCEDURES in field + msgId, you must choose a value from that same object in + the content field too. In this second case, it is to be + any INTEGER value.

+

StartMessage can in field content be + encoded with a value of any type that an object in object set + GENERAL-PROCEDURES has in its NEW MESSAGE field. + This field refers to a type field + &Message in the class. Field msgId is always + encoded as a PrintableString, as the field refers to a + fixed type in the class.

+

In practice, object sets are usually declared to be extensible so + that more objects can be added to the set later. Extensibility is + indicated as follows:

+
+GENERAL-PROCEDURES GENERAL-PROCEDURE ::= {
+    object1 | object2, ...}    
+

When decoding a type that uses an extensible set constraint, + it is always possible that the value in field UNIQUE + is unknown (that is, the type has been encoded with a later + version of the ASN.1 specification). The unencoded data is then + returned wrapped in a tuple as follows:

+ +
+{asn1_OPENTYPE,Binary}
+ +

Here Binary is an Erlang binary that contains the encoded + data. (If option legacy_erlang_types has been given, + only the binary is returned.)

+
+ +
+ Parameterization (X.683) +

Parameterization, which is defined in X.683, can be used when + defining types, values, value sets, classes, objects, or object sets. + A part of a definition can be supplied as a parameter. For + example, if a Type is used in a definition with a certain + purpose, you want the type name to express the intention. This + can be done with parameterization.

+

When many types (or another ASN.1 entity) only differ in some + minor cases, but the structure of the types is similar, only + one general type can be defined and the differences can be supplied + through parameters.

+

Example of use of parameterization:

+
+General{Type} ::= SEQUENCE
+{
+     number     INTEGER,
+     string     Type
+}
+      
+T1 ::= General{PrintableString}
+
+T2 ::= General{BIT STRING}
+

An example of a value that can be encoded as type T1 is + {12,"hello"}.

+

Notice that the compiler does not generate encode/decode functions + for parameterized types, only for the instances of the parameterized + types. Therefore, if a file contains the types General{}, + T1, and T2 as in the previous example, encode/decode + functions are only generated for T1 and T2. +

+
+
+ -- cgit v1.2.3