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