lgtm: Fix building dependencies (in particular tpm2-tss)
[strongswan.git] / src / libstrongswan / asn1 / asn1_parser.c
1 /*
2 * Copyright (C) 2006 Martin Will
3 * Copyright (C) 2000-2017 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <time.h>
20
21 #include <utils/debug.h>
22
23 #include "asn1.h"
24 #include "asn1_parser.h"
25
26 #define ASN1_MAX_LEVEL 10
27
28 typedef struct private_asn1_parser_t private_asn1_parser_t;
29
30 /**
31 * Private data of an asn1_cxt_t object.
32 */
33 struct private_asn1_parser_t {
34 /**
35 * Public interface.
36 */
37 asn1_parser_t public;
38
39 /**
40 * Syntax definition of ASN.1 object
41 */
42 asn1Object_t const *objects;
43
44 /**
45 * Current syntax definition line
46 */
47 int line;
48
49 /**
50 * Current stat of the parsing operation
51 */
52 bool success;
53
54 /**
55 * Declare object data as private - use debug level 4 to log it
56 */
57 bool private;
58
59 /**
60 * Top-most type is implicit - ignore it
61 */
62 bool implicit;
63
64 /**
65 * Top-most parsing level - defaults to 0
66 */
67 u_int level0;
68
69 /**
70 * Jump back address for loops for each level
71 */
72 int loopAddr[ASN1_MAX_LEVEL + 1];
73
74 /**
75 * Current parsing pointer for each level
76 */
77 chunk_t blobs[ASN1_MAX_LEVEL + 2];
78
79 /**
80 * Parsing a CHOICE on the current level ?
81 */
82 bool choice[ASN1_MAX_LEVEL + 2];
83
84 };
85
86 METHOD(asn1_parser_t, iterate, bool,
87 private_asn1_parser_t *this, int *objectID, chunk_t *object)
88 {
89 chunk_t *blob, *blob1, blob_ori;
90 u_char *start_ptr;
91 u_int level;
92 asn1Object_t obj;
93
94 *object = chunk_empty;
95
96 /* Advance to the next object syntax definition line */
97 obj = this->objects[++(this->line)];
98
99 /* Terminate if the end of the object syntax definition has been reached */
100 if (obj.flags & ASN1_EXIT)
101 {
102 return FALSE;
103 }
104
105 if (obj.flags & ASN1_END) /* end of loop or choice or option found */
106 {
107 if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
108 {
109 this->line = this->loopAddr[obj.level]; /* another iteration */
110 obj = this->objects[this->line];
111 }
112 else
113 {
114 this->loopAddr[obj.level] = 0; /* exit loop */
115
116 if (obj.flags & ASN1_CHOICE) /* end of choices */
117 {
118 if (this->choice[obj.level+1])
119 {
120 DBG1(DBG_ASN, "L%d - %s: incorrect choice encoding",
121 this->level0 + obj.level, obj.name);
122 this->success = FALSE;
123 goto end;
124 }
125 }
126
127 if (obj.flags & ASN1_CH) /* end of choice */
128 {
129 /* parsed a valid choice */
130 this->choice[obj.level] = FALSE;
131
132 /* advance to end of choices */
133 do
134 {
135 this->line++;
136 }
137 while (!((this->objects[this->line].flags & ASN1_END) &&
138 (this->objects[this->line].flags & ASN1_CHOICE) &&
139 (this->objects[this->line].level == obj.level-1)));
140 this->line--;
141 }
142
143 goto end;
144 }
145 }
146
147 level = this->level0 + obj.level;
148 blob = this->blobs + obj.level;
149 blob_ori = *blob;
150 blob1 = blob + 1;
151 start_ptr = blob->ptr;
152
153 /* handle ASN.1 defaults values */
154 if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
155 {
156 /* field is missing */
157 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
158 if (obj.type & ASN1_CONSTRUCTED)
159 {
160 this->line++ ; /* skip context-specific tag */
161 }
162 goto end;
163 }
164
165 /* handle ASN.1 options */
166 if ((obj.flags & ASN1_OPT)
167 && (blob->len == 0 || *start_ptr != obj.type))
168 {
169 /* advance to end of missing option field */
170 do
171 {
172 this->line++;
173 }
174 while (!((this->objects[this->line].flags & ASN1_END) &&
175 (this->objects[this->line].level == obj.level)));
176 goto end;
177 }
178
179 /* an ASN.1 object must possess at least a tag and length field */
180 if (blob->len < 2)
181 {
182 DBG1(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets",
183 level, obj.name);
184 this->success = FALSE;
185 goto end;
186 }
187
188 blob1->len = asn1_length(blob);
189
190 if (blob1->len == ASN1_INVALID_LENGTH)
191 {
192 DBG1(DBG_ASN, "L%d - %s: length of ASN.1 object invalid or too large",
193 level, obj.name);
194 this->success = FALSE;
195 goto end;
196 }
197
198 blob1->ptr = blob->ptr;
199 blob->ptr += blob1->len;
200 blob->len -= blob1->len;
201
202 /* handle ASN.1 choice without explicit context encoding */
203 if ((obj.flags & ASN1_CHOICE) && obj.type == ASN1_EOC)
204 {
205 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
206 this->choice[obj.level+1] = TRUE;
207 *blob1 = blob_ori;
208 goto end;
209 }
210
211 /* return raw ASN.1 object without prior type checking */
212 if (obj.flags & ASN1_RAW)
213 {
214 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
215 object->ptr = start_ptr;
216 object->len = (size_t)(blob->ptr - start_ptr);
217 goto end;
218 }
219
220 if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
221 {
222 DBG2(DBG_ASN, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
223 level, obj.name, obj.type, *start_ptr);
224 DBG3(DBG_ASN, "%b", start_ptr, (u_int)(blob->ptr - start_ptr));
225 this->success = FALSE;
226 goto end;
227 }
228
229 DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
230
231 /* In case of "SEQUENCE OF" or "SET OF" start a loop */
232 if (obj.flags & ASN1_LOOP)
233 {
234 if (blob1->len > 0)
235 {
236 /* at least one item, start the loop */
237 this->loopAddr[obj.level] = this->line + 1;
238 }
239 else
240 {
241 /* no items, advance directly to end of loop */
242 do
243 {
244 this->line++;
245 }
246 while (!((this->objects[this->line].flags & ASN1_END) &&
247 (this->objects[this->line].level == obj.level)));
248 goto end;
249 }
250 }
251
252 /* In case of a "CHOICE" start to scan for exactly one valid choice */
253 if (obj.flags & ASN1_CHOICE)
254 {
255 if (blob1->len == 0)
256 {
257 DBG1(DBG_ASN, "L%d - %s: contains no choice", level, obj.name);
258 this->success = FALSE;
259 goto end;
260 }
261 this->choice[obj.level+1] = TRUE;
262 }
263
264 if (obj.flags & ASN1_OBJ)
265 {
266 object->ptr = start_ptr;
267 object->len = (size_t)(blob->ptr - start_ptr);
268 if (this->private)
269 {
270 DBG4(DBG_ASN, "%B", object);
271 }
272 else
273 {
274 DBG3(DBG_ASN, "%B", object);
275 }
276 }
277 else if (obj.flags & ASN1_BODY)
278 {
279 *object = *blob1;
280 asn1_debug_simple_object(*object, obj.type, this->private);
281 }
282
283 end:
284 *objectID = this->line;
285 return this->success;
286 }
287
288 METHOD(asn1_parser_t, get_level, u_int,
289 private_asn1_parser_t *this)
290 {
291 return this->level0 + this->objects[this->line].level;
292 }
293
294 METHOD(asn1_parser_t, set_top_level, void,
295 private_asn1_parser_t *this, u_int level0)
296 {
297 this->level0 = level0;
298 }
299
300 METHOD(asn1_parser_t, set_flags, void,
301 private_asn1_parser_t *this, bool implicit, bool private)
302 {
303 this->implicit = implicit;
304 this->private = private;
305 }
306
307 METHOD(asn1_parser_t, success, bool,
308 private_asn1_parser_t *this)
309 {
310 return this->success;
311 }
312
313 METHOD(asn1_parser_t, destroy, void,
314 private_asn1_parser_t *this)
315 {
316 free(this);
317 }
318
319 /**
320 * Defined in header.
321 */
322 asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob)
323 {
324 private_asn1_parser_t *this;
325
326 INIT(this,
327 .public = {
328 .iterate = _iterate,
329 .get_level = _get_level,
330 .set_top_level = _set_top_level,
331 .set_flags = _set_flags,
332 .success = _success,
333 .destroy = _destroy,
334 },
335 .objects = objects,
336 .blobs[0] = blob,
337 .line = -1,
338 .success = TRUE,
339 );
340
341 return &this->public;
342 }