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