Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[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 - 2006 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 #define SILC_ASN1_TAG_SHORT_INTEGER 0x7006  /* Short integer */
46
47 /* Helper macros for adding the arguments to encoder and decoder. */
48
49 /* The arguments to silc_asn1_encode and silc_asn1_decode are constructed
50    as follows:
51
52    The first argument for type is a 32 bit integer where first 15-bits are
53    reserved for the type.  If the bit 16 is set then type and tag are same
54    and next argument is NOT the tag number.  If bit 16 is not set then
55    next argument is a 32 bit tag number.  This then also means that the type
56    is either implicitly or explicitly tagged.  The second 16-bits of the
57    first 32-bits argument is reserved for options.
58
59    Any argument that follow the type and optional tag number argument are
60    type specific arguments.
61
62    The SILC_ASN1_Ux macros set the bit 16, since the type and tag are same,
63    and also options are set to zero (0).
64
65    The SILC_ASN1_Tx macros does not set bit 16, but separate tag argument is
66    provided.  Options may or may not be zero, and they are put at the high
67    16-bits part of the first 32-bit argument.
68 */
69
70 #define SILC_ASN1_U0(type) \
71   SILC_ASN1_TAG_ ## type | 0x8000
72 #define SILC_ASN1_U1(type, x) \
73   SILC_ASN1_TAG_ ## type | 0x8000, (x)
74 #define SILC_ASN1_U2(type, x, xl) \
75   SILC_ASN1_TAG_ ## type | 0x8000, (x), (xl)
76
77 #define SILC_ASN1_T0(type, o, t) \
78   SILC_ASN1_TAG_ ## type | (o) << 16, (t)
79 #define SILC_ASN1_T1(type, o, t, x) \
80   SILC_ASN1_TAG_ ## type | (o) << 16, (t), (x)
81 #define SILC_ASN1_T2(type, o, t, x, xl) \
82   SILC_ASN1_TAG_ ## type | (o) << 16, (t), (x), (xl)
83
84 /* Macro to retreive type, options and tag.  The ret_type will include
85    the actual type, ret_class the BER class from options, ret_opts the
86    options (without the class), and ret_tag the tag. */
87 #define SILC_ASN1_ARGS(asn1, ret_type, ret_tag, ret_class, ret_opts)    \
88   ret_type = va_arg(asn1->ap, SilcUInt32);                              \
89   ret_tag = ret_class = ret_opts = 0;                                   \
90   if (ret_type != SILC_ASN1_END &&                                      \
91       ret_type != SILC_ASN1_TAG_OPTS) {                                 \
92     if (ret_type & 0x8000)                                              \
93       ret_tag = (ret_type & 0xffff) & ~0x8000;                          \
94     else                                                                \
95       ret_tag = va_arg(asn1->ap, SilcUInt32);                           \
96     ret_class = ret_type >> 16 & 0xf;                                   \
97     ret_opts = ret_type >> 16 & ~0xf;                                   \
98     if (ret_class)                                                      \
99       ret_class--;                                                      \
100     ret_type = (ret_type & 0xffff) & ~0x8000;                           \
101   }
102
103 /* Internal functions */
104
105 #if defined(SILC_DEBUG)
106 /* Returns string representation of a tag */
107 const char *silc_asn1_tag_name(SilcAsn1Tag tag);
108 #endif /* SILC_DEBUG */
109
110 #ifdef SILC_DIST_INPLACE
111 /* Dumps the ASN.1 data block into standard output (stdout). */
112 SilcBool silc_asn1_dump(SilcAsn1 asn1, SilcBuffer src);
113 #endif /* SILC_DIST_INPLACE */
114
115 #endif /* SILCASN1_I_H */