Added SILC_ASN1_ANY_PRIMITIVE to encode/decode any pre-encoded
[silc.git] / lib / silcasn1 / silcasn1_i.h
1 /*
2
3   silcasn1_i.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2005 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #ifndef SILCASN1_I_H
21 #define SILCASN1_I_H
22
23 #ifndef SILCASN1_H
24 #error "Do not include this header directly"
25 #endif
26
27 /* ASN.1 context */
28 struct SilcAsn1Object {
29   va_list ap;                   /* List of ASN.1 types given as argument */
30   SilcStack stack1;             /* Stack for encoder */
31   SilcStack stack2;             /* Internal stack for encoding/decoding */
32   unsigned int accumul  : 1;    /* Accumulate memory from stack for result */
33 };
34
35 /* The maximum depth for recursion in encoder and decoder. */
36 #define SILC_ASN1_RECURSION_DEPTH 512
37
38 /* Implementation specific special tags.  Range is 0x7000 - 0x7fff. */
39 #define SILC_ASN1_TAG_ANY           0x7000  /* SILC_ASN1_ANY given  */
40 #define SILC_ASN1_TAG_FUNC          0x7001  /* Callback encoder/decoder */
41 #define SILC_ASN1_TAG_OPTS          0x7002  /* SILC_ASN1_OPTS given */
42 #define SILC_ASN1_TAG_CHOICE        0x7003  /* SILC_ASN1_CHOICE given */
43 #define SILC_ASN1_TAG_SEQUENCE_OF   0x7004  /* SILC_ASN1_SEQUENCE_OF given */
44 #define SILC_ASN1_TAG_ANY_PRIMITIVE 0x7005  /* Pre-encoded primitive data */
45
46 /* Helper macros for adding the arguments to encoder and decoder. */
47
48 /* The arguments to silc_asn1_encode and silc_asn1_decode are constructed
49    as follows:
50
51    The first argument for type is a 32 bit integer where first 15-bits are
52    reserved for the type.  If the bit 16 is set then type and tag are same
53    and next argument is NOT the tag number.  If bit 16 is not set then
54    next argument is a 32 bit tag number.  This then also means that the type
55    is either implicitly or explicitly tagged.  The second 16-bits of the
56    first 32-bits argument is reserved for options.
57
58    Any argument that follow the type and optional tag number argument are
59    type specific arguments.
60
61    The SILC_ASN1_Ux macros set the bit 16, since the type and tag are same,
62    and also options are set to zero (0).
63
64    The SILC_ASN1_Tx macros does not set bit 16, but separate tag argument is
65    provided.  Options may or may not be zero, and they are put at the high
66    16-bits part of the first 32-bit argument.
67 */
68
69 #define SILC_ASN1_U0(type) \
70   SILC_ASN1_TAG_ ## type | 0x8000
71 #define SILC_ASN1_U1(type, x) \
72   SILC_ASN1_TAG_ ## type | 0x8000, (x)
73 #define SILC_ASN1_U2(type, x, xl) \
74   SILC_ASN1_TAG_ ## type | 0x8000, (x), (xl)
75
76 #define SILC_ASN1_T0(type, o, t) \
77   SILC_ASN1_TAG_ ## type | (o) << 16, (t)
78 #define SILC_ASN1_T1(type, o, t, x) \
79   SILC_ASN1_TAG_ ## type | (o) << 16, (t), (x)
80 #define SILC_ASN1_T2(type, o, t, x, xl) \
81   SILC_ASN1_TAG_ ## type | (o) << 16, (t), (x), (xl)
82
83 /* Macro to retreive type, options and tag.  The ret_type will include
84    the actual type, ret_class the BER class from options, ret_opts the
85    options (without the class), and ret_tag the tag. */
86 #define SILC_ASN1_ARGS(asn1, ret_type, ret_tag, ret_class, ret_opts)    \
87   ret_type = va_arg(asn1->ap, SilcUInt32);                              \
88   ret_tag = ret_class = ret_opts = 0;                                   \
89   if (ret_type != SILC_ASN1_END &&                                      \
90       ret_type != SILC_ASN1_TAG_OPTS) {                                 \
91     if (ret_type & 0x8000)                                              \
92       ret_tag = (ret_type & 0xffff) & ~0x8000;                          \
93     else                                                                \
94       ret_tag = va_arg(asn1->ap, SilcUInt32);                           \
95     ret_class = ret_type >> 16 & 0xf;                                   \
96     ret_opts = ret_type >> 16 & ~0xf;                                   \
97     if (ret_class)                                                      \
98       ret_class--;                                                      \
99     ret_type = (ret_type & 0xffff) & ~0x8000;                           \
100   }
101
102 #ifdef SILC_DIST_INPLACE
103 /* Internal functions */
104
105 /* Returns string representation of a tag */
106 const char *silc_asn1_tag_name(SilcAsn1Tag tag);
107
108 /* Dumps the ASN.1 data block into standard output (stdout). */
109 SilcBool silc_asn1_dump(SilcAsn1 asn1, SilcBuffer src);
110 #endif /* SILC_DIST_INPLACE */
111
112 #endif /* SILCASN1_I_H */