Using The Open Source ASN.1 Compiler: Documentation For Asn1c Version 0.9.29
Using The Open Source ASN.1 Compiler: Documentation For Asn1c Version 0.9.29
1 Compiler
Documentation for asn1c version 0.9.29
2 ASN.1 Compiler 10
2.1 The asn1c compiler tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Compiler output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3 Command line options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3 API reference 16
3.1 ASN_STRUCT_FREE() macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 ASN_STRUCT_RESET() macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.3 asn_check_constraints() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4 asn_decode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.5 asn_encode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.6 asn_encode_to_buffer() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.7 asn_encode_to_new_buffer() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.8 asn_fprint() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.9 asn_random_fill() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.10 ber_decode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.11 der_encode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.12 der_encode_to_buffer() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.13 oer_decode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.14 oer_encode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.15 oer_encode_to_buffer() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
1
CONTENTS asn1c-0.9.29
3.16 uper_decode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.17 uper_decode_complete() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.18 uper_encode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.19 uper_encode_to_buffer() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.20 uper_encode_to_new_buffer() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.21 xer_decode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.22 xer_encode() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.23 xer_fprint() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2
CONTENTS asn1c-0.9.29
3
Chapter 1
END
4
CHAPTER 1. QUICK START EXAMPLES asn1c-0.9.29
END
2. Compile it into the set of .c and .h files using asn1c compiler [ASN1C]:
asn1c ିnoିgenିexample rectangle.asn
3. Alternatively, use the Online ASN.1 compiler [AONL] by uploading the rectangle.asn file
into the Web form and unpacking the produced archive on your computer.
4. By this time, you should have gotten multiple files in the current directory, including
the Rectangle.c and Rectangle.h.
5. Create a main() routine which creates the Rectangle_t structure in memory and encodes
it using BER and XER encoding rules. Let’s name the file main.c:
#include <stdio.h>
#include <sys/types.h>
#include <Rectangle.h> /* Rectangle ASN.1 type */
5
CHAPTER 1. QUICK START EXAMPLES asn1c-0.9.29
if(!rectangle) {
perror(”calloc() failed”);
exit(1);
}
if(!fp) {
perror(filename);
exit(1);
}
7. Done. You have just created the BER and XER encoder of a Rectangle type, named
rencode!
6
CHAPTER 1. QUICK START EXAMPLES asn1c-0.9.29
END
2. Compile it into the set of .c and .h files using asn1c compiler [ASN1C]:
asn1c ିnoିgenିexample rectangle.asn
3. Alternatively, use the Online ASN.1 compiler [AONL] by uploading the rectangle.asn file
into the Web form and unpacking the produced archive on your computer.
4. By this time, you should have gotten multiple files in the current directory, including
the Rectangle.c and Rectangle.h.
5. Create a main() routine which takes the binary input file, decodes it as it were a BER-
encoded Rectangle type, and prints out the text (XML) representation of the Rectangle
type. Let’s name the file main.c:
#include <stdio.h>
#include <sys/types.h>
#include <Rectangle.h> /* Rectangle ASN.1 type */
1
Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.
7
CHAPTER 1. QUICK START EXAMPLES asn1c-0.9.29
if(ac != 2) {
fprintf(stderr, ”Usage: %s <file.ber>\n”, av[0]);
exit(1);
} else {
filename = av[1];
}
7. Done. You have just created the BER decoder of a Rectangle type, named rdecode!
8
CHAPTER 1. QUICK START EXAMPLES asn1c-0.9.29
END
3. Modify the Rectangle type processing routine (you can start with the main() routine
shown in the section 1.3 on page 7) by placing the following snippet of code before
encoding and/or after decoding the Rectangle type:
int ret; /* Return value */
char errbuf[128]; /* Buffer for error message */
size_t errlen = sizeof(errbuf); /* Size of the buffer */
5. Test the constraints checking code by assigning integer value 101 to the .height member
of the Rectangle structure, or a negative value to the .width member. The program will
fail with “Constraint validation failed” message.
6. Done.
9
Chapter 2
ASN.1 Compiler
END
The asn1c compiler reads this ASN.1 definition and produce the following C type:
typedef struct Rectangle_s {
long height;
long width;
} Rectangle_t;
2
Chapter 5 on page 64 provides a quick reference on the ASN.1 notation.
10
CHAPTER 2. ASN.1 COMPILER asn1c-0.9.29
The asn1c compiler also creates the code for converting this structure into platform-independent
wire representation and the decoder of such wire representation back into local, machine-
specific type. These encoders and decoders are also called serializers and deserializers, mar-
shallers and unmarshallers, or codecs.
Compiling ASN.1 modules into C codecs can be as simple as invoking asn1c: may be
used to compile the ASN.1 modules:
asn1c <modules.asn>
If several ASN.1 modules contain interdependencies, all of the files must be specified
altogether:
asn1c <module1.asn> <module2.asn> ...
The compiler -E and -EF options are used for testing the parser and the semantic fixer, re-
spectively. These options will instruct the compiler to dump out the parsed (and fixed, if -F
is involved) ASN.1 specification as it was understood by the compiler. It might be useful to
check whether a particular syntactic construct is properly supported by the compiler.
asn1c -EF <module-to-test.asn>
The -P option is used to dump the compiled output on the screen instead of creating a bunch
of .c and .h files on disk in the current directory. You would probably want to start with -P
option instead of creating a mess in your current directory. Another option, -R, asks compiler
to only generate the files which need to be generated, and supress linking in the numerous
support files.
Print the compiled output instead of creating multiple source files:
asn1c -P <module-to-compile-and-print.asn>
11
CHAPTER 2. ASN.1 COMPILER asn1c-0.9.29
• A set of .c and .h files for each type defined in the ASN.1 specification. These files will
be named similarly to the ASN.1 types (Rectangle.c and Rectangle.h for the Rectangle-
Module ASN.1 module defined in the beginning of this document).
• A set of helper .c and .h files which contain the generic encoders, decoders and other
useful routines. Sometimes they are referred to by the term skeletons. There will be
quite a few of them, some of them are not even always necessary, but the overall amount
of code after compilation will be rather small anyway.
• A Makefile.am.libasncodecs file which explicitly lists all the generated files. This make-
file can be used on its own to build the just the codec library.
• A converter-example.c file containing the int main() function with a fully functioning
encoder and data format converter. It can convert a given PDU between BER, XER, OER
and PER. At some point you will want to replace this file with your own file containing
the int main() function.
12
CHAPTER 2. ASN.1 COMPILER asn1c-0.9.29
-E Stop after the parsing stage and print the reconstructed ASN.1
specification code to the standard output.
-F Used together with -E, instructs the compiler to stop after
the ASN.1 syntax tree fixing stage and dump the reconstructed
ASN.1 specification to the standard output.
-P Dump the compiled output to the standard output instead of
creating the target language files on disk.
-R Restrict the compiler to generate only the ASN.1 tables, omit-
ting the usual support code.
-S <directory> Use the specified directory with ASN.1 skeleton files.
-X Generate the XML DTD for the specified ASN.1 modules.
13
CHAPTER 2. ASN.1 COMPILER asn1c-0.9.29
-no-gen-OER Do not generate the Octet Encoding Rules (OER, X.696) support
code.
-no-gen-PER Do not generate the Packed Encoding Rules (PER, X.691) sup-
port code.
-no-gen-example Do not generate the ASN.1 format converter example.
14
CHAPTER 2. ASN.1 COMPILER asn1c-0.9.29
-pdu={all|auto|Type} Create a PDU table for specified types, or discover the Proto-
col Data Units automatically. In case of -pdu=all, all ASN.1
types defined in all modules wil form a PDU table. In case of
-pdu=auto, all types not referenced by any other type will
form a PDU table. If Type is an ASN.1 type identifier, it is
added to a PDU table. The last form may be specified multiple
times.
-print-class-matrix When -EF options are given, this option instructs the compiler
to print out the collected Information Object Class matrix.
-print-constraints With -EF, this option instructs the compiler to explain its in-
ternal understanding of subtype constraints.
-print-lines Generate “-- #line” comments in -E output.
15
Chapter 3
API reference
The functions desribed in this chapter are to be used by the application programmer. These
functions won’t likely change change or get removed until the next major release.
The API calls not listed here are not public and should not be used by the application
level code.
16
CHAPTER 3. API REFERENCE asn1c-0.9.29
Description
Recursively releases memory occupied by the structure described by the type_descriptor
and referred to by the struct_ptr pointer.
Does nothing when struct_ptr is NULL.
Return values
Does not return a value.
Example
Rectangle_t *rect = ...;
ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
17
CHAPTER 3. API REFERENCE asn1c-0.9.29
Description
Recursively releases memory occupied by the members of the structure described by the
type_descriptor and referred to by the struct_ptr pointer.
Does not release the memory pointed to by struct_ptr itself. Instead it clears the
memory block by filling it out with 0 bytes.
Does nothing when struct_ptr is NULL.
Return values
Does not return a value.
Example
struct my_figure { /* The custom structure */
int flags; /* <some custom member> */
/* The type is generated by the ASN.1 compiler */
Rectangle_t rect;
/* other members of the structure */
};
18
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.3 asn_check_constraints()
Synopsis
int asn_check_constraints(
const asn_TYPE_descriptor_t *type_descriptor,
const void *struct_ptr, /* Target language’s structure */
char *errbuf, /* Returned error description */
size_t *errlen /* Length of the error description */
);
Description
Validate a given structure according to the ASN.1 constraints. If errbuf and errlen are
given, they shall point to the appropriate buffer space and its length before calling this func-
tion. Alternatively, they could be passed as NULLs. If constraints validation fails, errlen
will contain the actual number of bytes used in errbuf to encode an error message. The
message is going to be properly 0-terminated.
Return values
This function returns 0 in case all ASN.1 constraints are met and -1 if one or more ASN.1
constraints were violated.
Example
Rectangle_t *rect = ...;
19
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.4 asn_decode()
Synopsis
asn_dec_rval_t asn_decode(
const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
);
Description
The asn_decode() function parses the data given by the buffer and size arguments.
The encoding rules are specified in the syntax argument and the type to be decoded is
specified by the type_descriptor.
The struct_ptr_ptr must point to the memory location which contains the pointer
to the structure being decoded. Initially the *struct_ptr_ptr pointer is typically set
to 0. In that case, asn_decode() will dynamically allocate memory for the structure and
its members as needed during the parsing. If *struct_ptr_ptr already points to some
memory, the asn_decode() will allocate the subsequent members as needed during the
parsing.
Return values
Upon unsuccessful termination, the *struct_ptr_ptr may contain partially decoded
data. This data may be useful for debugging (such as by using asn_fprint()). Don’t
forget to discard the unused partially decoded data by calling ASN_STRUCT_FREE() or
ASN_STRUCT_RESET().
The function returns a compound structure:
typedef struct {
enum {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
20
CHAPTER 3. API REFERENCE asn1c-0.9.29
Restartability
Some transfer syntax parsers (such as ATS_BER) support restartability.
That means that in case the buffer has less data than expected, the asn_decode()
will process whatever is available and ask for more data to be provided using the RC_WMORE
return .code.
Note that in the RC_WMORE case the decoder may have processed less data than it is
available in the buffer, which means that you must be able to arrange the next buffer to
contain the unprocessed part of the previous buffer.
The RC_WMORE code may still be returned by parser not supporting restartabilty. In such
cases, the partially decoded structure shall be discarded and the next invocation should use
the extended buffer to parse from the very beginning.
Example
ᇦᇧᇧᇧᇧᇧᇧᇨ
Rectangle_t *rect = 0; /* Note this 01 ! */
asn_dec_rval_t rval;
rval = asn_decode(0, ATS_BER, &asn_DEF_Rectangle, (void **)&rect, buffer, buf_size);
switch(rval.code) {
case RC_OK:
asn_fprint(stdout, &asn_DEF_Rectangle, rect);
ASN_STRUCT_FREE(&asn_DEF_Rectangle, rect);
break;
case RC_WMORE:
case RC_FAIL:
default:
1
Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.
21
CHAPTER 3. API REFERENCE asn1c-0.9.29
ASN_STRUCT_FREE(&asn_DEF_Rectangle, rect);
break;
}
See also
asn_fprint() at page 29.
22
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.5 asn_encode()
Synopsis
#include <asn_application.h>
asn_enc_rval_t asn_encode(
const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,
const asn_TYPE_descriptor_t *type_to_encode,
const void *structure_to_encode,
asn_app_consume_bytes_f *callback, void *callback_key);
Description
The asn_encode() function serializes the given structure_to_encode using the
chosen ASN.1 transfer syntax.
During serialization, a user-specified callback is invoked zero or more times with bytes
of data to add to the output stream (if any), and the callback_key. The signature for the
callback is as follows:
typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t
size, void *callback_key);
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
23
CHAPTER 3. API REFERENCE asn1c-0.9.29
The serialized output size is returned in bytes irrespectively of the ASN.1 transfer syntax
chosen.1
On error (when .encoded is set to -1), the errno is set to one of the following values:
EINVAL Incorrect parameters to the function, such as NULLs
ENOENT Encoding transfer syntax is not defined (for this type)
EBADF The structure has invalid form or content constraint failed
EIO The callback has returned negative value during encoding
Example
static int
save_to_file(const void *data, size_t size, void *key) {
FILE *fp = key;
return (fwrite(data, 1, size, fp) == size) ? 0 : ି1;
}
1
This is different from some lower level encoding functions, such as uper_encode(), which returns the
number of encoded bits instead of bytes.
24
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.6 asn_encode_to_buffer()
Synopsis
#include <asn_application.h>
asn_enc_rval_t asn_encode_to_buffer(
const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,
const asn_TYPE_descriptor_t *type_to_encode,
const void *structure_to_encode,
void *buffer, size_t buffer_size);
Description
The asn_encode_to_buffer() function serializes the given structure_to_encode
using the chosen ASN.1 transfer syntax.
The function places the serialized data into the given buffer of size buffer_size.
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
The serialized output size is returned in bytes irrespectively of the ASN.1 transfer syntax
chosen.1
1
This is different from some lower level encoding functions, such as uper_encode(), which returns the
number of encoded bits instead of bytes.
25
CHAPTER 3. API REFERENCE asn1c-0.9.29
Example
Rectangle_t *rect = ...;
uint8_t buffer[128];
asn_enc_rval_t er;
er = asn_encode_to_buffer(0, ATS_DER, &asn_DEF_Rectangle, rect, buffer, sizeof(buffer));
if(er.encoded == ି1) {
fprintf(stderr, ”Serialization of %s failed.\n”, asn_DEF_Rectangle.name);
} else if(er.encoded > sizeof(buffer)) {
fprintf(stderr, ”Buffer of size %zu is too small for %s, need %zu\n”,
buf_size, asn_DEF_Rectangle.name, er.encoded);
}
See also
asn_encode_to_new_buffer() at page 27.
26
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.7 asn_encode_to_new_buffer()
Synopsis
#include <asn_application.h>
typedef struct {
void *buffer; /* NULL if failed to encode. */
asn_enc_rval_t result;
} asn_encode_to_new_buffer_result_t;
asn_encode_to_new_buffer_result_t asn_encode_to_new_buffer(
const asn_codec_ctx_t *opt_codec_ctx,
enum asn_transfer_syntax syntax,
const asn_TYPE_descriptor_t *type_to_encode,
const void *structure_to_encode);
Description
The asn_encode_to_new_buffer() function serializes the given structure_to_encode
using the chosen ASN.1 transfer syntax.
The function places the serialized data into the newly allocated buffer which it returns in
a compound structure.
Return values
On failure, the .buffer is set to NULL and .result.encoded is set to -1. The global
errno is set to one of the following values:
EINVAL Incorrect parameters to the function, such as NULLs
ENOENT Encoding transfer syntax is not defined (for this type)
EBADF The structure has invalid form or content constraint failed
ENOMEM Memory allocation failed due to system or internal limits
On success, the .result.encoded is set to the number of bytes that it took to serialize
the structure. The .buffer contains the serialized content. The user is responsible for
freeing the .buffer.
Example
27
CHAPTER 3. API REFERENCE asn1c-0.9.29
asn_encode_to_new_buffer_result_t res;
res = asn_encode_to_new_buffer(0, ATS_DER, &asn_DEF_Rectangle, rect);
if(res.buffer) {
/* Encoded successfully. */
free(res.buffer);
} else {
fprintf(stderr, ”Failed to encode %s, estimated %zd bytes\n”,
asn_DEF_Rectangle.name, res.result.encoded);
}
See also
asn_encode_to_buffer() at page 25.
28
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.8 asn_fprint()
Synopsis
Description
The asn_fprint() function prints human readable description of the target language’s
structure into the file stream specified by stream pointer.
The output format does not conform to any standard.
The asn_fprint() function attempts to produce a valid output even for incomplete
and broken structures, which makes it more suitable for debugging complex cases than
xer_fprint().
Return values
0 Output was successfully made
-1 Error printing out the structure
Example
Rectangle_t *rect = ...;
asn_fprint(stdout, &asn_DEF_Rectangle, rect);
See also
xer_fprint() at page 54.
29
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.9 asn_random_fill()
Synopsis
int asn_random_fill(
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
size_t approx_max_length_limit
);
Description
Create or initialize a structure with random contents, according to the type specification and
optional member constraints.
For best results the code should be generated without -no-gen-PER option to asn1c.
Making PER constraints code available in runtime will make asn_random_fill explore
the edges of PER-visible constraints and sometimes break out of extensible contstraints’
ranges.
The asn_random_fill() function has a bias to generate edge case values. This
property makes it useful for debugging the application level code and for security testing, as
random data can be a good seed to fuzzing.
The approx_max_length_limit specifies the approximate limit of the resulting
structure in units closely resembling bytes. The actual result might be several times larger
or smaller than the given length limit. A rule of thumb way to select the initial value for this
parameter is to take a typical structure and use twice its DER output size.
Return values
0 Structure was properly initialized with random data
-1 Failure to initialize the structure with random data
30
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.10 ber_decode()
Synopsis
asn_dec_rval_t ber_decode(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
);
Description
Decode BER, DER and CER data (Basic Encoding Rules, Distinguished Encoding Rules, Canon-
ical Encoding Rules), as defined by ITU-T X.690.
DER and CER are different subsets of BER.
Return values
Upon unsuccessful termination, the *struct_ptr_ptr may contain partially decoded
data. This data may be useful for debugging (such as by using asn_fprint()). Don’t
forget to discard the unused partially decoded data by calling ASN_STRUCT_FREE() or
ASN_STRUCT_RESET().
The function returns a compound structure:
typedef struct {
enum {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
} code; /* Result code */
size_t consumed; /* Number of bytes consumed */
} asn_dec_rval_t;
The .code member specifies the decoding outcome.
31
CHAPTER 3. API REFERENCE asn1c-0.9.29
Restartability
The ber_decode() function is restartable (stream-oriented). That means that in case the
buffer has less data than expected, the decoder will process whatever is available and ask for
more data to be provided using the RC_WMORE return .code.
Note that in the RC_WMORE case the decoder may have processed less data than it is
available in the buffer, which means that you must be able to arrange the next buffer to
contain the unprocessed part of the previous buffer.
See also
der_encode() at page 33.
32
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.11 der_encode
Synopsis
asn_enc_rval_t der_encode(
const asn_TYPE_descriptor_t *type_descriptor,
const void *structure_to_encode,
asn_app_consume_bytes_f *callback,
void *callback_key
Description
The der_encode() function serializes the given structure_to_encode using the
DER transfer syntax (a variant of BER, Basic Encoding Rules).
During serialization, a user-specified callback is invoked zero or more times with bytes
of data to add to the output stream (if any), and the callback_key. The signature for the
callback is as follows:
typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t
size, void *callback_key);
Consider using a more generic function asn_encode(ATS_DER).
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
The serialized output size is returned in bytes.
33
CHAPTER 3. API REFERENCE asn1c-0.9.29
Example
static int
save_to_file(const void *data, size_t size, void *key) {
FILE *fp = key;
return (fwrite(data, 1, size, fp) == size) ? 0 : ି1;
}
See also
ber_decode() at page 31, asn_decode(ATS_BER) at page 20.
34
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.12 der_encode_to_buffer()
Synopsis
asn_enc_rval_t der_encode_to_buffer(
const asn_TYPE_descriptor_t *type_descriptor,
const void *structure_to_encode,
void *buffer, size_t buffer_size);
Description
The der_encode_to_buffer() function serializes the given structure_to_encode
using the DER transfer syntax (a variant of BER, Basic Encoding Rules).
The function places the serialized data into the given buffer of size buffer_size.
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
The serialized output size is returned in bytes.
The .encoded never exceeds the available buffer size.1 If the buffer_size is not
sufficient, the .encoded will be set to -1 and encoding would fail.
Example
1
This behavior is different from asn_encode_to_buffer().
35
CHAPTER 3. API REFERENCE asn1c-0.9.29
See also
ber_decode() at page 31, asn_decode(ATS_BER) at page 20, asn_encode_to_buffer(ATS_
at page 25.
36
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.13 oer_decode()
Synopsis
asn_dec_rval_t oer_decode(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of that buffer */
);
Description
Decode the BASIC-OER and CANONICAL-OER (Octet Encoding Rules), as defined by ITU-T X.696.
Return values
Upon unsuccessful termination, the *struct_ptr_ptr may contain partially decoded
data. This data may be useful for debugging (such as by using asn_fprint()). Don’t
forget to discard the unused partially decoded data by calling ASN_STRUCT_FREE() or
ASN_STRUCT_RESET().
The function returns a compound structure:
typedef struct {
enum {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
} code; /* Result code */
size_t consumed; /* Number of bytes consumed */
} asn_dec_rval_t;
The .code member specifies the decoding outcome.
RC_OK Decoded successfully and completely
RC_WMORE More data expected, call again
RC_FAIL Failed for good
37
CHAPTER 3. API REFERENCE asn1c-0.9.29
The .consumed member specifies the amount of buffer data that was used during pars-
ing, irrespectively of the .code.
The .consumed value is in bytes.
Restartability
The oer_decode() function is restartable (stream-oriented). That means that in case the
buffer has less data than expected, the decoder will process whatever is available and ask for
more data to be provided using the RC_WMORE return .code.
Note that in the RC_WMORE case the decoder may have processed less data than it is
available in the buffer, which means that you must be able to arrange the next buffer to
contain the unprocessed part of the previous buffer.
38
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.14 oer_encode()
Synopsis
asn_enc_rval_t oer_encode(
const asn_TYPE_descriptor_t *type_descriptor,
const void *structure_to_encode,
asn_app_consume_bytes_f *callback,
void *callback_key);
Description
The oer_encode() function serializes the given structure_to_encode using the
CANONICAL-OER transfer syntax (Octet Encoding Rules, ITU-T X.691).
During serialization, a user-specified callback is invoked zero or more times with bytes
of data to add to the output stream (if any), and the callback_key. The signature for the
callback is as follows:
typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t
size, void *callback_key);
Consider using a more generic function asn_encode(ATS_CANONICAL_OER).
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
The serialized output size is returned in bytes.
39
CHAPTER 3. API REFERENCE asn1c-0.9.29
Example
static int
save_to_file(const void *data, size_t size, void *key) {
FILE *fp = key;
return (fwrite(data, 1, size, fp) == size) ? 0 : ି1;
}
See also
asn_encode(ATS_CANONICAL_OER) at page 23.
40
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.15 oer_encode_to_buffer()
Synopsis
asn_enc_rval_t oer_encode_to_buffer(
const asn_TYPE_descriptor_t *type_descriptor,
const asn_oer_constraints_t *constraints,
const void *structure_to_encode,
void *buffer, size_t buffer_size);
Description
The oer_encode_to_buffer() function serializes the given structure_to_encode
using the CANONICAL-OER transfer syntax (Octet Encoding Rules, ITU-T X.691).
The function places the serialized data into the given buffer of size buffer_size.
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
The serialized output size is returned in bytes.
The .encoded never exceeds the available buffer size.1 If the buffer_size is not
sufficient, the .encoded will be set to -1 and encoding would fail.
1
This behavior is different from asn_encode_to_buffer().
41
CHAPTER 3. API REFERENCE asn1c-0.9.29
Example
Rectangle_t *rect = ...;
uint8_t buffer[128];
asn_enc_rval_t er;
er = oer_encode_to_buffer(&asn_DEF_Rectangle, 0, rect, buffer, sizeof(buffer));
if(er.encoded == ି1) {
fprintf(stderr, ”Serialization of %s failed.\n”, asn_DEF_Rectangle.name);
}
See also
ber_decode() at page 31, asn_decode(ATS_BER) at page 20, asn_encode_to_buffer(ATS_
at page 25.
42
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.16 uper_decode()
Synopsis
asn_dec_rval_t uper_decode(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
const void *buffer, /* Data to be decoded */
size_t size, /* Size of the input data buffer, bytes */
int skip_bits, /* Number of unused leading bits, 0..7 */
int unused_bits /* Number of unused tailing bits, 0..7 */
);
Description
Decode the Unaligned BASIC or CANONICAL PER (Packed Encoding Rules), as defined by ITU-
T X.691.
Return values
Upon unsuccessful termination, the *struct_ptr_ptr may contain partially decoded
data. This data may be useful for debugging (such as by using asn_fprint()). Don’t
forget to discard the unused partially decoded data by calling ASN_STRUCT_FREE() or
ASN_STRUCT_RESET().
The function returns a compound structure:
typedef struct {
enum {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
} code; /* Result code */
size_t consumed; /* Number of bytes consumed */
} asn_dec_rval_t;
The .code member specifies the decoding outcome.
43
CHAPTER 3. API REFERENCE asn1c-0.9.29
Restartability
The uper_decode() function is not restartable. Failures are final.
44
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.17 uper_decode_complete()
Synopsis
asn_dec_rval_t uper_decode_complete(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of data buffer */
);
Description
Decode a “Production of a complete encoding”, according to ITU-T X.691 (08/2015) #11.1.
Return values
Upon unsuccessful termination, the *struct_ptr_ptr may contain partially decoded
data. This data may be useful for debugging (such as by using asn_fprint()). Don’t
forget to discard the unused partially decoded data by calling ASN_STRUCT_FREE() or
ASN_STRUCT_RESET().
The function returns a compound structure:
typedef struct {
enum {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
} code; /* Result code */
size_t consumed; /* Number of bytes consumed */
} asn_dec_rval_t;
The .code member specifies the decoding outcome.
RC_OK Decoded successfully and completely
RC_WMORE More data expected, call again
RC_FAIL Failed for good
45
CHAPTER 3. API REFERENCE asn1c-0.9.29
The .consumed member specifies the amount of buffer data that was used during pars-
ing, irrespectively of the .code.
The the .consumed value is returned in whole bytes (NB).
Restartability
The uper_decode_complete() function is not restartable. Failures are final.
The complete encoding contains at least one byte, so on success .consumed will be
greater or equal to 1.
46
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.18 uper_encode()
47
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.19 uper_encode_to_buffer()
48
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.20 uper_encode_to_new_buffer()
49
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.21 xer_decode()
Synopsis
asn_dec_rval_t xer_decode(
const asn_codec_ctx_t *opt_codec_ctx,
const asn_TYPE_descriptor_t *type_descriptor,
void **struct_ptr_ptr,/* Pointer to a target structure’s ptr */
const void *buffer, /* Data to be decoded */
size_t size /* Size of data buffer */
);
Description
Decode the BASIC-XER and CANONICAL-XER (XML Encoding Rules) encoding, as defined by
ITU-T X.693.
Return values
Upon unsuccessful termination, the *struct_ptr_ptr may contain partially decoded
data. This data may be useful for debugging (such as by using asn_fprint()). Don’t
forget to discard the unused partially decoded data by calling ASN_STRUCT_FREE() or
ASN_STRUCT_RESET().
The function returns a compound structure:
typedef struct {
enum {
RC_OK, /* Decoded successfully */
RC_WMORE, /* More data expected, call again */
RC_FAIL /* Failure to decode data */
} code; /* Result code */
size_t consumed; /* Number of bytes consumed */
} asn_dec_rval_t;
The .code member specifies the decoding outcome.
RC_OK Decoded successfully and completely
RC_WMORE More data expected, call again
RC_FAIL Failed for good
50
CHAPTER 3. API REFERENCE asn1c-0.9.29
The .consumed member specifies the amount of buffer data that was used during pars-
ing, irrespectively of the .code.
The .consumed value is in bytes.
Restartability
The xer_decode() function is restartable (stream-oriented). That means that in case the
buffer has less data than expected, the decoder will process whatever is available and ask for
more data to be provided using the RC_WMORE return .code.
Note that in the RC_WMORE case the decoder may have processed less data than it is
available in the buffer, which means that you must be able to arrange the next buffer to
contain the unprocessed part of the previous buffer.
51
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.22 xer_encode()
Synopsis
enum xer_encoder_flags_e {
/* Mode of encoding */
XER_F_BASIC = 0x01, /* BASICିXER (prettyିprinting) */
XER_F_CANONICAL = 0x02 /* Canonical XER (strict rules) */
};
asn_enc_rval_t xer_encode(
const asn_TYPE_descriptor_t *type_descriptor,
const void *structure_to_encode,
enum xer_encoder_flags_e xer_flags,
asn_app_consume_bytes_f *callback,
void *callback_key);
Description
The xer_encode() function serializes the given structure_to_encode using the
BASIC-XER or CANONICAL-XER transfer syntax (XML Encoding Rules, ITU-T X.693).
During serialization, a user-specified callback is invoked zero or more times with bytes
of data to add to the output stream (if any), and the callback_key. The signature for the
callback is as follows:
typedef int(asn_app_consume_bytes_f)(const void *buffer, size_t
size, void *callback_key);
Consider using a more generic function asn_encode() with ATS_BASIC_XER or ATS_CANONICAL_XER
transfer syntax option.
Return values
The function returns a compound structure:
typedef struct {
ssize_t encoded;
const asn_TYPE_descriptor_t *failed_type;
const void *structure_ptr;
} asn_enc_rval_t;
52
CHAPTER 3. API REFERENCE asn1c-0.9.29
In case of unsuccessful encoding, the .encoded member is set to -1 and the other members
of the compound structure point to where the encoding has failed to proceed further.
In case encoding is successful, the .encoded member specifies the size of the serialized
output.
The serialized output size is returned in bytes.
Example
static int
save_to_file(const void *data, size_t size, void *key) {
FILE *fp = key;
return (fwrite(data, 1, size, fp) == size) ? 0 : ି1;
}
See also
xer_fprint() at page 54.
53
CHAPTER 3. API REFERENCE asn1c-0.9.29
3.23 xer_fprint()
Synopsis
Description
The xer_fprint() function outputs XML-based serialization of the given structure into
the file stream specified by stream pointer.
The output conforms to a BASIC-XER transfer syntax, as defined by ITU-T X.693.
Return values
0 XML output was successfully made
-1 Error printing out the structure
Since the xer_fprint() function attempts to produce a conforming output, it will likely
break on partial structures by writing incomplete data to the output stream and returning -1.
This makes it less suitable for debugging complex cases than asn_fprint().
Example
Rectangle_t *rect = ...;
xer_fprint(stdout, &asn_DEF_Rectangle, rect);
See also
asn_fprint() at page 29.
54
Chapter 4
Let’s start with including the necessary header files into your application. Normally it is
enough to include the header file of the main PDU type. For our Rectangle module, including
the Rectangle.h file is sufficient:
#include <Rectangle.h>
The header files defines a C structure corresponding to the ASN.1 definition of a rectangle and
the declaration of the ASN.1 type descriptor. A type descriptor is a special globally accessible
object which is used as an argument to most of the API functions provided by the ASN.1
codec. A type descriptor starts with asn_DEF_…. For example, here is the code which frees
the Rectangle_t structure:
Rectangle_t *rect = ...;
ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
This code defines a rect pointer which points to the Rectangle_t structure which needs to
be freed. The second line uses a generic ASN_STRUCT_FREE() macro which invokes
the memory deallocation routine created specifically for this Rectangle_t structure. The
asn_DEF_Rectangle is the type descriptor which holds a collection of routines and operations
defined for the Rectangle_t structure.
55
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
The asn1c runtime supplies (see asn_application.h) two sets of high level functions, asn_encode*
and asn_decode*, which take a transfer syntax selector as an argument. The transfer syn-
tax selector is defined as this:
/*
* A selection of ASN.1 Transfer Syntaxes to use with generalized encoders and decoders.
*/
enum asn_transfer_syntax {
ATS_INVALID,
ATS_NONSTANDARD_PLAINTEXT,
ATS_BER,
ATS_DER,
ATS_CER,
ATS_BASIC_OER,
ATS_CANONICAL_OER,
ATS_UNALIGNED_BASIC_PER,
ATS_UNALIGNED_CANONICAL_PER,
ATS_BASIC_XER,
ATS_CANONICAL_XER,
};
Using this encoding selector, encoding and decoding becomes very generic:
Encoding:
uint8_t buffer[128];
size_t buf_size = sizeof(buffer);
asn_enc_rval_t er;
Decoding:
ᇦᇧᇧᇧᇧᇧᇧᇨ
Rectangle_t *rect = 0; /* Note this 01 ! */
56
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
capable of decoding the data encoded by the CER and DER encoders. The opposite is not
true.
The ASN.1 compiler provides the generic BER decoder which is capable of decoding BER, CER
and DER encoded data.
The decoder is restartable (stream-oriented). That means that in case the buffer has less
data than expected, the decoder will process whatever is available and ask for more data to
be provided using the RC_WMORE return .code.
Note that in the RC_WMORE case the decoder may have processed less data than it is
available in the buffer, which means that you must be able to arrange the next buffer to
contain the unprocessed part of the previous buffer.
Suppose, you have two buffers of encoded data: 100 bytes and 200 bytes.
• You can concatenate these buffers and feed the BER decoder with 300 bytes of data, or
• You can feed it the first buffer of 100 bytes of data, realize that the ber_decoder con-
sumed only 95 bytes from it and later feed the decoder with 205 bytes buffer which
consists of 5 unprocessed bytes from the first buffer and the additional 200 bytes from
the second buffer.
This is not as convenient as it could be (the BER encoder could consume the whole 100 bytes
and keep these 5 bytes in some temporary storage), but in case of existing stream based
processing it might actually fit well into existing algorithm. Suggestions are welcome.
Here is the example of BER decoding of a simple structure:
Rectangle_t *
simple_deserializer(const void *buffer, size_t buf_size) {
asn_dec_rval_t rval;
ᇦᇧᇧᇧᇧᇧᇧᇨ
Rectangle_t *rect = 0; /* Note this 01 ! */
rval = asn_DEF_Rectangle.op->ber_decoder(0,
&asn_DEF_Rectangle,
ᇦᇧᇧᇧᇨ,
(void **)&rect /* Decoder changes the pointer */
buffer, buf_size, 0);
if(rval.code == RC_OK) {
return rect; /* Decoding succeeded */
} else {
1
Forgetting to properly initialize the pointer to a destination structure is a major source of support requests.
57
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
• RC_WMORE: There is more data expected than it is provided (stream mode continuation
feature);
Together with the return code (.code) the asn_dec_rval_t type contains the number of bytes
which is consumed from the buffer. In the previous hypothetical example of two buffers (of
100 and 200 bytes), the first call to ber_decode() would return with .code = RC_WMORE and
.consumed = 95. The .consumed field of the BER decoder return value is always valid, even if
the decoder succeeds or fails with any other return code.
Look into ber_decoder.h for the precise definition of ber_decode() and related types.
58
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
59
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
Look into der_encoder.h for the precise definition of der_encode() and related types.
er = xer_encode(&asn_DEF_Rectangle, rect,
XER_F_BASIC, /* BASICିXER or CANONICALିXER */
write_stream, ostream);
60
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
if(rval.code == RC_OK) {
return rect; /* Decoding succeeded */
} else {
/* Free partially decoded rect */
ASN_STRUCT_FREE(asn_DEF_Rectangle, rect);
return 0;
}
}
The decoder takes both BASIC-XER and CANONICAL-XER encodings.
The decoder shares its data consumption properties with BER decoder; please read the
section 4.2 on page 56 to know more.
Look into xer_decoder.h for the precise definition of xer_decode() and related types.
61
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
The asn_check_constraints() function checks the type for various implicit and
explicit constraints. It is recommended to use the asn_check_constraints() function
after each decoding and before each encoding.
62
CHAPTER 4. API USAGE EXAMPLES asn1c-0.9.29
63
Chapter 5
This chapter defines some basic ASN.1 concepts and describes several most widely used types. It is
by no means an authoritative or complete reference. For more complete ASN.1 description, please
refer to Olivier Dubuisson’s book [Dub00] or the ASN.1 body of standards itself [ITU-T/ASN.1].
The Abstract Syntax Notation One is used to formally describe the data transmitted across
the network. Two communicating parties may employ different formats of their native data
types (e. g., different number of bits for the native integer type), thus it is important to have
a way to describe the data in a manner which is independent from the particular machine’s
representation. The ASN.1 specifications are used to achieve the following:
• The specification expressed in the ASN.1 notation is a formal and precise way to com-
municate the structure of data to human readers;
• The ASN.1 specifications may be used as input for automatic compilers which produce
the code for some target language (C, C++, Java, etc) to encode and decode the data
according to some encoding formats. Several such encoding formats (called Transfer
Encoding Rules) have been defined by the ASN.1 standard.
64
CHAPTER 5. ABSTRACT SYNTAX NOTATION: ASN.1 asn1c-0.9.29
to send or receive the encoded data is outside the scope of ASN.1. For example, this data
structure may be encoded according to some encoding rules and sent to the destination
using the TCP protocol. The ASN.1 specifies several ways of encoding (or “serializing”, or
“marshaling”) the data: BER, PER, XER and others, including CER and DER derivatives from
BER.
The complete specification must be wrapped in a module, which looks like this:
RectangleModule1
{ iso org(3) dod(6) internet(1) private(4)
enterprise(1) spelio(9363) software(1)
asn1c(5) docs(2) rectangle(1) 1 }
DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
END
The module header consists of module name (RectangleModule1), the module object identi-
fier ({...}), a keyword “DEFINITIONS”, a set of module flags (AUTOMATIC TAGS) and “::= BEGIN”.
The module ends with an “END” statement.
65
CHAPTER 5. ABSTRACT SYNTAX NOTATION: ASN.1 asn1c-0.9.29
ିି Integer, negative
NegativeInt ::= INTEGER (MIN..0)
66
CHAPTER 5. ABSTRACT SYNTAX NOTATION: ASN.1 asn1c-0.9.29
For example, the very first ASN.1 module in this Chapter (RectangleModule1) has the
following OBJECT IDENTIFIER: 1 3 6 1 4 1 9363 1 5 2 1 1.
ExampleOID ::= OBJECT IDENTIFIER
rectangleModule1ିoid ExampleOID
::= { 1 3 6 1 4 1 9363 1 5 2 1 1 }
67
CHAPTER 5. ABSTRACT SYNTAX NOTATION: ASN.1 asn1c-0.9.29
68
CHAPTER 5. ABSTRACT SYNTAX NOTATION: ASN.1 asn1c-0.9.29
ିି Example 2
ManyRectangles ::= SEQUENCE OF Rectangle
69
CHAPTER 5. ABSTRACT SYNTAX NOTATION: ASN.1 asn1c-0.9.29
70
Bibliography
71