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