Added SILC Server library.
[silc.git] / lib / silcasn1 / silcasn1.c
1 /*
2
3   silcasn1.c
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 #include "silc.h"
21 #include "silcasn1.h"
22 #include "silcber.h"
23
24 /* Allocate ASN.1 context. */
25
26 SilcAsn1 silc_asn1_alloc(void)
27 {
28   SilcAsn1 asn1 = silc_calloc(1, sizeof(*asn1));
29   if (!asn1)
30     return NULL;
31
32   if (!silc_asn1_init(asn1))
33     return NULL;
34
35   return asn1;
36 }
37
38 /* Free ASN.1 context */
39
40 void silc_asn1_free(SilcAsn1 asn1)
41 {
42   silc_asn1_uninit(asn1);
43   silc_free(asn1);
44 }
45
46 /* Init pre-allocated ASN.1 context */
47
48 SilcBool silc_asn1_init(SilcAsn1 asn1)
49 {
50   asn1->stack1 = silc_stack_alloc(768);
51   if (!asn1->stack1)
52     return FALSE;
53
54   asn1->stack2 = silc_stack_alloc(768);
55   if (!asn1->stack2) {
56     silc_stack_free(asn1->stack2);
57     return FALSE;
58   }
59
60   asn1->accumul = 0;
61
62   return TRUE;
63 }
64
65 /* Uninit ASN.1 context */
66
67 void silc_asn1_uninit(SilcAsn1 asn1)
68 {
69 #if 1
70   silc_stack_stats(asn1->stack1);
71   silc_stack_stats(asn1->stack2);
72 #endif
73   silc_stack_free(asn1->stack1);
74   silc_stack_free(asn1->stack2);
75 }
76
77 #ifdef SILC_DIST_INPLACE
78 /* Returns string representation of a tag */
79
80 const char *silc_asn1_tag_name(SilcAsn1Tag tag)
81 {
82   switch (tag) {
83   case SILC_ASN1_END:
84     return "END";
85   case SILC_ASN1_TAG_OPTS:
86     return "";
87   case SILC_ASN1_TAG_CHOICE:
88     return "choice";
89   case SILC_ASN1_TAG_ANY:
90     return "any";
91   case SILC_ASN1_TAG_SEQUENCE_OF:
92     return "sequence of";
93
94   case SILC_ASN1_TAG_SEQUENCE:
95     return "sequence";
96   case SILC_ASN1_TAG_SET:
97     return "set";
98   case SILC_ASN1_TAG_INTEGER:
99     return "integer";
100   case SILC_ASN1_TAG_OID:
101     return "oid";
102   case SILC_ASN1_TAG_BOOLEAN:
103     return "boolean";
104   case SILC_ASN1_TAG_OCTET_STRING:
105     return "octet-string";
106   case SILC_ASN1_TAG_BIT_STRING:
107     return "bit-string";
108   case SILC_ASN1_TAG_NULL:
109     return "null";
110   case SILC_ASN1_TAG_ENUM:
111     return "enum";
112   case SILC_ASN1_TAG_UTC_TIME:
113     return "utc-time";
114   case SILC_ASN1_TAG_GENERALIZED_TIME:
115     return "generalized-time";
116   case SILC_ASN1_TAG_UTF8_STRING:
117     return "utf8-string";
118   case SILC_ASN1_TAG_NUMERIC_STRING:
119     return "numeric-string";
120   case SILC_ASN1_TAG_PRINTABLE_STRING:
121     return "printable-string";
122   case SILC_ASN1_TAG_IA5_STRING:
123     return "ia5-string";
124   case SILC_ASN1_TAG_VISIBLE_STRING:
125     return "visible-string";
126   case SILC_ASN1_TAG_UNIVERSAL_STRING:
127     return "universal-string";
128   case SILC_ASN1_TAG_UNRESTRICTED_STRING:
129     return "unrestricted-string";
130   case SILC_ASN1_TAG_BMP_STRING:
131     return "bmp-string";
132   case SILC_ASN1_TAG_ODE:
133     return "ode";
134   case SILC_ASN1_TAG_ETI:
135     return "eti";
136   case SILC_ASN1_TAG_REAL:
137     return "real";
138   case SILC_ASN1_TAG_EMBEDDED:
139     return "embedded";
140   case SILC_ASN1_TAG_ROI:
141     return "roi";
142   case SILC_ASN1_TAG_TELETEX_STRING:
143     return "teletex-string";
144   case SILC_ASN1_TAG_VIDEOTEX_STRING:
145     return "videotex-string";
146   case SILC_ASN1_TAG_GRAPHIC_STRING:
147     return "graphic-string";
148   case SILC_ASN1_TAG_GENERAL_STRING:
149     return "general-string";
150   default:
151     break;
152   }
153   return "unknown";
154 }
155
156 /* Dumps the ASN.1 data block into standard output (stdout). */
157
158 SilcBool silc_asn1_dump(SilcAsn1 asn1, SilcBuffer src)
159 {
160   SilcBool ret = FALSE;
161   SilcBerEncoding renc;
162   SilcAsn1Tag rtag;
163   const unsigned char *rdata;
164   SilcUInt32 rdata_len, len = 0;
165   SilcBool rindef;
166
167   SILC_LOG_DEBUG(("Dumping ASN.1"));
168
169   while (silc_buffer_len(src)) {
170     /* Decode the BER block */
171     ret = silc_ber_decode(src, NULL, &renc, (SilcUInt32 *)&rtag, &rdata,
172                           &rdata_len, &rindef, &len);
173     if (!ret) {
174       SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
175       return FALSE;
176     }
177
178     fprintf(stdout, "Type %s [%d]\n",
179             silc_asn1_tag_name(rtag), rtag);
180
181     if (renc == SILC_BER_ENC_PRIMITIVE)
182       len = len + rdata_len;
183     else
184       len = len;
185
186     if (len)
187       silc_buffer_pull(src, len);
188   }
189
190   return TRUE;
191 }
192
193 #endif /* SILC_DIST_INPLACE */