Header documentation changes and other small fixes
[crypto.git] / lib / silcasn1 / silcasn1.h
index f9c4c46f79f61797892224758c82c2b30e0878a2..baef012d099d3066d917b8cb15b741650f9e0fa9 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2003 - 2005 Pekka Riikonen
+  Copyright (C) 2003 - 2008 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -23,6 +23,7 @@
  *
  * Efficient Abstract Syntax Notation One (ASN.1) implementation.  This
  * interface provides simple and efficient ASN.1 encoder and decoder.
+ *
  * The encoder directly encodes BER encoded data blocks from variable
  * argument list of ASN.1 types.  Multiple trees can be encoded at once
  * and multiple nodes can be encoded into the tree at once.  By default
  * pre-allocated SilcStack is used as memory.
  *
  * The encoding and decoding interface is simple.  silc_asn1_encode is used
- * encode and silc_asn1_decode to decode.  The actual ASN.1 is defined
+ * to encode and silc_asn1_decode to decode.  The actual ASN.1 is defined
  * as variable argument list to the function.  Various macros can be used
  * to encode and decode different ASN.1 types.  All types may also be used
  * to encode and decode with various options (such as implicit and explicit
  * tagging and defining specific class option).
  *
- * The implementation supports all the common ASN.1 types.  This
- * implementation does not support advanced ASN.1 features like macros.
+ * The implementation supports all the common ASN.1 types.
  *
  * References: ITU-T X.680 - X.693
  * http://www.itu.int/ITU-T/studygroups/com17/languages/
  *
+ * EXAMPLE
+ *
+ * silc_asn1_encode(asn1, buf,
+ *                  SILC_ASN1_SEQUENCE,
+ *                    SILC_ASN1_BOOLEAN(bool_val),
+ *                    SILC_ASN1_OCTET_STRING(string, string_len),
+ *                    SILC_ASN1_SEQUENCE_T(0, 2),
+ *                      SILC_ASN1_BOOLEAN_T(SILC_ASN1_EXPLICIT, 100, foo),
+ *                     SILC_ASN1_END,
+ *                     SILC_ASN1_OCTET_STRING_T(0, 1, string2, string2_len),
+ *                   SILC_ASN1_END, SILC_ASN1_END);
+ *
+ * Creates ASN.1 tree that looks something like:
+ *
+ * buf ::= SEQUENCE {
+ *   bool_val      BOOLEAN,
+ *   string        OCTET-STRING,
+ *            [2]  SEQUENCE {
+ *                   foo   [100] EXPLICIT BOOLEAN }
+ *   string2  [1]  OCTET-STRING }
+ *
  ***/
 
 #ifndef SILCASN1_H
 #define SILCASN1_H
 
-/****s* silcasn1/SilcASN1API/SilcAsn1
+/****s* silcasn1/SilcAsn1
  *
  * NAME
  *
@@ -69,7 +90,7 @@
  ***/
 typedef struct SilcAsn1Object *SilcAsn1;
 
-/****s* silcasn1/SilcASN1API/SilcAsn1Struct
+/****s* silcasn1/SilcAsn1Struct
  *
  * NAME
  *
@@ -85,7 +106,7 @@ typedef struct SilcAsn1Object *SilcAsn1;
  ***/
 typedef struct SilcAsn1Object SilcAsn1Struct;
 
-/****d* silcasn1/SilcASN1API/SilcAsn1Options
+/****d* silcasn1/SilcAsn1Options
  *
  * NAME
  *
@@ -102,13 +123,36 @@ typedef struct SilcAsn1Object SilcAsn1Struct;
  *    with SILC_ASN1_OPTS macro.  Other options can be given with various
  *    SILC_ASN1_*_T macros.
  *
+ * EXAMPLE
+ *
+ *    // Encodes boolean value with explicit tag and private class, and
+ *    // the result is allocated into `dest'.
+ *    silc_asn1_encode(asn1, &dest,
+ *                     SILC_ASN1_OPTS(SILC_ASN1_ALLOC),
+ *                     SILC_ASN1_BOOLEAN_T(SILC_ASN1_PRIVATE |
+ *                                         SILC_ASN1_EXPLICIT, 100, boolval),
+ *                     SILC_ASN1_END);
+ *
+ *    // Decode optional value, with SILC_ASN1_OPTIONAL the type must be
+ *    // a pointer so that NULL can be returned if the type is not present.
+ *    SilcBool *val;
+ *
+ *    silc_asn1_decode(asn1, src,
+ *                     SILC_ASN1_OPTS(SILC_ASN1_OPTIONAL),
+ *                     SILC_ASN1_BOOLEAN(&val),
+ *                     SILC_ASN1_END);
+ *
+ *    // If val == NULL, the optional value was not present
+ *    if (val == NULL)
+ *      error;
+ *
  * SOURCE
  */
 typedef enum {
   /* Default. If only this is set then defaults are implied. */
   SILC_ASN1_DEFAULT      = 0x0000,
 
-  /* Class options.  User does not need to set these unless specificly
+  /* Class options.  User does not need to set these unless specifically
      wanted to do so.  If SILC_ASN1_DEFAULT is set the SILC_ASN1_CONTEXT is
      implied if any of the tag options are set.  Otherwise SILC_ASN1_UNIVERSAL
      is implied. Only one of these can bet set at once. */
@@ -131,14 +175,17 @@ typedef enum {
 
   /* ASN.1 encoder/decoder options (bitmask).  These can be given
      only with SILC_ASN1_OPTS macro at the start of encoding/decoding. */
-  SILC_ASN1_ALLOC        = 0x0400,       /* Dynamically allocate results */
+  SILC_ASN1_ALLOC        = 0x0400,       /* Dynamically allocate results,
+                                           or if stack was given to
+                                           silc_asn1_alloc, they are allocated
+                                           and consumed from the stack. */
   SILC_ASN1_ACCUMUL      = 0x0800,       /* Accumulate memory for results,
                                            next call to silc_asn1_decode
                                            will not cancel old results. */
 } SilcAsn1Options;
 /***/
 
-/****d* silcasn1/SilcASN1API/SilcAsn1Tag
+/****d* silcasn1/SilcAsn1Tag
  *
  * NAME
  *
@@ -187,17 +234,18 @@ typedef enum {
 
 #include "silcasn1_i.h"
 
-/****f* silcasn1/SilcASN1API/silc_asn1_alloc
+/****f* silcasn1/silc_asn1_alloc
  *
  * SYNOPSIS
  *
- *    SilcAsn1 silc_asn1_alloc(void);
+ *    SilcAsn1 silc_asn1_alloc(SilcStack stack);
  *
  * DESCRIPTION
  *
  *    Allocates and initializes ASN.1 encoder/decoder and returns SilcAsn1
  *    context or NULL on error.  This context can be used with both
- *    silc_asn1_encode and silc_asn1_decode functions.
+ *    silc_asn1_encode and silc_asn1_decode functions.  If `stack' is non-NULL
+ *    all memory will be allocated from `stack'.
  *
  *    Usually SilcAsn1 is allocated when encoder or decoder is needed,
  *    however it is also possible to allocate long-lasting SilcAsn1 and
@@ -207,12 +255,14 @@ typedef enum {
  *
  *    When this context is freed with silc_asn1_free all memory will be
  *    freed, and all encoded ASN.1 buffers becomes invalid.  Also all
- *    data that is returned by silc_asn1_decode function becomes invalid.
+ *    data that is returned by silc_asn1_encode and silc_asn1_decode function
+ *    becomes invalid, unless SILC_ASN1_ALLOC flag is used, in which case the
+ *    memory is allocated from `stack' and the `stack' is consumed.
  *
  ***/
-SilcAsn1 silc_asn1_alloc(void);
+SilcAsn1 silc_asn1_alloc(SilcStack stack);
 
-/****f* silcasn1/SilcASN1API/silc_asn1_free
+/****f* silcasn1/silc_asn1_free
  *
  * SYNOPSIS
  *
@@ -227,11 +277,11 @@ SilcAsn1 silc_asn1_alloc(void);
  ***/
 void silc_asn1_free(SilcAsn1 asn1);
 
-/****f* silcasn1/SilcASN1API/silc_asn1_init
+/****f* silcasn1/silc_asn1_init
  *
  * SYNOPSIS
  *
- *    bool silc_asn1_init(SilcAsn1 asn1);
+ *    SilcBool silc_asn1_init(SilcAsn1 asn1, SilcStack stack);
  *
  * DESCRIPTION
  *
@@ -242,13 +292,13 @@ void silc_asn1_free(SilcAsn1 asn1);
  * EXAMPLE
  *
  *    SilcAsn1Struct asn1;
- *    if (!silc_asn1_init(&asn1))
+ *    if (!silc_asn1_init(&asn1, NULL))
  *      error;
  *
  ***/
-bool silc_asn1_init(SilcAsn1 asn1);
+SilcBool silc_asn1_init(SilcAsn1 asn1, SilcStack stack);
 
-/****f* silcasn1/SilcASN1API/silc_asn1_uninit
+/****f* silcasn1/silc_asn1_uninit
  *
  * SYNOPSIS
  *
@@ -262,11 +312,11 @@ bool silc_asn1_init(SilcAsn1 asn1);
  ***/
 void silc_asn1_uninit(SilcAsn1 asn1);
 
-/****f* silcasn1/SilcASN1API/silc_asn1_encode
+/****f* silcasn1/silc_asn1_encode
  *
  * SYNOPSIS
  *
- *    bool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
+ *    SilcBool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
  *
  * DESCRIPTION
  *
@@ -275,15 +325,16 @@ void silc_asn1_uninit(SilcAsn1 asn1);
  *    trees and nodes that are encoded into the `dest'.  By default, the
  *    memory for `dest' is allocated from the `asn1', and the buffer becomes
  *    invalid either by calling silc_asn1_free, silc_asn1_uninit, or when
- *    silc_asn1_encode is called for the next time.
+ *    silc_asn1_encode is called for the next time with `asn1' context.
  *
  *    If the SILC_ASN1_OPTS macro with SILC_ASN1_ALLOC option is given then
  *    the `dest' is dynamically allocated and caller must free it by itself.
- *    Alternatively if SILC_ASN1_ACCUMUL is given then memory is accumulated
- *    from `asn1' for `dest' and it is freed only when silc_asn1_free or
- *    silc_asn1_uninit is called.  Next call to silc_asn1_encode will not
- *    cancel the previous result, but will accumulate more memory for new
- *    result.
+ *    If the `stack' was given to silc_asn1_alloc, the SILC_ASN1_ALLOC will
+ *    allocate from that stack and consume the stack.  Alternatively if
+ *    SILC_ASN1_ACCUMUL is given then memory is accumulated from `asn1' for
+ *    `dest' and it is freed only when silc_asn1_free or silc_asn1_uninit
+ *    is called.  Next call to silc_asn1_encode will not cancel the previous
+ *    result, but will accumulate more memory for new result.
  *
  *    The variable argument list is constructed by using various
  *    macros, for example SILC_ASN1_SEQUENCE, etc.  The variable argument
@@ -313,13 +364,13 @@ void silc_asn1_uninit(SilcAsn1 asn1);
  *      string2  [1]  OCTET-STRING }
  *
  ***/
-bool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
+SilcBool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
 
-/****f* silcasn1/SilcASN1API/silc_asn1_decode
+/****f* silcasn1/silc_asn1_decode
  *
  * SYNOPSIS
  *
- *    bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
+ *    SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  *
  * DESCRIPTION
  *
@@ -341,13 +392,14 @@ bool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
  *
  *    If the SILC_ASN1_OPTS macro with SILC_ASN1_ALLOC option is given then
  *    all results are dynamically allocated and caller must free them by
- *    itself. Alternatively if SILC_ASN1_ACCUMUL is given then memory is
- *    accumulated from `asn1' for results and they are freed only when the
- *    silc_asn1_free or silc_asn1_uninit is called.  Next calls to the
- *    silc_asn1_decode will NOT invalidate the old results, but will
- *    accumulate more memory for new results.  If the SILC_ASN1_OPTS is not
- *    given at all then the default allocation method (decribed above)
- *    applies.
+ *    itself. If the `stack' was given to silc_asn1_alloc, the SILC_ASN1_ALLOC
+ *    will allocate from that stack and consume the stack.  Alternatively if
+ *    SILC_ASN1_ACCUMUL is given then memory is accumulated from `asn1' for
+ *    results and they are freed only when the silc_asn1_free or
+ *    silc_asn1_uninit is called.  Next calls to the silc_asn1_decode will
+ *    NOT invalidate the old results, but will accumulate more memory for new
+ *    results.  If the SILC_ASN1_OPTS is not given at all then the default
+ *    allocation method (decribed above) applies.
  *
  *    If caller needs to store the results even after `asn1' becomes invalid
  *    then call must either use SILC_ASN1_ALLOC option or duplicate the
@@ -355,7 +407,7 @@ bool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
  *
  * EXAMPLE
  *
- *    bool bool_val, foo;
+ *    SilcBool bool_val, foo;
  *    unsigned char *string, string2;
  *    SilcUInt32 string_len, string2_len;
  *
@@ -370,9 +422,9 @@ bool silc_asn1_encode(SilcAsn1 asn1, SilcBuffer dest, ...);
  *                     SILC_ASN1_END, SILC_ASN1_END);
  *
  ***/
-bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
+SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_OPTS
+/****f* silcasn1/SILC_ASN1_OPTS
  *
  * SYNOPSIS
  *
@@ -403,7 +455,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  ***/
 #define SILC_ASN1_OPTS(opts) SILC_ASN1_TAG_OPTS, (opts)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_ANY
+/****f* silcasn1/SILC_ASN1_ANY
  *
  * SYNOPSIS
  *
@@ -413,7 +465,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  *
  *    Decoding:
  *    SILC_ASN1_ANY(&buffer)
- *    SILC_ASN1_ANY_T(opts, tag, &buffer)
+ *    SILC_ASN1_ANY_T(opts, tag, buffer)
  *
  * DESCRIPTION
  *
@@ -443,7 +495,53 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_ANY(x) SILC_ASN1_U1(ANY, x)
 #define SILC_ASN1_ANY_T(o, t, x) SILC_ASN1_T1(ANY, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_SEQUENCE
+/****f* silcasn1/SILC_ASN1_ANY_PRIMITIVE
+ *
+ * SYNOPSIS
+ *
+ *    Encoding:
+ *    SILC_ASN1_ANY_PRIMITIVE(tag, buffer)
+ *    SILC_ASN1_ANY_PRIMITIVE_T(opts, tag, buffer)
+ *
+ *    Decoding:
+ *    SILC_ASN1_ANY_PRIMITIVE(tag, &buffer)
+ *    SILC_ASN1_ANY_PRIMITIVE_T(opts, tag, buffer)
+ *
+ * DESCRIPTION
+ *
+ *    Special macro used to encode pre-encoded primitive data blob.  The data
+ *    can be any primitive type that is already encoded in correct format.
+ *    The caller is responsible of making sure the data is formatted
+ *    correctly.  When decoding this returns the raw data blob and the caller
+ *    must know of what type and format it is.  The buffer type is SilcBuffer.
+ *
+ *    This macro can be used in cases when the data to be encoded is already
+ *    in encoded format, and it only needs to be added to ASN.1 tree.  The
+ *    SILC_ASN1_ANY cannot be used with primitives when tagging implicitly,
+ *    in these cases this macro can be used.
+ *
+ *    The `opts' is SilcAsn1Options.  The `tag' is a tag number.
+ *
+ * EXAMPLE
+ *
+ *    // Get MP integer in encoded format
+ *    mpbuf = mp_get_octet_string(mp);
+ *
+ *    // Encode the MP integer data to the tree
+ *    silc_asn1_encode(asn1, tree,
+ *                     SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_INTEGER, mpbuf),
+ *                     SILC_ASN1_END);
+ *
+ *    // Decode the MP integer data from the tree
+ *    silc_asn1_decode(asn1, tree,
+ *                     SILC_ASN1_ANY_PRIMITIVE(SILC_ASN1_TAG_INTEGER, &buffer),
+ *                     SILC_ASN1_END);
+ *
+ ***/
+#define SILC_ASN1_ANY_PRIMITIVE(t, x) SILC_ASN1_T1(ANY_PRIMITIVE, 0, t, x)
+#define SILC_ASN1_ANY_PRIMITIVE_T(o, t, x) SILC_ASN1_T1(ANY_PRIMITIVE, o, t, x)
+
+/****f* silcasn1/SILC_ASN1_SEQUENCE
  *
  * SYNOPSIS
  *
@@ -470,11 +568,17 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  *                       SILC_ASN1_BOOLEAN(boolval),
  *                     SILC_ASN1_END, SILC_ASN1_END);
  *
+ *    silc_asn1_encode(asn1, tree2,
+ *                     SILC_ASN1_SEQUENCE_T(SILC_ASN1_PRIVATE, 101),
+ *                       SILC_ASN1_ANY(node),
+ *                       SILC_ASN1_BOOLEAN(boolval),
+ *                     SILC_ASN1_END, SILC_ASN1_END);
+ *
  ***/
 #define SILC_ASN1_SEQUENCE SILC_ASN1_U0(SEQUENCE)
 #define SILC_ASN1_SEQUENCE_T(o, t) SILC_ASN1_T0(SEQUENCE, o, t)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_SET
+/****f* silcasn1/SILC_ASN1_SET
  *
  * SYNOPSIS
  *
@@ -504,7 +608,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_SET SILC_ASN1_U0(SET)
 #define SILC_ASN1_SET_T(o, t) SILC_ASN1_T0(SET, o, t)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_SEQUENCE_OF
+/****f* silcasn1/SILC_ASN1_SEQUENCE_OF
  *
  * SYNOPSIS
  *
@@ -538,7 +642,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  ***/
 #define SILC_ASN1_SEQUENCE_OF(x, c) SILC_ASN1_U2(SEQUENCE_OF, x, c)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_SET_OF
+/****f* silcasn1/SILC_ASN1_SET_OF
  *
  * SYNOPSIS
  *
@@ -569,49 +673,51 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  ***/
 #define SILC_ASN1_SET_OF(x, c) SILC_ASN1_U2(SEQUENCE_OF, x, c)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_CHOICE
+/****f* silcasn1/SILC_ASN1_CHOICE
  *
  * SYNOPSIS
  *
  *    Decoding:
- *    SILC_ASN1_CHOICE
+ *    SILC_ASN1_CHOICE(&chosen)
  *
  * DESCRIPTION
  *
  *    Macro used to specify choices in decoding.  The choice list must
  *    be terminated with SILC_ASN1_END.  There is no limit how many choices
- *    can be specified in the list.
+ *    can be specified in the list.  The `chosen' is SilcUInt32 and its
+ *    value tells which of the choice was found.  First choice in the list
+ *    has value 1, second value 2, and so on.
  *
  * EXAMPLE
  *
  *    // Decode timeval that is either UTC or generalized time
  *    silc_asn1_decode(asn1, tree,
  *                     SILC_ASN1_SEQUENCE,
- *                       SILC_ASN1_CHOICE,
+ *                       SILC_ASN1_CHOICE(&chosen),
  *                         SILC_ASN1_UTC_TIME(&timeval),
  *                         SILC_ASN1_GEN_TIME(&timeval),
  *                       SILC_ASN1_END,
  *                     SILC_ASN1_END, SILC_ASN1_END);
  *
  ***/
-#define SILC_ASN1_CHOICE SILC_ASN1_U0(CHOICE)
+#define SILC_ASN1_CHOICE(x) SILC_ASN1_U1(CHOICE, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_BOOLEAN
+/****f* silcasn1/SILC_ASN1_BOOLEAN
  *
  * SYNOPSIS
  *
  *    Encoding:
- *    SILC_ASN1_BOOLEAN(bool)
- *    SILC_ASN1_BOOLEAN_T(opts, tag, bool)
+ *    SILC_ASN1_BOOLEAN(boolval)
+ *    SILC_ASN1_BOOLEAN_T(opts, tag, boolval)
  *
  *    Decoding:
- *    SILC_ASN1_BOOLEAN(&bool)
- *    SILC_ASN1_BOOLEAN_T(opts, tag, &bool)
+ *    SILC_ASN1_BOOLEAN(&boolval)
+ *    SILC_ASN1_BOOLEAN_T(opts, tag, &boolval)
  *
  * DESCRIPTION
  *
- *    Macro used to encode or decode boolean value.  Type boolean type
- *    is bool.
+ *    Macro used to encode or decode boolean value.  The boolean type
+ *    is SilcBool.
  *
  *    The `opts' is SilcAsn1Options.  The `tag' is a tag number.
  *
@@ -619,7 +725,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_BOOLEAN(x) SILC_ASN1_U1(BOOLEAN, x)
 #define SILC_ASN1_BOOLEAN_T(o, t, x) SILC_ASN1_T1(BOOLEAN, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_INT
+/****f* silcasn1/SILC_ASN1_INT
  *
  * SYNOPSIS
  *
@@ -642,7 +748,30 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_INT(x) SILC_ASN1_U1(INTEGER, x)
 #define SILC_ASN1_INT_T(o, t, x) SILC_ASN1_T1(INTEGER, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_ENUM
+/****f* silcasn1/SILC_ASN1_SHORT_INT
+ *
+ * SYNOPSIS
+ *
+ *    Encoding:
+ *    SILC_ASN1_SHORT_INT(integer)
+ *    SILC_ASN1_SHORT_INT_T(opts, tag, integer)
+ *
+ *    Decoding:
+ *    SILC_ASN1_SHORT_INT(&integer)
+ *    SILC_ASN1_SHORT_INT_T(opts, tag, &integer);
+ *
+ * DESCRIPTION
+ *
+ *    Macro used to encode or decode short integer (32 bits).  The
+ *    integer type is SilcUInt32.
+ *
+ *    The `opts' is SilcAsn1Options.  The `tag' is a tag number.
+ *
+ ***/
+#define SILC_ASN1_SHORT_INT(x) SILC_ASN1_U1(SHORT_INTEGER, x)
+#define SILC_ASN1_SHORT_INT_T(o, t, x) SILC_ASN1_T1(SHORT_INTEGER, o, t, x)
+
+/****f* silcasn1/SILC_ASN1_ENUM
  *
  * SYNOPSIS
  *
@@ -665,7 +794,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_ENUM(x) SILC_ASN1_U1(ENUM, x)
 #define SILC_ASN1_ENUM_T(o, t, x) SILC_ASN1_T1(ENUM, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_BIT_STRING
+/****f* silcasn1/SILC_ASN1_BIT_STRING
  *
  * SYNOPSIS
  *
@@ -690,29 +819,33 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_BIT_STRING(x, xl) SILC_ASN1_U2(BIT_STRING, x, xl)
 #define SILC_ASN1_BIT_STRING_T(o, t, x, xl) SILC_ASN1_T2(BIT_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_NULL
+/****f* silcasn1/SILC_ASN1_NULL
  *
  * SYNOPSIS
  *
  *    Encoding:
  *    SILC_ASN1_NULL
- *    SILC_ASN1_NULL_T(opts, tag)
+ *    SILC_ASN1_NULL_T(opts, tag, set)
  *
  *    Decoding:
  *    SILC_ASN1_NULL
- *    SILC_ASN1_NULL_T(opts, tag)
+ *    SILC_ASN1_NULL_T(opts, tag, &set)
  *
  * DESCRIPTION
  *
  *    Macro used to encode or decode null value.
  *
- *    The `opts' is SilcAsn1Options.  The `tag' is a tag number.
+ *    The `opts' is SilcAsn1Options.  The `tag' is a tag number.  In encoding
+ *    `set' is SilcBool and if it is TRUE the NULL value will be encoded.  If
+ *    it is FALSE the SILC_ASN1_NULL will be ignored.  In decoding the `set'
+ *    is SilcBool and if it is TRUE the NULL value was present.  This can be
+ *    used to verify whether NULL was present if it is SILC_ASN1_OPTIONAL.
  *
  ***/
-#define SILC_ASN1_NULL SILC_ASN1_U0(NULL)
-#define SILC_ASN1_NULL_T(o, t) SILC_ASN1_T0(NULL, 0, t)
+#define SILC_ASN1_NULL(x) SILC_ASN1_U1(NULL, x)
+#define SILC_ASN1_NULL_T(o, t, x) SILC_ASN1_T1(NULL, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_OID
+/****f* silcasn1/SILC_ASN1_OID
  *
  * SYNOPSIS
  *
@@ -735,7 +868,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_OID(x) SILC_ASN1_U1(OID, x)
 #define SILC_ASN1_OID_T(o, t, x) SILC_ASN1_UT(OID, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_OCTET_STRING
+/****f* silcasn1/SILC_ASN1_OCTET_STRING
  *
  * SYNOPSIS
  *
@@ -750,21 +883,16 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  * DESCRIPTION
  *
  *    Macro used to encode or decode octet string.  The string type is
- *    unsigned char and string length SilcUInt32.
+ *    unsigned char and string length SilcUInt32.  Octet string is
+ *    considered to be 8-bit unsigned binary data.
  *
  *    The `opts' is SilcAsn1Options.  The `tag' is a tag number.
  *
- * NOTES
- *
- *    The string must be in UTF-8 encoding when encoding.  The decoded
- *    string will be in UTF-8 encoding.  The actual data is encoded to
- *    or decoded from 8-bit ASCII.
- *
  ***/
 #define SILC_ASN1_OCTET_STRING(x, xl) SILC_ASN1_U2(OCTET_STRING, x, xl)
 #define SILC_ASN1_OCTET_STRING_T(o, t, x, xl) SILC_ASN1_T2(OCTET_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_UTF8_STRING
+/****f* silcasn1/SILC_ASN1_UTF8_STRING
  *
  * SYNOPSIS
  *
@@ -793,7 +921,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_UTF8_STRING(x, xl) SILC_ASN1_U2(UTF8_STRING, x, xl)
 #define SILC_ASN1_UTF8_STRING_T(o, t, x, xl) SILC_ASN1_T2(UTF8_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_NUMERIC_STRING
+/****f* silcasn1/SILC_ASN1_NUMERIC_STRING
  *
  * SYNOPSIS
  *
@@ -822,7 +950,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_NUMERIC_STRING(x, xl) SILC_ASN1_U2(NUMERIC_STRING, x, xl)
 #define SILC_ASN1_NUMERIC_STRING_T(o, t, x, xl) SILC_ASN1_T2(NUMERIC_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_PRINTABLE_STRING
+/****f* silcasn1/SILC_ASN1_PRINTABLE_STRING
  *
  * SYNOPSIS
  *
@@ -851,7 +979,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_PRINTABLE_STRING(x, xl) SILC_ASN1_U2(PRINTABLE_STRING, x, xl)
 #define SILC_ASN1_PRINTABLE_STRING_T(o, t, x, xl) SILC_ASN1_T2(PRINTABLE_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_TELETEX_STRING
+/****f* silcasn1/SILC_ASN1_TELETEX_STRING
  *
  * SYNOPSIS
  *
@@ -880,7 +1008,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_TELETEX_STRING(x, xl) SILC_ASN1_U2(TELETEX_STRING, x, xl)
 #define SILC_ASN1_TELETEX_STRING_T(o, t, x, xl) SILC_ASN1_T2(TELETEX_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_IA5_STRING
+/****f* silcasn1/SILC_ASN1_IA5_STRING
  *
  * SYNOPSIS
  *
@@ -909,7 +1037,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_IA5_STRING(x, xl) SILC_ASN1_U2(IA5_STRING, x, xl)
 #define SILC_ASN1_IA5_STRING_T(o, t, x, xl) SILC_ASN1_T2(IA5_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_VISIBLE_STRING
+/****f* silcasn1/SILC_ASN1_VISIBLE_STRING
  *
  * SYNOPSIS
  *
@@ -938,7 +1066,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_VISIBLE_STRING(x, xl) SILC_ASN1_U2(VISIBLE_STRING, x, xl)
 #define SILC_ASN1_VISIBLE_STRING_T(o, t, x, xl) SILC_ASN1_T2(VISIBLE_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_UNIVERSAL_STRING
+/****f* silcasn1/SILC_ASN1_UNIVERSAL_STRING
  *
  * SYNOPSIS
  *
@@ -967,7 +1095,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_UNIVERSAL_STRING(x, xl) SILC_ASN1_U2(UNIVERSAL_STRING, x, xl)
 #define SILC_ASN1_UNIVERSAL_STRING_T(o, t, x, xl) SILC_ASN1_T2(UNIVERSAL_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_BMP_STRING
+/****f* silcasn1/SILC_ASN1_BMP_STRING
  *
  * SYNOPSIS
  *
@@ -996,7 +1124,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_BMP_STRING(x, xl) SILC_ASN1_U2(BMP_STRING, x, xl)
 #define SILC_ASN1_BMP_STRING_T(o, t, x, xl) SILC_ASN1_T2(BMP_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_UNRESTRICTED_STRING
+/****f* silcasn1/SILC_ASN1_UNRESTRICTED_STRING
  *
  * SYNOPSIS
  *
@@ -1025,7 +1153,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_UNRESTRICTED_STRING(x, xl) SILC_ASN1_U2(UNRESTRICTED_STRING, x, xl)
 #define SILC_ASN1_UNRESTRICTED_STRING_T(o, t, x, xl) SILC_ASN1_T2(UNRESTRICTED_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_GENERAL_STRING
+/****f* silcasn1/SILC_ASN1_GENERAL_STRING
  *
  * SYNOPSIS
  *
@@ -1054,7 +1182,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_GENERAL_STRING(x, xl) SILC_ASN1_U2(GENERAL_STRING, x, xl)
 #define SILC_ASN1_GENERAL_STRING_T(o, t, x, xl) SILC_ASN1_T2(GENERAL_STRING, o, t, x, xl)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_UTC_TIME
+/****f* silcasn1/SILC_ASN1_UTC_TIME
  *
  * SYNOPSIS
  *
@@ -1064,7 +1192,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  *
  *    Decoding:
  *    SILC_ASN1_UTC_TIME(&str, &timeval)
- *    SILC_ASN1_UTC_TIME_T(opts, tag, &timeval)
+ *    SILC_ASN1_UTC_TIME_T(opts, tag, timeval)
  *
  * DESCRIPTION
  *
@@ -1077,7 +1205,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_UTC_TIME(x) SILC_ASN1_U1(UTC_TIME, x)
 #define SILC_ASN1_UTC_TIME_T(o, t, x) SILC_ASN1_T1(UTC_TIME, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_GEN_TIME
+/****f* silcasn1/SILC_ASN1_GEN_TIME
  *
  * SYNOPSIS
  *
@@ -1087,7 +1215,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
  *
  *    Decoding:
  *    SILC_ASN1_GEN_TIME(&str, &timeval)
- *    SILC_ASN1_GEN_TIME_T(opts, tag, &timeval)
+ *    SILC_ASN1_GEN_TIME_T(opts, tag, timeval)
  *
  * DESCRIPTION
  *
@@ -1100,7 +1228,7 @@ bool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...);
 #define SILC_ASN1_GEN_TIME(x) SILC_ASN1_U1(GENERALIZED_TIME, x)
 #define SILC_ASN1_GEN_TIME_T(o, t, x) SILC_ASN1_T1(GENERALIZED_TIME, o, t, x)
 
-/****f* silcasn1/SilcASN1API/SILC_ASN1_END
+/****f* silcasn1/SILC_ASN1_END
  *
  * SYNOPSIS
  *