TOP

ASN.1/C Runtime API Overview

Applies to: ASN.1/C 11.0

Introduction

The OSS Encoder/Decoder API, also known as the OSS Runtime API, is a collection of functions that you can call to encode, decode, and perform auxiliary operations on application messages or Protocol Data Units (PDUs).

The ASN.1/C Runtime API enables you to:

  • Encode and decode using the following encoding rules:
    • Basic Encoding Rules (BER)
    • Packed Encoding Rules (Aligned Basic-PER: PER, Unaligned Basic-PER: UPER, Aligned Canonical-PER: CPER, Unaligned Canonical-PER: CUPER)
    • Distinguished Encoding Rules (DER)
    • Canonical Encoding Rules (CER)
    • XML Encoding Rules (Basic: XER, Canonical: CXER, Extended: E-XER)
    • Octet Encoding Rules (Basic: OER, Canonical: COER)
    • JavaScript Object Notation Encoding Rules (JSON).
  • Check an unencoded PDU to see if the schema constraints are satisfied.
  • Print PDUs in encoded and unencoded/decoded forms.
  • Copy PDUs to different destinations.
  • Compare unencoded or decoded PDUs.
  • Free encoder/decoder output memory.

Encoder/Decoder Types

The encoder transforms data stored in C structures into encoded data.

The decoder, on the other hand, transforms encodings into C data structures. The encoder/decoder relies on the C code generated by the OSS ASN.1 compiler.

NOTE: Starting with version 9.0, by default, the OSS ASN.1 compiler generates TOED files instead of SOED files.

OSS Nokalva provides three types of encoders/decoders:

Time-Optimized Encoder/Decoder (TOED)
Optimized to minimize CPU utilization. This is the default encoder/decoder for the OSS ASN.1/C Tools.
Space-Optimized Encoder/Decoder (SOED)
Optimized to minimize the use of memory. The API for the first two types of encoders/decoders is identical.
Lean Encoder/Decoder (LED)
Optimized for embedded systems with limited available memory running applications which require fast processing time. The speed is comparable to that of TOED and the memory usage is smaller than that of SOED. LED is provided separately.

You can switch between the first two encoders/decoders without modifying your application program. To switch, specify the -soed or -toed option and re-compile your ASN.1 schema. Then rebuild your application by linking to the corresponding encoder/decoder runtime library.

In case the size of your schema is small or medium, the code generated by TOED is smaller, thus is executed faster than the code generated by SOED. Unless you need the externalized memory manager that the SOED uses, we recommend that you use TOED.

If the size of your schema is large or complex, note that SOED requires less memory than TOED.

Linking Options

To use the API functions, link your application with the OSS API libraries.

There are two types of libraries provided:

  • Static
  • Dynamic

Additionally, each type has three basic variants according to the type of encoder/decoder used:

  • Space-Optimized library
  • Time-Optimized library
  • Lean library

Until you become more familiar with the OSS API, we recommend that you use the Space-Optimized library.

The following table contains filenames associated with the libraries mentioned above, available for Microsoft Windows platforms:

Encoder/Decoder type Dynamic library (DLL) Static library Notes
Space-Optimized
ossapi.lib
soeddefa.lib
soeddemd.lib
*md.lib is a static encoder/decoder library linked with the dynamic C-runtime (built using /MD C compiler option).
Time-Optimized
ossapit.lib
toedcode.lib
toedcomd.lib
Lean
ossapil.lib
asn1lean.lib
asn1lemd.lib
asn1dlean.lib
asn1dlemd.lib
asn1d*.lib include tracing capabilities useful during debugging.

To avoid having multiple incompatible copies of runtime code in memory, make sure you are consistent in the way you are using your C/C++ compiler options. For example, if you compile your DLLs or executables to link statically with the C runtime libraries (/MT for Microsoft VC++), use the static OSS library soeddefa.lib (also compiled with /MT).

Similarly, if you compile your code to link dynamically with the C runtime libraries (/MD for Microsoft VC++), either use ossapi.lib or soeddemd.lib (the latter is built using /MD option for C runtime libraries).

OSS encoder/decoder DLLs are located in the bin/ directory of the OSS ASN.1/C Tools. Make sure these libraries are available at run time. For example, include the bin/ directory in the environment path of the operating system or move these DLLs to another location in your environment path.

Using the API

This is a typical OSS API function prototype:

returnType ossFunctionName(OssGlobal *world, ...);

All OSS API functions begin with the oss prefix. Most functions take a pointer to an instance of the structure OssGlobal as their first argument. This structure contains information about the OSS runtime environment that must be retained from an OSS API function to the next. For example:

OssGlobal world;
ossinit(&world, controlHeader);
ossPrint(&world, "Hello world.\n");
ossterm(&worldn);

controlHeader is the extern void* pointer declared at the end of the ASN.1 compiler-generated header file. This pointer is set to reference the SOED control table or the TOED code file entry points.

Your application must call the terminating function ossterm() to end the session.

NOTE: If you need multiple schemas for your application, a separate instance of the OssGlobal structure must be allocated and initialized for each control table (SOED) or each code file (TOED) generated for each schema by the ASN.1 compiler.

Using Multiple Threads

OSS API functions are re-entrant and thread-safe. However, you must ensure that, when using the OSS API functions in multiple simultaneous threads, you either serialize access to the OssGlobal structure or keep a separate copy of OssGlobal in each thread. If you choose to keep a separate copy of the OssGlobal structure in each thread, call ossinit() and ossterm() from within each thread.

NOTE: Unless you are using the Windows platform, you must not specify the OSS_TRAPPING flag to achieve thread-safety. For more information, see ossSetFlags().

To create a duplicate copy of the OssGlobal structure in each thread, instead of using ossinit(), you can call ossDupWorld(). Compared to ossinit(), the latter has a lower overhead. To free OssGlobal in each thread, call ossterm().

NOTE: If you are using the static OSS libraries (soeddefa.lib) on Windows, to achieve thread-safety, call ossInitSync() or ossTermSync(), before and after you use the OSS API.

Runtime Restrictions

The encoder/decoder has the following implementation details and limitations:

Time-Optimized Encoder/Decoder (TOED)

  • Minimal constraint checking.
  • Limited trace capabilities. To instruct the TOED to construct error messages accessible via ossGetErrMsg(), set the DOSSDEBUG=2 C compiler flag.
  • To use information object handling functions (ossAddInfoObject(), ossGetInfoObject(), ossGetInfoObjectSet(), ossRemoveInfoObject()), ASN.1-compile your input specification with -autoEncDec and -toed. To make these functions available at runtime, C-compile the produced code file with -DOSS_INFOOBJ_API being defined.
  • To automatically encode/decode open types, see the following procedure:
    1. ASN.1-compile your input specification with -autoEncDec and -toed specified.
    2. Set the AUTOMATIC_ENCDEC flag during runtime (via ossSetFlags()).
    Currently, in the TOED implementation of automatic encoding/decoding of open types, a SET OF or SEQUENCE OF type cannot be referenced by a component relation constraint that is used to determine the base type of the open type.
  • The encoder supports only the DEFINITE length form of BER encodings. However, the Time-Optimized decoder supports all valid BER encodings including those that are in the INDEFINITE form.
  • Certain forms of invalid encodings are silently ignored by the decoder. However, the encoder will encode (or re-encode) such values (upon request) in a format that conforms to the official encoding rules standard.
  • TOED does not check PATTERN constraints.
  • In the case of a BIT STRING with a named bit list represented in POINTER-ed VARYING form, the TOED PER decoder allocates the number of bytes the value consists of for the decoded value, and not the number of bytes that the value type occupies.
  • The encoder does not support the Canonical Encoding Rules (CER). However, the decoder supports decoding of a CER encoding because CER is a valid subset of BER.
  • TOED does not support user defined constraints (CONSTRAINED BY). Also, it does not support PER Encoding Analyzer functions: ossPrintPER() or ossPrintXPER(). They are compatible only with the SOED libraries.

Read-only function pointers TOED (RTOED)

  • The Memory Handle API is not supported.
  • Custom malloc()/free() functions can be specified only at linking time, not at run time.
  • The ossSetUserPrint(), ossGetUserPrint(), and ossPrintPDUToBuffer() API functions are not supported.
  • A runtime DLL or shared library is not available for RTOED, but you can create a shared library or DLL using the .sa (for UNIX platforms) or /MD (for Windows platforms) library.

Space-Optimized Encoder/Decoder (SOED)

  • When you use the SOED Encoder/Decoder, partial decoding is not supported. The partial decoding feature is supported only for the Time Optimized Encoder/Decoder (TOED).

Lean Encoder/Decoder (LED)

  • The LED has no support for:
  • The Lean encoder does not support the Canonical Encoding Rules (CER). However, the Lean decoder supports decoding of a CER encoding, since CER is a valid subset of BER.
  • The Lean encoder supports the DEFINITE length form of BER encodings. The Lean decoder supports all valid BER encodings including those that are in the INDEFINITE form.
  • The LED runtime library ignores the OSS_TRAPPING/NOTRAPPING runtime flags.
  • The Lean Encoder/Decoder does not support partial decoding. The partial decoding feature is supported only for the Time Optimized encoder/decoder (TOED).

DEFAULT Values in PER/BER

The rules of PER state that a value which takes the default value must be omitted from the encoding. That is, for

abc INTEGER DEFAULT 5

if abc is set to 6, the BASIC-PER encoder should encode it, but if it is set to 5, the encoder should mark it absent. Since such checking to see whether the value is set to the default value hinders performance, OSS chooses to enable it only when the STRICT_PER_ENCODING_OF_DEFAULT_VALUES runtime flag is set (see ossSetEncodingFlags()) and the OSS_STRICT_PER_ENCODING_OF_DEFAULT_VALUES macro is used at C compile time.

Without an explicit setting of the STRICT_PER_ENCODING_OF_DEFAULT_VALUES runtime flag and the DOSS_STRICT_PER_ENCODING_OF_DEFAULT_VALUES compiler option, the encoder will encode default values whenever the present bit is set, for example, for abc as defined above, the compiler generates

unsigned char   bit_mask;
#define  abc_present 0x80
int      abc;

If you set the abc_present bit in bit_mask, abc will be encoded; if you set abc_present to 0, abc will not be encoded.

The CANONICAL-PER encoder always skips the components marked DEFAULT if the value to be encoded is the default value.

If a DEFAULT field is marked present, the BER encoder always encodes its value.

DER Encoding SET OF Matching the DEFAULT Value

If the value for a SET OF type is the same as the specified DEFAULT value, the DER encoder will not recognize the match between the two values if the order of occurrence of the SET OF elements differs. For example, for a definition: some-field SET OF INTEGER DEFAULT {3, 2, 1}, if the value presented for encoding is {1, 2, 3}, theoretically, the encoder should not encode that value because it is the same as the default one. However, it encodes the value as if the two were not equal. This is done to simplify the comparison algorithm, thereby reducing its size and increasing its speed. In practice, this restriction does not pose a problem with X.509 or any other ASN.1 known DER specification, since they do not define such defaults.

UTC Time in DER

The encoder cannot determine whether a time is UTC (Coordinated Universal Time), therefore you must ensure that GeneralizedTime values are UTC time. Set the field utc in the GeneralizedTime structure to TRUE, which indicates a UTC time.

PER Encoder/Decoder (ALIGNED and UNALIGNED)

The OSS.OBJHANDLE | OSS.NOCOPY directive is not supported.

XER Encoding/Decoding

  • The DEBUGPDU, IGNORE_DEFER_DECODING, DONT_FREE_ENCODED, and IGNORE_PDU_TAG runtime flags are not supported.
  • Node values for the OBJECT IDENTIFIER type with an ENCODED representation and for the RELATIVE-OID type should not exceed the maximum 64-bit unsigned INTEGER (18446744073709551615). This applies to all encoder/decoder libraries (SOED/TOED/LED), CXER, and E-XER.
  • The OSS.OBJHANDLE | OSS.NOCOPY directive is supported for Any and Open types.

E-XER Encoding/Decoding

  • The OSS.OBJHANDLE | OSS.NOCOPY directive is not supported.
  • The OSS EXTENDED-XER runtime supports only certain C representations for the OER utility fields of the following encoding instructions.
E-XER instruction ASN.1 definition
ANY-ATTRIBUTES
SEQUENCE OF UTF8String
ANY-ELEMENT
UTF8String
EMBED-VALUES
SEQUENCE OF UTF8String
USE-ORDER
SEQUENCE OF ENUMERATED
USE-QNAME
pair of UTF8String fields

The representation of SEQUENCE OF must be in an UNBOUNDED or LINKED (the default for the ASN.1/C Compiler) or DLINKED-PLUS (the default for the -helperNames compiler option). UTF8String must be either null terminated (the default for SOED and TOED) or UNBOUNDED (the default for LEAN).

The decoder does not perform automatic decoding of types with component relation constraints that reference the following:

  • SEQUENCE OF fields of EMBED-VALUES or USE-ORDER encoding instructions.
  • Fields with ANY-ELEMENT or ANY-ATTRIBUTES encoding instructions.

When the control table is produced with the -noConstrain option, certain CHOICE types with the USE-UNION instruction may not be decoded correctly. This might occur when the constraint information is needed to identify the union alternative. See the following example:

C ::= [USE-UNION] CHOICE {
   t1 IA5String (FROM ("a".."z")),
   t2 INTEGER (1..MAX),
   t3 BOOLEAN }

The following instance:

<C>0</C> 

will be decoded as:

v C ::= t1 : "0"

instead of:

v C ::= t3 : FALSE

OER/COER Encoder/Decoder

When the OER/COER encoder/decoder is in use, the following ASN.1 compiler directives are not supported: ASN1.DeferDecoding, OSS.OBJHANDLE (OSS.NOCOPY).

ossPrintPDU() and NULL Characters

The ossPrintPDU() function does not support printing of character string values which have the NULL character embedded in the string value. This limitation applies only to ossPrintPDU(). The encoder and decoder correctly handle NULL characters embedded in character string values even when generating tracing output.

Encoding Compression

When the USE_COMPRESSION flag is set, the encoder/decoder library will ignore OSS.NOCOPY and ASN1.DeferDecoding. To use these directives with the compression function, you must explicitly call ossCompress() after ossEncode(), and ossUncompress() before ossDecode().

SOED with default memory manager and LED support compression. TOED does not support compression.

Constraint Checker

Encoder/decoder ignores single value or value range constraint violations for SET OF values for all encoding rules.

In the following example, value v is successfully encoded and decoded to avoid a potential performance hit that might occur during verification of such constraints:

Test DEFINITIONS ::= BEGIN
   Setof ::= SET ({1, 2}) OF INTEGER
   v Setof ::= {1}
END

This documentation applies to the OSS® ASN.1 Tools for C release 11.0 and later.

Copyright © 2020 OSS Nokalva, Inc. All rights reserved.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means electronic, mechanical, photocopying, recording or otherwise, without the prior permission of OSS Nokalva, Inc.
Every distributed copy of the OSS® ASN.1 Tools for C is associated with a specific license and related unique license number. That license determines, among other things, what functions of the OSS ASN.1 Tools for C are available to you.