blob: 73221028cf386bee2580e8e9bfc28af0233beca2 [file] [log] [blame]
Lev Walkin464166c2010-11-09 08:34:38 -08001\documentclass[english,oneside,12pt]{book}
2\usepackage{fontspec}
3\usepackage{xunicode}
4\usepackage{xltxtra}
5
Lev Walkin11c9a8c2013-03-26 00:46:55 -07006\usepackage[hmargin={1in,1in},vmargin={1.5in,1.5in}]{geometry}
Lev Walkin464166c2010-11-09 08:34:38 -08007
8\defaultfontfeatures{Mapping=tex-text}
Lev Walkin11c9a8c2013-03-26 00:46:55 -07009\setmainfont{PT Sans}
10\setsansfont{PT Sans}
Lev Walkin464166c2010-11-09 08:34:38 -080011\setmonofont{Consolas}
12
Lev Walkined44bf42010-11-08 02:04:55 -080013\usepackage{fancyhdr}
Lev Walkined44bf42010-11-08 02:04:55 -080014\usepackage{longtable}
Lev Walkin464166c2010-11-09 08:34:38 -080015\usepackage{booktabs}
Lev Walkined44bf42010-11-08 02:04:55 -080016\usepackage{varioref}
17\usepackage{url}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070018\usepackage{xcolor}
19\usepackage{listings}
20\usepackage{setspace}
21
22\setstretch{1.1}
23
24% Courier 10 Pitch
25\def\courierFont{Courier10 BT WGL4}
26%\def\courierFont{Consolas}
27\setmonofont[Scale=1.05]{\courierFont}
28
Lev Walkined44bf42010-11-08 02:04:55 -080029
30\makeatletter
31
Lev Walkined44bf42010-11-08 02:04:55 -080032%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific LaTeX commands.
Lev Walkin11c9a8c2013-03-26 00:46:55 -070033\lstloadlanguages{C,bash}
34\newfontfamily\listingfont[Scale=1.05]{\courierFont}
35\newfontfamily\inlinelistingfont[Scale=1.05]{\courierFont}
36\definecolor{clrlcomment}{gray}{0.3}
37\definecolor{clrlkeyword}{rgb}{0.588,0.145,0.18}
38\newcommand{\listingkeyword}[1]{\color{clrlkeyword}{#1}}
39\newcommand{\listingstring}[1]{\color{clrlcomment}{#1}}
40\newcommand{\listingcomment}[1]{\color{clrlcomment}{#1}}
41\lstset{tabsize=4,
42 showstringspaces=false,
43 showtabs=false,
44 showspaces=false,
45 keywordstyle=\listingkeyword,
46 stringstyle=\listingstring,
47 commentstyle=\listingcomment,
48 xleftmargin=\parindent,
49 columns=fixed,
50 escapechar=\%,
51 texcl
52}
53\lstdefinestyle{listingStyle}{
54 basicstyle=\small\listingfont,
55 stringstyle=\listingstring,
56 breaklines=true,
57 breakatwhitespace=true,
58 flexiblecolumns=false
59 }
60\lstdefinelanguage{asn1}{
61 morekeywords={DEFINITIONS,BEGIN,END,SEQUENCE,SET,OF,CHOICE,OPTIONAL},
62 morecomment=[l]{--},
63 morecomment=[n]{/*}{*/}
64 }
65
66\lstnewenvironment{codesample}[1][]{\lstset{style=listingStyle,language=C,#1}}{}
Lev Walkin2a744a72013-03-27 01:56:23 -070067\lstnewenvironment{bash}[1][]{\lstset{style=listingStyle,language=bash,#1}}{}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070068\lstnewenvironment{asn}[1][]{\lstset{style=listingStyle,language=asn1,#1}}{}
69\def\code{lstinline}
Lev Walkined44bf42010-11-08 02:04:55 -080070
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands.
72\usepackage{extramarks}
73\lhead{\firstxmark}
74\rfoot{\lastxmark}
Lev Walkin11c9a8c2013-03-26 00:46:55 -070075\definecolor{clrlink}{rgb}{0,0.4,0}
76\definecolor{clrurl}{rgb}{0,0,.6}
Lev Walkined44bf42010-11-08 02:04:55 -080077\usepackage[colorlinks=true,
Lev Walkin11c9a8c2013-03-26 00:46:55 -070078 linkcolor={clrlink},
79 citecolor={clrlink},
80 urlcolor={clrurl},
81 pdfauthor={Lev Walkin},
82 pdftitle={Using the Open Source ASN.1 Compiler},
83 pdfkeywords={ASN.1,asn1c,compiler},
84 bookmarksopen,bookmarksopenlevel=1,
85 pdffitwindow,
86 xetex
Lev Walkined44bf42010-11-08 02:04:55 -080087]{hyperref}
Lev Walkined44bf42010-11-08 02:04:55 -080088
89\makeatother
90
91\usepackage{babel}
92
93\begin{document}
94
95\title{Using the Open Source ASN.1 Compiler}
Lev Walkined44bf42010-11-08 02:04:55 -080096\author{Lev Walkin <\href{mailto:vlm@lionet.info?Subject=asn1c}{vlm@lionet.info}>}
97
Lev Walkin11c9a8c2013-03-26 00:46:55 -070098\pagestyle{fancy}
99\fancyhead[L]{\leftmark}
100\fancyhead[R]{\href{http://lionet.info/asn1c}{asn1c-0.9.25}}
Lev Walkined44bf42010-11-08 02:04:55 -0800101\maketitle
Lev Walkined44bf42010-11-08 02:04:55 -0800102
103\tableofcontents{}
104
Lev Walkined44bf42010-11-08 02:04:55 -0800105\part{Using the ASN.1 Compiler}
106
107
108\chapter{Introduction to the ASN.1 Compiler}
109
110The purpose of the ASN.1 compiler is to convert the specifications
111in ASN.1 notation into some other language. At this moment, only C
112and C++ target languages are supported, the latter is in upward compatibility
113mode.
114
115The compiler reads the specification and emits a series of target
Lev Walkin464166c2010-11-09 08:34:38 -0800116language structures (C structs, unions, enums) describing the corresponding
Lev Walkined44bf42010-11-08 02:04:55 -0800117ASN.1 types. The compiler also creates the code which allows automatic
118serialization and deserialization of these structures using several
Lev Walkin464166c2010-11-09 08:34:38 -0800119standardized encoding rules (BER, DER, XER, PER).
Lev Walkined44bf42010-11-08 02:04:55 -0800120
121For example, suppose the following ASN.1 module is given%
Lev Walkin464166c2010-11-09 08:34:38 -0800122\footnote{Part \vref{par:ASN.1-Basics} provides a quick reference
123on the ASN.1 notation.}:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700124\begin{asn}
125RectangleTest DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800126
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700127Rectangle ::= SEQUENCE {
128 height INTEGER, -- Height of the rectangle
129 width INTEGER -- Width of the rectangle
130}
Lev Walkined44bf42010-11-08 02:04:55 -0800131
132END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700133\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800134The compiler would read this ASN.1 definition and produce the following
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700135C type:
136\begin{codesample}
137typedef struct Rectangle_s {
138 long height;
139 long width;
140} Rectangle_t;
141\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800142It would also create the code for converting this structure into platform-independent
143wire representation (a serializer API) and the decoder of such wire
144representation back into local, machine-specific type (a deserializer
145API).
146
147
148\section{Quick start with asn1c}
149
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700150After building and installing the compiler, the \emph{asn1c}
151command may be used to compile the ASN.1 modules%
Lev Walkin464166c2010-11-09 08:34:38 -0800152\footnote{This is probably \textbf{not} what you want to try out right now. Read through the rest of this chapter and check the Section \vref{sec:Command-line-options}
Lev Walkined44bf42010-11-08 02:04:55 -0800153to find out about \textbf{-P} and \textbf{-R} options.%
154}:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700155\begin{bash}
156asn1c %\emph{<modules.asn1>}%
157\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800158If several ASN.1 modules contain interdependencies, all of the files
159must be specified altogether:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700160\begin{bash}
161asn1c %\emph{<module1.asn1> <module2.asn1> ...}%
162\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800163The compiler \textbf{-E} and \textbf{-EF} options are used for testing
164the parser and the semantic fixer, respectively. These options will
165instruct the compiler to dump out the parsed (and fixed, if \textbf{-F}
Lev Walkin2a744a72013-03-27 01:56:23 -0700166is involved) ASN.1 specification as it was understood
Lev Walkined44bf42010-11-08 02:04:55 -0800167by the compiler. It might be useful to check whether a particular
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700168syntactic construct is properly supported by the compiler.
169\begin{bash}
170asn1c %\textbf{-EF} \emph{<module-to-test.asn1>}%
171\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800172The \textbf{-P} option is used to dump the compiled output on the
173screen instead of creating a bunch of .c and .h files on disk in the
174current directory. You would probably want to start with \textbf{-P}
175option instead of creating a mess in your current directory. Another
176option, \textbf{-R}, asks compiler to only generate the files which
177need to be generated, and supress linking in the numerous support
178files.
179
180Print the compiled output instead of creating multiple source files:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700181\begin{bash}
182asn1c %\textbf{-P} \emph{<module-to-compile-and-print.asn1>}%
183\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800184
Lev Walkin2a744a72013-03-27 01:56:23 -0700185\clearpage{}
Lev Walkined44bf42010-11-08 02:04:55 -0800186\section{Recognizing compiler output}
187
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700188The asn1c compiler produces a number of files:
Lev Walkined44bf42010-11-08 02:04:55 -0800189\begin{itemize}
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700190\item A set of .c and .h files for each type defined
191in the ASN.1 specification. These files will be named similarly to
Lev Walkined44bf42010-11-08 02:04:55 -0800192the ASN.1 types (\emph{Rectangle.c} and \emph{Rectangle.h} for the
193RectangleTest ASN.1 module defined in the beginning of this document).
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700194\item A set of helper .c and .h files which contain the generic encoders,
195decoders and other useful routines. There will be quite a few of them, some
196of them are not even always necessary, but the overall amount of code
Lev Walkined44bf42010-11-08 02:04:55 -0800197after compilation will be rather small anyway.
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700198\item A \emph{converter-sample.c} file containing the \emph{int main()} function with a fully functioning decoder. It can convert a given PDU between BER, XER and possibly PER (if -gen-PER option to asn1c was in effect). At some point you will want to replace this file with your own file containing the \emph{int main()} function.
Lev Walkined44bf42010-11-08 02:04:55 -0800199\item A \emph{Makefile.am.sample} file mentioning all the files created
200at the earlier steps. This file is suitable for either automake suite
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700201or the plain `make` utility. Just rename it into \emph{Makefile}.
Lev Walkined44bf42010-11-08 02:04:55 -0800202\end{itemize}
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700203It is possible to compile everything with just a couple of instructions:
204\begin{bash}
Lev Walkin2a744a72013-03-27 01:56:23 -0700205asn1c -pdu=%\emph{Rectangle}% *.asn1
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700206make -f Makefile.am.sample # If you use `make`
207\end{bash}
208or
209\begin{bash}
Lev Walkin2a744a72013-03-27 01:56:23 -0700210asn1c *.asn1
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700211cc -I. -DPDU=%\emph{Rectangle}% -o rectangle.exe *.c # ... or like this
212\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800213Refer to the Chapter \vref{cha:Step-by-step-examples} for a sample
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700214\emph{int main()} function if you want some custom logic and not satisfied
215with the supplied \emph{converter-sample.c}.
Lev Walkined44bf42010-11-08 02:04:55 -0800216
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700217\clearpage{}
Lev Walkined44bf42010-11-08 02:04:55 -0800218\section{\label{sec:Command-line-options}Command line options}
219
220The following table summarizes the asn1c command line options.
221
Lev Walkin464166c2010-11-09 08:34:38 -0800222\renewcommand{\arraystretch}{1.33}
223\begin{longtable}{lp{4in}}
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700224\textbf{Overall Options} & \textbf{Description}\\
Lev Walkin464166c2010-11-09 08:34:38 -0800225\midrule
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700226{-E} & {\small Stop after the parsing stage and print the reconstructed ASN.1
227specification code to the standard output.}\\
228{-F} & {\small Used together with -E, instructs the compiler to stop after
Lev Walkined44bf42010-11-08 02:04:55 -0800229the ASN.1 syntax tree fixing stage and dump the reconstructed ASN.1
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700230specification to the standard output.}\\
231{-P} & {\small Dump the compiled output to the standard output instead of
232creating the target language files on disk.}\\
233{-R} & {\small Restrict the compiler to generate only the ASN.1 tables, omitting the usual support code.}\\
234{-S}~\emph{<directory>} & {\small Use the specified directory with ASN.1 skeleton files.}\\
235{-X} & {\small Generate the XML DTD for the specified ASN.1 modules.}\\\\
236\textbf{Warning Options} & \textbf{Description}\\
Lev Walkin464166c2010-11-09 08:34:38 -0800237\midrule
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700238{-Werror} & {\small Treat warnings as errors; abort if any warning is produced.}\\
239{-Wdebug-lexer} & {\small Enable lexer debugging during the ASN.1 parsing stage.}\\
240{-Wdebug-fixer} & {\small Enable ASN.1 syntax tree fixer debugging during the
241 fixing stage.}\\
242{-Wdebug-compiler} & {\small Enable debugging during the actual compile time.}\\ \\
243\textbf{Language Options} & \textbf{Description}\\
Lev Walkin464166c2010-11-09 08:34:38 -0800244\midrule
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700245{-fbless-SIZE} & {\small Allow SIZE() constraint for INTEGER, ENUMERATED, and other
Lev Walkined44bf42010-11-08 02:04:55 -0800246types for which this constraint is normally prohibited by the standard.
247This is a violation of an ASN.1 standard and compiler may fail to
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700248produce the meaningful code.}\\
249{-fcompound-names} & {\small Use complex names for C structures. Using complex names prevents
Lev Walkined44bf42010-11-08 02:04:55 -0800250name clashes in case the module reuses the same identifiers in multiple
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700251contexts.}\\
252{-findirect-choice} & {\small When generating code for a CHOICE type, compile the CHOICE
Lev Walkined44bf42010-11-08 02:04:55 -0800253members as indirect pointers instead of declaring them inline. Consider
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700254using this option together with \textbf{-fno-include-deps}
255to prevent circular references. }\\
256{-fknown-extern-type=}\emph{<name>} & {\small Pretend the specified type is known. The compiler will assume
Lev Walkined44bf42010-11-08 02:04:55 -0800257the target language source files for the given type have been provided
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700258manually. }\\
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700259{-fno-constraints} & {\small Do not generate ASN.1 subtype constraint checking code. This
260may produce a shorter executable.}\\
261{-fno-include-deps} & {\small Do not generate courtesy \#include lines for non-critical
262dependencies.}\\
Lev Walkin2a744a72013-03-27 01:56:23 -0700263{-funnamed-unions} & {\small Enable unnamed unions in the definitions of target language's structures.}\\
264{-fwide-types} & {\small Use the wide integer types (INTEGER\_t, REAL\_t) instead of machine's native data types (long, double). }\\\\
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700265\textbf{Codecs Generation Options} & \textbf{Description}\\
Lev Walkin464166c2010-11-09 08:34:38 -0800266\midrule
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700267{-gen-PER} & {\small Generate Packed Encoding Rules (PER) support code.}\\
268{-pdu=}\emph{auto} & {\small Generate PDU tables by discovering Protocol Data Units automatically. Also accepts a special keyword \emph{all} or a particular type to be used as a PDU.}\\ \\
269\textbf{Output Options} & \textbf{Description}\\
Lev Walkin464166c2010-11-09 08:34:38 -0800270\midrule
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700271{-print-constraints} & {\small When -EF are also specified, this option forces the compiler
272to explain its internal understanding of subtype constraints.}\\
273{-print-lines} & {\small Generate ``-{}- \#line'' comments
274in -E output.}\\
Lev Walkined44bf42010-11-08 02:04:55 -0800275\end{longtable}
Lev Walkin464166c2010-11-09 08:34:38 -0800276\renewcommand{\arraystretch}{1}
Lev Walkined44bf42010-11-08 02:04:55 -0800277
278
279\chapter{Using the ASN.1 Compiler}
280
281
282\section[Invoking the helper code]{Invoking the ASN.1 helper code}
283
284First of all, you should include one or more header files into your
285application. Typically, it is enough to include the header file of
286the main PDU type. For our Rectangle module, including the Rectangle.h
287file is sufficient:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700288\begin{codesample}
289#include <Rectangle.h>
290\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800291The header files defines the C structure corresponding to the ASN.1
292definition of a rectangle and the declaration of the ASN.1 type descriptor,
293which is used as an argument to most of the functions provided by
294the ASN.1 module. For example, here is the code which frees the Rectangle\_t
295structure:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700296\begin{codesample}
297Rectangle_t *rect = ...;
Lev Walkined44bf42010-11-08 02:04:55 -0800298
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700299asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
300\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800301This code defines a \emph{rect} pointer which points to the Rectangle\_t
302structure which needs to be freed. The second line invokes the generic
303\emph{free\_struct()} routine created specifically for this Rectangle\_t
304structure. The \emph{asn\_DEF\_Rectangle} is the type descriptor,
305which holds a collection of routines to deal with the Rectangle\_t
306structure.
307
308The following member functions of the asn\_DEF\_Rectangle type descriptor
309are of interest:
310\begin{description}
311\item [{ber\_decoder}] This is the generic \emph{restartable}%
312\footnote{Restartable means that if the decoder encounters the end of the buffer,
313it will fail, but may later be invoked again with the rest of the
314buffer to continue decoding.%
315} BER decoder (Basic Encoding Rules). This decoder would create and/or
316fill the target structure for you. See Section \vref{sub:Decoding-BER}.
317\item [{der\_encoder}] This is the generic DER encoder (Distinguished Encoding
318Rules). This encoder will take the target structure and encode it
319into a series of bytes. See Section \vref{sub:Encoding-DER}. NOTE:
320DER encoding is a subset of BER. Any BER decoder should be able to
321handle DER input.
322\item [{xer\_decoder}] This is the generic XER decoder. It takes both BASIC-XER
323or CANONICAL-XER encodings and deserializes the data into a local,
324machine-dependent representation. See Section \vref{sub:Decoding-XER}.
325\item [{xer\_encoder}] This is the XER encoder (XML Encoding Rules). This
326encoder will take the target structure and represent it as an XML
327(text) document using either BASIC-XER or CANONICAL-XER encoding rules.
328See Section \vref{sub:Encoding-XER}.
329\item [{uper\_decoder}] This is the Unaligned PER decoder.
330\item [{uper\_encoder}] This is the Unaligned Basic PER encoder. This encoder
331will take the target structure and encode it into a series of bytes.
332\item [{check\_constraints}] Check that the contents of the target structure
333are semantically valid and constrained to appropriate implicit or
334explicit subtype constraints. See Section \vref{sub:Validating-the-target}.
335\item [{print\_struct}] This function convert the contents of the passed
336target structure into human readable form. This form is not formal
337and cannot be converted back into the structure, but it may turn out
338to be useful for debugging or quick-n-dirty printing. See Section
339\vref{sub:Printing-the-target}.
340\item [{free\_struct}] This is a generic disposal which frees the target
341structure. See Section \vref{sub:Freeing-the-target}.
342\end{description}
343Each of the above function takes the type descriptor (\emph{asn\_DEF\_\ldots{}})
344and the target structure (\emph{rect}, in the above example).
345
346
347\subsection{\label{sub:Decoding-BER}Decoding BER}
348
349The Basic Encoding Rules describe the most widely used (by the ASN.1
350community) way to encode and decode a given structure in a machine-independent
351way. Several other encoding rules (CER, DER) define a more restrictive
352versions of BER, so the generic BER parser is also capable of decoding
353the data encoded by CER and DER encoders. The opposite is not true.
354
355\emph{The ASN.1 compiler provides the generic BER decoder which is
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700356capable of decoding BER, CER and DER encoded data.}
Lev Walkined44bf42010-11-08 02:04:55 -0800357
358The decoder is restartable (stream-oriented), which means that in
359case the buffer has less data than it is expected, the decoder will
360process whatever there is available and ask for more data to be provided.
361Please note that the decoder may actually process less data than it
362was given in the buffer, which means that you must be able to make
363the next buffer contain the unprocessed part of the previous buffer.
364
365Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
366\begin{itemize}
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700367\item You can concatenate these buffers and feed the BER decoder with 300
Lev Walkined44bf42010-11-08 02:04:55 -0800368bytes of data, or
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700369\item You can feed it the first buffer of 100 bytes of data, realize that
Lev Walkined44bf42010-11-08 02:04:55 -0800370the ber\_decoder consumed only 95 bytes from it and later feed the
371decoder with 205 bytes buffer which consists of 5 unprocessed bytes
372from the first buffer and the additional 200 bytes from the second
373buffer.
374\end{itemize}
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700375This is not as convenient as it could be (the BER encoder could
Lev Walkined44bf42010-11-08 02:04:55 -0800376consume the whole 100 bytes and keep these 5 bytes in some temporary
377storage), but in case of existing stream based processing it might
378actually fit well into existing algorithm. Suggestions are welcome.
379
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700380Here is the simplest example of BER decoding:
Lev Walkined44bf42010-11-08 02:04:55 -0800381
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700382\begin{codesample}
383Rectangle_t *
384simple_deserializer(const void *buffer, size_t buf_size) {
385 Rectangle_t *rect = 0; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
386 asn_dec_rval_t rval;
Lev Walkined44bf42010-11-08 02:04:55 -0800387
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700388 rval = %\textbf{asn\_DEF\_Rectangle.ber\_decoder}%(0,
389 &asn_DEF_Rectangle,
390 (void **)&rect, /* Decoder %\emph{moves}% the pointer */
391 buffer, buf_size,
392 0);
Lev Walkined44bf42010-11-08 02:04:55 -0800393
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700394 if(rval%\textbf{.code}% == RC_OK) {
395 return rect; /* Decoding succeeded */
396 } else {
397 /* Free partially decoded rect */
398 asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
399 return 0;
400 }
401}
402\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800403The code above defines a function, \emph{simple\_deserializer}, which
404takes a buffer and its length and is expected to return a pointer
405to the Rectangle\_t structure. Inside, it tries to convert the bytes
406passed into the target structure (rect) using the BER decoder and
407returns the rect pointer afterwards. If the structure cannot be deserialized,
408it frees the memory which might be left allocated by the unfinished
409\emph{ber\_decoder} routine and returns 0 (no data). (This \textbf{freeing
410is necessary} because the ber\_decoder is a restartable procedure,
411and may fail just because there is more data needs to be provided
412before decoding could be finalized). The code above obviously does
413not take into account the way the \emph{ber\_decoder()} failed, so
414the freeing is necessary because the part of the buffer may already
415be decoded into the structure by the time something goes wrong.
416
417A little less wordy would be to invoke a globally available \emph{ber\_decode()}
418function instead of dereferencing the asn\_DEF\_Rectangle type descriptor:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700419\begin{codesample}
420rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
421\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800422Note that the initial (asn\_DEF\_Rectangle.ber\_decoder) reference
423is gone, and also the last argument (0) is no longer necessary.
424
425These two ways of BER decoder invocations are fully equivalent.
426
427The BER de\emph{coder} may fail because of (\emph{the following RC\_\ldots{}
428codes are defined in ber\_decoder.h}):
429\begin{itemize}
430\item RC\_WMORE: There is more data expected than it is provided (stream
431mode continuation feature);
432\item RC\_FAIL: General failure to decode the buffer;
433\item \ldots{} other codes may be defined as well.
434\end{itemize}
435Together with the return code (.code) the asn\_dec\_rval\_t type contains
436the number of bytes which is consumed from the buffer. In the previous
437hypothetical example of two buffers (of 100 and 200 bytes), the first
438call to ber\_decode() would return with .code = RC\_WMORE and .consumed
439= 95. The .consumed field of the BER decoder return value is \textbf{always}
440valid, even if the decoder succeeds or fails with any other return
441code.
442
Lev Walkin464166c2010-11-09 08:34:38 -0800443Look into ber\_decoder.h for the precise definition of ber\_decode()
Lev Walkined44bf42010-11-08 02:04:55 -0800444and related types.
445
446
447\subsection{\label{sub:Encoding-DER}Encoding DER}
448
449The Distinguished Encoding Rules is the \emph{canonical} variant of
450BER encoding rules. The DER is best suited to encode the structures
451where all the lengths are known beforehand. This is probably exactly
452how you want to encode: either after a BER decoding or after a manual
453fill-up, the target structure contains the data which size is implicitly
454known before encoding. Among other uses, the DER encoding is used
455to encode X.509 certificates.
456
457As with BER decoder, the DER encoder may be invoked either directly
458from the ASN.1 type descriptor (asn\_DEF\_Rectangle) or from the stand-alone
459function, which is somewhat simpler:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700460\begin{codesample}
461/*
462 * This is the serializer itself.
463 * It supplies the DER encoder with the
464 * pointer to the custom output function.
465 */
466ssize_t
467simple_serializer(FILE *ostream, Rectangle_t *rect) {
468 asn_enc_rval_t er; /* Encoder return value */
Lev Walkined44bf42010-11-08 02:04:55 -0800469
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700470 er = der_encode(&asn_DEF_Rect, rect, write_stream, ostream);
471 if(er%\textbf{.encoded}% == -1) {
472 /*
473 * Failed to encode the rectangle data.
474 */
475 fprintf(stderr, "Cannot encode %\%%s: %\%%s\n",
476 er%\textbf{.failed\_type}%->name, strerror(errno));
477 return -1;
478 } else {
479 /* Return the number of bytes */
480 return er.encoded;
481 }
482}
483\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800484As you see, the DER encoder does not write into some sort of buffer
485or something. It just invokes the custom function (possible, multiple
486times) which would save the data into appropriate storage. The optional
487argument \emph{app\_key} is opaque for the DER encoder code and just
488used by \emph{\_write\_stream()} as the pointer to the appropriate
489output stream to be used.
490
491If the custom write function is not given (passed as 0), then the
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700492DER encoder will essentially do the same thing (i.~e., encode the data)
Lev Walkined44bf42010-11-08 02:04:55 -0800493but no callbacks will be invoked (so the data goes nowhere). It may
494prove useful to determine the size of the structure's encoding before
495actually doing the encoding%
496\footnote{It is actually faster too: the encoder might skip over some computations
497which aren't important for the size determination.%
498}.
499
Lev Walkin464166c2010-11-09 08:34:38 -0800500Look into der\_encoder.h for the precise definition of der\_encode()
Lev Walkined44bf42010-11-08 02:04:55 -0800501and related types.
502
503
504\subsection{\label{sub:Encoding-XER}Encoding XER}
505
506The XER stands for XML Encoding Rules, where XML, in turn, is eXtensible
507Markup Language, a text-based format for information exchange. The
508encoder routine API comes in two flavors: stdio-based and callback-based.
509With the callback-based encoder, the encoding process is very similar
510to the DER one, described in Section \vref{sub:Encoding-DER}. The
511following example uses the definition of write\_stream() from up there.
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700512\begin{codesample}
513/*
514 * This procedure generates the XML document
515 * by invoking the XER encoder.
516 * NOTE: Do not copy this code verbatim!
517 * If the stdio output is necessary,
518 * use the xer_fprint() procedure instead.
519 * See Section%\vref{sub:Printing-the-target}%.
520 */
Lev Walkined44bf42010-11-08 02:04:55 -0800521int
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700522print_as_XML(FILE *ostream, Rectangle_t *rect) {
523 asn_enc_rval_t er; /* Encoder return value */
Lev Walkined44bf42010-11-08 02:04:55 -0800524
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700525 er = xer_encode(&asn_DEF_Rectangle, rect,
526 XER_F_BASIC, /* BASIC-XER or CANONICAL-XER */
527 write_stream, ostream);
Lev Walkined44bf42010-11-08 02:04:55 -0800528
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700529 return (er.encoded == -1) ? -1 : 0;
530}
531\end{codesample}
Lev Walkin464166c2010-11-09 08:34:38 -0800532Look into xer\_encoder.h for the precise definition of xer\_encode()
Lev Walkined44bf42010-11-08 02:04:55 -0800533and related types.
534
535See Section \ref{sub:Printing-the-target} for the example of stdio-based
536XML encoder and other pretty-printing suggestions.
537
538
539\subsection{\label{sub:Decoding-XER}Decoding XER}
540
541The data encoded using the XER rules can be subsequently decoded using
542the xer\_decode() API call:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700543\begin{codesample}
544Rectangle_t *
545XML_to_Rectangle(const void *buffer, size_t buf_size) {
546 Rectangle_t *rect = 0; /* %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
547 asn_dec_rval_t rval;
Lev Walkined44bf42010-11-08 02:04:55 -0800548
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700549 rval = xer_decode(0, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
Lev Walkined44bf42010-11-08 02:04:55 -0800550
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700551 if(rval%\textbf{.code}% == RC_OK) {
552 return rect; /* Decoding succeeded */
553 } else {
554 /* Free partially decoded rect */
555 asn_DEF_Rectangle.free_struct(&asn_DEF_Rectangle, rect, 0);
556 return 0;
557 }
558}
559\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800560The decoder takes both BASIC-XER and CANONICAL-XER encodings.
561
562The decoder shares its data consumption properties with BER decoder;
563please read the Section \vref{sub:Decoding-BER} to know more.
564
Lev Walkin464166c2010-11-09 08:34:38 -0800565Look into xer\_decoder.h for the precise definition of xer\_decode()
Lev Walkined44bf42010-11-08 02:04:55 -0800566and related types.
567
568
569\subsection{\label{sub:Validating-the-target}Validating the target structure}
570
571Sometimes the target structure needs to be validated. For example,
572if the structure was created by the application (as opposed to being
573decoded from some external source), some important information required
574by the ASN.1 specification might be missing. On the other hand, the
575successful decoding of the data from some external source does not
576necessarily mean that the data is fully valid either. It might well
577be the case that the specification describes some subtype constraints
578that were not taken into account during decoding, and it would actually
579be useful to perform the last check when the data is ready to be encoded
580or when the data has just been decoded to ensure its validity according
581to some stricter rules.
582
583The asn\_check\_constraints() function checks the type for various
584implicit and explicit constraints. It is recommended to use asn\_check\_constraints()
585function after each decoding and before each encoding.
586
Lev Walkin464166c2010-11-09 08:34:38 -0800587Look into constraints.h for the precise definition of asn\_check\_constraints()
Lev Walkined44bf42010-11-08 02:04:55 -0800588and related types.
589
590
591\subsection{\label{sub:Printing-the-target}Printing the target structure}
592
593There are two ways to print the target structure: either invoke the
594print\_struct member of the ASN.1 type descriptor, or using the asn\_fprint()
595function, which is a simpler wrapper of the former:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700596\begin{codesample}
597asn_fprint(stdout, &asn_DEF_Rectangle, rect);
598\end{codesample}
Lev Walkin464166c2010-11-09 08:34:38 -0800599Look into constr\_TYPE.h for the precise definition of asn\_fprint()
Lev Walkined44bf42010-11-08 02:04:55 -0800600and related types.
601
602Another practical alternative to this custom format printing would
603be to invoke XER encoder. The default BASIC-XER encoder performs reasonable
604formatting for the output to be useful and human readable. To invoke
605the XER decoder in a manner similar to asn\_fprint(), use the xer\_fprint()
606call:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700607\begin{codesample}
608xer_fprint(stdout, &asn_DEF_Rectangle, rect);
609\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800610See Section \vref{sub:Encoding-XER} for XML-related details.
611
612
613\subsection{\label{sub:Freeing-the-target}Freeing the target structure}
614
615Freeing the structure is slightly more complex than it may seem to.
616When the ASN.1 structure is freed, all the members of the structure
617and their submembers are recursively freed as well. But it might not
618be feasible to free the structure itself. Consider the following case:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700619\begin{codesample}
620struct my_figure { /* The custom structure */
621 int flags; /* <some custom member> */
622 /* The type is generated by the ASN.1 compiler */
623 Rectangle_t rect;
624 /* other members of the structure */
625};
626\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800627In this example, the application programmer defined a custom structure
628with one ASN.1-derived member (rect). This member is not a reference
629to the Rectangle\_t, but an in-place inclusion of the Rectangle\_t
630structure. If the freeing is necessary, the usual procedure of freeing
631everything must not be applied to the \&rect pointer itself, because
632it does not point to the memory block directly allocated by the memory
633allocation routine, but instead lies within a block allocated for
634the my\_figure structure.
635
636To solve this problem, the free\_struct routine has the additional
637argument (besides the obvious type descriptor and target structure
638pointers), which is the flag specifying whether the outer pointer
639itself must be freed (0, default) or it should be left intact (non-zero
640value).
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700641\begin{codesample}
642/* %\textbf{1. Rectangle\_t is defined within my\_figure}% */
643struct my_figure {
644 Rectangle_t rect;
645} *mf = ...;
646/*
647 * Freeing the Rectangle_t
648 * without freeing the mf->rect area.
649 */
650asn_DEF_Rectangle.free_struct(
651 &asn_DEF_Rectangle, &mf->rect, %\textbf{1 /* !free */}%);
652
653/* %\textbf{2. Rectangle\_t is a stand-alone pointer}% */
654Rectangle_t *rect = ...;
655/*
656 * Freeing the Rectangle_t
657 * and freeing the rect pointer.
658 */
659asn_DEF_Rectangle.free_struct(
660 &asn_DEF_Rectangle, rect, %\textbf{0 /* free the pointer too */}%);
661\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800662It is safe to invoke the \emph{free\_struct} function with the target
663structure pointer set to 0 (NULL), the function will do nothing.
664
665For the programmer's convenience, the following macros are available:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700666\begin{codesample}
667ASN_STRUCT_FREE(asn_DEF, ptr);
668ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr);
669\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800670These macros bear the same semantics as the \emph{free\_struct} function
671invocation, discussed above.
672
673
674\chapter{\label{cha:Step-by-step-examples}Step by step examples}
675
676
Lev Walkin464166c2010-11-09 08:34:38 -0800677\section{A ``Rectangle'' Encoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800678
679This example will help you create a simple BER and XER encoder of
Lev Walkin464166c2010-11-09 08:34:38 -0800680a ``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800681\begin{enumerate}
682\item Create a file named \textbf{rectangle.asn1} with the following contents:
683
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700684\begin{asn}
685RectangleModule1 DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800686
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700687Rectangle ::= SEQUENCE {
688 height INTEGER,
689 width INTEGER
690}
Lev Walkined44bf42010-11-08 02:04:55 -0800691
692END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700693\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800694\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
695
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700696\begin{bash}
Lev Walkin2a744a72013-03-27 01:56:23 -0700697asn1c %\textbf{rectangle.asn1}%
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700698\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800699\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
700the \textbf{rectangle.asn1} file into the Web form and unpacking the
701produced archive on your computer.
702\item By this time, you should have gotten multiple files in the current
703directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
704\item Create a main() routine which creates the Rectangle\_t structure in
705memory and encodes it using BER and XER encoding rules. Let's name
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700706the file \textbf{main.c}:
Lev Walkined44bf42010-11-08 02:04:55 -0800707
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700708\begin{codesample}[basicstyle=\scriptsize\listingfont]
709#include <stdio.h>
710#include <sys/types.h>
711#include <Rectangle.h> /* Rectangle ASN.1 type */
Lev Walkined44bf42010-11-08 02:04:55 -0800712
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700713/* Write the encoded output into some FILE stream. */
714static int write_out(const void *buffer, size_t size, void *app_key) {
715 FILE *out_fp = app_key;
716 size_t wrote = fwrite(buffer, 1, size, out_fp);
717 return (wrote == size) ? 0 : -1;
718}
719
720int main(int ac, char **av) {
721 Rectangle_t *rectangle; /* Type to encode */
722 asn_enc_rval_t ec; /* Encoder return value */
Lev Walkined44bf42010-11-08 02:04:55 -0800723
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700724 /* Allocate the Rectangle_t */
725 rectangle = calloc(1, sizeof(Rectangle_t)); /* not malloc! */
726 if(!rectangle) {
727 perror("calloc() failed");
728 exit(1);
729 }
Lev Walkined44bf42010-11-08 02:04:55 -0800730
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700731 /* Initialize the Rectangle members */
732 rectangle->height = 42; /* any random value */
733 rectangle->width = 23; /* any random value */
Lev Walkined44bf42010-11-08 02:04:55 -0800734
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700735 /* BER encode the data if filename is given */
736 if(ac < 2) {
737 fprintf(stderr, "Specify filename for BER output\n");
738 } else {
739 const char *filename = av[1];
740 FILE *fp = fopen(filename, "wb"); /* for BER output */
741
742 if(!fp) {
743 perror(filename);
744 exit(1);
745 }
Lev Walkined44bf42010-11-08 02:04:55 -0800746
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700747 /* Encode the Rectangle type as BER (DER) */
748 ec = der_encode(&asn_DEF_Rectangle, rectangle, write_out, fp);
749 fclose(fp);
750 if(ec.encoded == -1) {
751 fprintf(stderr, "Could not encode Rectangle (at %\%%s)\n",
752 ec.failed_type ? ec.failed_type->name : "unknown");
753 exit(1);
754 } else {
755 fprintf(stderr, "Created %\%%s with BER encoded Rectangle\n", filename);
756 }
757 }
Lev Walkined44bf42010-11-08 02:04:55 -0800758
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700759 /* Also print the constructed Rectangle XER encoded (XML) */
760 xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
Lev Walkined44bf42010-11-08 02:04:55 -0800761
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700762 return 0; /* Encoding finished successfully */
763 }
764\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800765\item Compile all files together using C compiler (varies by platform):
766
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700767\begin{bash}
768cc -I. -o %\textbf{\emph{rencode}} \emph{*.c}%
769\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800770\item Voila! You have just created the BER and XER encoder of a Rectangle
771type, named \textbf{rencode}!
772\end{enumerate}
Lev Walkined44bf42010-11-08 02:04:55 -0800773
Lev Walkin464166c2010-11-09 08:34:38 -0800774\section{\label{sec:A-Rectangle-Decoder}A ``Rectangle'' Decoder}
Lev Walkined44bf42010-11-08 02:04:55 -0800775
776This example will help you to create a simple BER decoder of a simple
Lev Walkin464166c2010-11-09 08:34:38 -0800777``Rectangle'' type used throughout this document.
Lev Walkined44bf42010-11-08 02:04:55 -0800778\begin{enumerate}
779\item Create a file named \textbf{rectangle.asn1} with the following contents:
780
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700781\begin{asn}
782RectangleModule1 DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800783
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700784Rectangle ::= SEQUENCE {
785 height INTEGER,
786 width INTEGER
787}
Lev Walkined44bf42010-11-08 02:04:55 -0800788
789END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700790\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800791\item Compile it into the set of .c and .h files using asn1c compiler \cite{ASN1C}:
792
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700793\begin{bash}
Lev Walkin2a744a72013-03-27 01:56:23 -0700794asn1c %\textbf{rectangle.asn1}%
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700795\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800796\item Alternatively, use the Online ASN.1 compiler \cite{AONL} by uploading
797the \textbf{rectangle.asn1} file into the Web form and unpacking the
798produced archive on your computer.
799\item By this time, you should have gotten multiple files in the current
800directory, including the \textbf{Rectangle.c} and \textbf{Rectangle.h}.
801\item Create a main() routine which takes the binary input file, decodes
802it as it were a BER-encoded Rectangle type, and prints out the text
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700803(XML) representation of the Rectangle type. Let's name the file \textbf{main.c}:
Lev Walkined44bf42010-11-08 02:04:55 -0800804
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700805\begin{codesample}[basicstyle=\scriptsize\listingfont]
806#include <stdio.h>
807#include <sys/types.h>
808#include <Rectangle.h> /* Rectangle ASN.1 type */
Lev Walkined44bf42010-11-08 02:04:55 -0800809
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700810int main(int ac, char **av) {
811 char buf[1024]; /* Temporary buffer */
812 Rectangle_t *rectangle = 0; /* Type to decode. %\textbf{\color{red}Note this 0\footnote{Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.}!}% */
813 asn_dec_rval_t rval; /* Decoder return value */
814 FILE *fp; /* Input file handler */
815 size_t size; /* Number of bytes read */
816 char *filename; /* Input file name */
Lev Walkined44bf42010-11-08 02:04:55 -0800817
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700818 /* Require a single filename argument */
819 if(ac != 2) {
820 fprintf(stderr, "Usage: %\%%s <file.ber>\n", av[0]);
821 exit(1);
822 } else {
823 filename = av[1];
824 }
Lev Walkined44bf42010-11-08 02:04:55 -0800825
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700826 /* Open input file as read-only binary */
827 fp = fopen(filename, "rb");
828 if(!fp) {
829 perror(filename);
830 exit(1);
831 }
Lev Walkined44bf42010-11-08 02:04:55 -0800832
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700833 /* Read up to the buffer size */
834 size = fread(buf, 1, sizeof(buf), fp);
835 fclose(fp);
836 if(!size) {
837 fprintf(stderr, "%\%%s: Empty or broken\n", filename);
838 exit(1);
839 }
Lev Walkined44bf42010-11-08 02:04:55 -0800840
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700841 /* Decode the input buffer as Rectangle type */
842 rval = ber_decode(0, &asn_DEF_Rectangle, (void **)&rectangle, buf, size);
843 if(rval.code != RC_OK) {
844 fprintf(stderr, "%\%%s: Broken Rectangle encoding at byte %\%%ld\n", filename, (long)rval.consumed);
845 exit(1);
846 }
Lev Walkined44bf42010-11-08 02:04:55 -0800847
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700848 /* Print the decoded Rectangle type as XML */
849 xer_fprint(stdout, &asn_DEF_Rectangle, rectangle);
Lev Walkined44bf42010-11-08 02:04:55 -0800850
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700851 return 0; /* Decoding finished successfully */
852\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800853\item Compile all files together using C compiler (varies by platform):
854
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700855\begin{bash}
856cc -I. -o %\textbf{\emph{rdecode}} \emph{*.c}%
857\end{bash}
Lev Walkined44bf42010-11-08 02:04:55 -0800858\item Voila! You have just created the BER decoder of a Rectangle type,
859named \textbf{rdecode}!
860\end{enumerate}
861
862\chapter{Constraint validation examples}
863
864This chapter shows how to define ASN.1 constraints and use the generated
865validation code.
866
867
Lev Walkin464166c2010-11-09 08:34:38 -0800868\section{Adding constraints into ``Rectangle'' type}
Lev Walkined44bf42010-11-08 02:04:55 -0800869
870This example shows how to add basic constraints to the ASN.1 specification
871and how to invoke the constraints validation code in your application.
872\begin{enumerate}
873\item Create a file named \textbf{rectangle.asn1} with the following contents:
874
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700875\begin{asn}
876RectangleModuleWithConstraints DEFINITIONS ::= BEGIN
Lev Walkined44bf42010-11-08 02:04:55 -0800877
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700878Rectangle ::= SEQUENCE {
879 height INTEGER (0..100), -- Value range constraint
880 width INTEGER (0..MAX) -- Makes width non-negative
881}
Lev Walkined44bf42010-11-08 02:04:55 -0800882
883END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700884\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800885\item Compile the file according to procedures shown in the previous chapter.
886\item Modify the Rectangle type processing routine (you can start with the
887main() routine shown in the Section \vref{sec:A-Rectangle-Decoder})
888by placing the following snippet of code \emph{before} encoding and/or
889\emph{after} decoding the Rectangle type%
890\footnote{Placing the constraint checking code \emph{before} encoding helps
891to make sure you know the data is correct and within constraints before
892sharing the data with anyone else.
893
894Placing the constraint checking code \emph{after} decoding, but before
895any further action depending on the decoded data, helps to make sure
896the application got the valid contents before making use of it.%
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700897}:
Lev Walkined44bf42010-11-08 02:04:55 -0800898
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700899\begin{codesample}
900int ret; /* Return value */
901char errbuf[128]; /* Buffer for error message */
902size_t errlen = sizeof(errbuf); /* Size of the buffer */
Lev Walkined44bf42010-11-08 02:04:55 -0800903
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700904/* ... here may go Rectangle %\emph{decoding}% code ... */
Lev Walkined44bf42010-11-08 02:04:55 -0800905
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700906ret = asn_check_constraints(&asn_DEF_Rectangle, rectangle, errbuf, &errlen);
907/* assert(errlen < sizeof(errbuf)); // you may rely on that */
908if(ret) {
909 fprintf(stderr, "Constraint validation failed: %\%%s\n",
910 errbuf /* errbuf is properly nul-terminated */
911 );
912 /* exit(...); // Replace with appropriate action */
913 }
Lev Walkined44bf42010-11-08 02:04:55 -0800914
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700915/* ... here may go Rectangle %\emph{encoding}% code ... */
916\end{codesample}
Lev Walkined44bf42010-11-08 02:04:55 -0800917\item Compile the resulting C code as shown in the previous chapters.
918\item Try to test the constraints checking code by assigning integer value
919101 to the \textbf{.height} member of the Rectangle structure, or
920a negative value to the \textbf{.width} member. In either case, the
Lev Walkin464166c2010-11-09 08:34:38 -0800921program should print ``Constraint validation failed'' message, followed
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700922by a short explanation why validation did not succeed.
Lev Walkined44bf42010-11-08 02:04:55 -0800923\item Done.
924\end{enumerate}
925
926\part{\label{par:ASN.1-Basics}ASN.1 Basics}
927
928
929\chapter{\label{cha:Abstract-Syntax-Notation:}Abstract Syntax Notation: ASN.1}
930
931\emph{This chapter defines some basic ASN.1 concepts and describes
932several most widely used types. It is by no means an authoritative
933or complete reference. For more complete ASN.1 description, please
934refer to Olivier Dubuisson's book \cite{Dub00} or the ASN.1 body
935of standards itself \cite{ITU-T/ASN.1}.}
936
937The Abstract Syntax Notation One is used to formally describe the
938semantics of data transmitted across the network. Two communicating
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700939parties may have different formats of their native data types (i.~e.
Lev Walkined44bf42010-11-08 02:04:55 -0800940number of bits in the integer type), thus it is important to have
941a way to describe the data in a manner which is independent from the
942particular machine's representation. The ASN.1 specifications are
943used to achieve the following:
944\begin{itemize}
945\item The specification expressed in the ASN.1 notation is a formal and
946precise way to communicate the data semantics to human readers;
947\item The ASN.1 specifications may be used as input for automatic compilers
948which produce the code for some target language (C, C++, Java, etc)
949to encode and decode the data according to some encoding rules (which
950are also defined by the ASN.1 standard).
951\end{itemize}
952Consider the following example:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700953\begin{asn}
954Rectangle ::= SEQUENCE {
955 height INTEGER,
956 width INTEGER
957}
958\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800959This ASN.1 specification describes a constructed type, \emph{Rectangle},
960containing two integer fields. This specification may tell the reader
961that there exists this kind of data structure and that some entity
962may be prepared to send or receive it. The question on \emph{how}
963that entity is going to send or receive the \emph{encoded data} is
964outside the scope of ASN.1. For example, this data structure may be
965encoded according to some encoding rules and sent to the destination
966using the TCP protocol. The ASN.1 specifies several ways of encoding
Lev Walkin464166c2010-11-09 08:34:38 -0800967(or ``serializing'', or ``marshaling'') the data: BER, PER, XER
Lev Walkined44bf42010-11-08 02:04:55 -0800968and others, including CER and DER derivatives from BER.
969
970The complete specification must be wrapped in a module, which looks
971like this:
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700972\begin{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800973RectangleModule1
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700974 { iso org(3) dod(6) internet(1) private(4)
975 enterprise(1) spelio(9363) software(1)
976 asn1c(5) docs(2) rectangle(1) 1 }
977 DEFINITIONS AUTOMATIC TAGS ::=
Lev Walkined44bf42010-11-08 02:04:55 -0800978BEGIN
979
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700980-- This is a comment which describes nothing.
981Rectangle ::= SEQUENCE {
982 height INTEGER, -- Height of the rectangle
983 width INTEGER -- Width of the rectangle
984}
Lev Walkined44bf42010-11-08 02:04:55 -0800985
986END
Lev Walkin11c9a8c2013-03-26 00:46:55 -0700987\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -0800988The module header consists of module name (RectangleModule1), the
Lev Walkin464166c2010-11-09 08:34:38 -0800989module object identifier (\{...\}), a keyword ``DEFINITIONS'', a
990set of module flags (AUTOMATIC TAGS) and ``::= BEGIN''. The module
991ends with an ``END'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -0800992
993
994\section{Some of the ASN.1 Basic Types}
995
996
997\subsection{The BOOLEAN type}
998
999The BOOLEAN type models the simple binary TRUE/FALSE, YES/NO, ON/OFF
1000or a similar kind of two-way choice.
1001
1002
1003\subsection{The INTEGER type}
1004
1005The INTEGER type is a signed natural number type without any restrictions
1006on its size. If the automatic checking on INTEGER value bounds are
1007necessary, the subtype constraints must be used.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001008\begin{asn}
1009SimpleInteger ::= INTEGER
Lev Walkined44bf42010-11-08 02:04:55 -08001010
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001011-- An integer with a very limited range
1012SmallPositiveInt ::= INTEGER (0..127)
Lev Walkined44bf42010-11-08 02:04:55 -08001013
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001014-- Integer, negative
1015NegativeInt ::= INTEGER (MIN..0)
1016\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001017
1018\subsection{The ENUMERATED type}
1019
1020The ENUMERATED type is semantically equivalent to the INTEGER type
1021with some integer values explicitly named.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001022\begin{asn}
1023FruitId ::= ENUMERATED { apple(1), orange(2) }
Lev Walkined44bf42010-11-08 02:04:55 -08001024
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001025-- The numbers in braces are optional,
1026-- the enumeration can be performed
1027-- automatically by the compiler
1028ComputerOSType ::= ENUMERATED {
1029 FreeBSD, -- acquires value 0
1030 Windows, -- acquires value 1
1031 Solaris(5), -- remains 5
1032 Linux, -- becomes 6
1033 MacOS -- becomes 7
1034}
1035\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001036
1037\subsection{The OCTET STRING type}
1038
1039This type models the sequence of 8-bit bytes. This may be used to
1040transmit some opaque data or data serialized by other types of encoders
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001041(i.~e., video file, photo picture, etc).
Lev Walkined44bf42010-11-08 02:04:55 -08001042
1043\subsection{The OBJECT IDENTIFIER type}
1044
1045The OBJECT IDENTIFIER is used to represent the unique identifier of
1046any object, starting from the very root of the registration tree.
1047If your organization needs to uniquely identify something (a router,
1048a room, a person, a standard, or whatever), you are encouraged to
1049get your own identification subtree at \url{http://www.iana.org/protocols/forms.htm}.
1050
1051For example, the very first ASN.1 module in this Chapter (RectangleModule1)
1052has the following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001053\begin{asn}
1054ExampleOID ::= OBJECT IDENTIFIER
Lev Walkined44bf42010-11-08 02:04:55 -08001055
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001056rectangleModule1-oid ExampleOID
1057 ::= { 1 3 6 1 4 1 9363 1 5 2 1 1 }
Lev Walkined44bf42010-11-08 02:04:55 -08001058
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001059-- An identifier of the Internet.
1060internet-id OBJECT IDENTIFIER
1061 ::= { iso(1) identified-organization(3)
1062 dod(6) internet(1) }
1063\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001064As you see, names are optional.
1065
1066
1067\subsection{The RELATIVE-OID type}
1068
1069The RELATIVE-OID type has the semantics of a subtree of an OBJECT
1070IDENTIFIER. There may be no need to repeat the whole sequence of numbers
1071from the root of the registration tree where the only thing of interest
1072is some of the tree's subsequence.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001073\begin{asn}
1074this-document RELATIVE-OID ::= { docs(2) usage(1) }
Lev Walkined44bf42010-11-08 02:04:55 -08001075
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001076this-example RELATIVE-OID ::= {
1077 this-document assorted-examples(0) this-example(1) }
1078\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001079
1080\section{Some of the ASN.1 String Types}
1081
1082
1083\subsection{The IA5String type}
1084
1085This is essentially the ASCII, with 128 character codes available
1086(7 lower bits of an 8-bit byte).
1087
1088
1089\subsection{The UTF8String type}
1090
1091This is the character string which encodes the full Unicode range
1092(4 bytes) using multibyte character sequences.
1093
1094
1095\subsection{The NumericString type}
1096
1097This type represents the character string with the alphabet consisting
Lev Walkin464166c2010-11-09 08:34:38 -08001098of numbers (``0'' to ``9'') and a space.
Lev Walkined44bf42010-11-08 02:04:55 -08001099
1100
1101\subsection{The PrintableString type}
1102
Lev Walkin464166c2010-11-09 08:34:38 -08001103The character string with the following alphabet: space, ``\textbf{'}''
1104(single quote), ``\textbf{(}'', ``\textbf{)}'', ``\textbf{+}'',
1105``\textbf{,}'' (comma), ``\textbf{-}'', ``\textbf{.}'', ``\textbf{/}'',
1106digits (``0'' to ``9''), ``\textbf{:}'', ``\textbf{=}'', ``\textbf{?}'',
1107upper-case and lower-case letters (``A'' to ``Z'' and ``a''
1108to ``z'').
Lev Walkined44bf42010-11-08 02:04:55 -08001109
1110
1111\subsection{The VisibleString type}
1112
1113The character string with the alphabet which is more or less a subset
Lev Walkin464166c2010-11-09 08:34:38 -08001114of ASCII between the space and the ``\textbf{\textasciitilde{}}''
Lev Walkined44bf42010-11-08 02:04:55 -08001115symbol (tilde).
1116
1117Alternatively, the alphabet may be described as the PrintableString
Lev Walkin464166c2010-11-09 08:34:38 -08001118alphabet presented earlier, plus the following characters: ``\textbf{!}'',
1119``\textbf{``}'', ``\textbf{\#}'', ``\textbf{\$}'', ``\textbf{\%}'',
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001120``\textbf{\&}'', ``\textbf{*}'', ``\textbf{;}'', ``\textbf{<}'',
Lev Walkin464166c2010-11-09 08:34:38 -08001121``\textbf{>}'', ``\textbf{{[}}'', ``\textbf{\textbackslash{}}'',
1122``\textbf{{]}}'', ``\textbf{\textasciicircum{}}'', ``\textbf{\_}'',
1123``\textbf{`}`` (single left quote), ``\textbf{\{}'', ``\textbf{|}'',
1124``\textbf{\}}'', ``\textbf{\textasciitilde{}}''.
Lev Walkined44bf42010-11-08 02:04:55 -08001125
1126
1127\section{ASN.1 Constructed Types}
1128
1129
1130\subsection{The SEQUENCE type}
1131
1132This is an ordered collection of other simple or constructed types.
Lev Walkin464166c2010-11-09 08:34:38 -08001133The SEQUENCE constructed type resembles the C ``struct'' statement.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001134\begin{asn}
1135Address ::= SEQUENCE {
1136 -- The apartment number may be omitted
1137 apartmentNumber NumericString OPTIONAL,
1138 streetName PrintableString,
1139 cityName PrintableString,
1140 stateName PrintableString,
1141 -- This one may be omitted too
1142 zipNo NumericString OPTIONAL
1143}
1144\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001145
1146\subsection{The SET type}
1147
1148This is a collection of other simple or constructed types. Ordering
1149is not important. The data may arrive in the order which is different
1150from the order of specification. Data is encoded in the order not
1151necessarily corresponding to the order of specification.
1152
1153
1154\subsection{The CHOICE type}
1155
1156This type is just a choice between the subtypes specified in it. The
1157CHOICE type contains at most one of the subtypes specified, and it
1158is always implicitly known which choice is being decoded or encoded.
Lev Walkin464166c2010-11-09 08:34:38 -08001159This one resembles the C ``union'' statement.
Lev Walkined44bf42010-11-08 02:04:55 -08001160
1161The following type defines a response code, which may be either an
Lev Walkin464166c2010-11-09 08:34:38 -08001162integer code or a boolean ``true''/``false'' code.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001163\begin{asn}
1164ResponseCode ::= CHOICE {
1165 intCode INTEGER,
1166 boolCode BOOLEAN
1167}
1168\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001169
1170\subsection{The SEQUENCE OF type}
1171
1172This one is the list (array) of simple or constructed types:
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001173\begin{asn}
1174-- Example 1
1175ManyIntegers ::= SEQUENCE OF INTEGER
Lev Walkined44bf42010-11-08 02:04:55 -08001176
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001177-- Example 2
1178ManyRectangles ::= SEQUENCE OF Rectangle
Lev Walkined44bf42010-11-08 02:04:55 -08001179
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001180-- More complex example:
1181-- an array of structures defined in place.
1182ManyCircles ::= SEQUENCE OF SEQUENCE {
1183 radius INTEGER
1184 }
1185\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001186
1187\subsection{The SET OF type}
1188
1189The SET OF type models the bag of structures. It resembles the SEQUENCE
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001190OF type, but the order is not important: i.~e. the elements may arrive
Lev Walkined44bf42010-11-08 02:04:55 -08001191in the order which is not necessarily the same as the in-memory order
1192on the remote machines.
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001193\begin{asn}
1194-- A set of structures defined elsewhere
1195SetOfApples :: SET OF Apple
Lev Walkined44bf42010-11-08 02:04:55 -08001196
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001197-- Set of integers encoding the kind of a fruit
1198FruitBag ::= SET OF ENUMERATED { apple, orange }
1199\end{asn}
Lev Walkined44bf42010-11-08 02:04:55 -08001200\begin{thebibliography}{ITU-T/ASN.1}
1201\bibitem[ASN1C]{ASN1C}The Open Source ASN.1 Compiler. \url{http://lionet.info/asn1c}
1202
1203\bibitem[AONL]{AONL}Online ASN.1 Compiler. \url{http://lionet.info/asn1c/asn1c.cgi}
1204
1205\bibitem[Dub00]{Dub00}Olivier Dubuisson --- \emph{ASN.1 Communication
Lev Walkin11c9a8c2013-03-26 00:46:55 -07001206between heterogeneous systems} --- Morgan Kaufmann Publishers, 2000.
Lev Walkined44bf42010-11-08 02:04:55 -08001207\url{http://asn1.elibel.tm.fr/en/book/}. ISBN:0-12-6333361-0.
1208
Lev Walkin464166c2010-11-09 08:34:38 -08001209\bibitem[ITU-T/ASN.1]{ITU-T/ASN.1}ITU-T Study Group 17 --- Languages
Lev Walkined44bf42010-11-08 02:04:55 -08001210for Telecommunication Systems \url{http://www.itu.int/ITU-T/studygroups/com17/languages/}
1211\end{thebibliography}
1212
1213\end{document}