/src/libtasn1/lib/parser_aux.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2000-2025 Free Software Foundation, Inc. |
3 | | * |
4 | | * This file is part of LIBTASN1. |
5 | | * |
6 | | * The LIBTASN1 library is free software; you can redistribute it |
7 | | * and/or modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, but |
12 | | * WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, see |
18 | | * <https://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include <config.h> |
22 | | |
23 | | #include <limits.h> /* WORD_BIT */ |
24 | | |
25 | | #include "int.h" |
26 | | #include "parser_aux.h" |
27 | | #include "gstr.h" |
28 | | #include "structure.h" |
29 | | #include "element.h" |
30 | | #include "c-ctype.h" |
31 | | |
32 | | char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ |
33 | | |
34 | | /* Return a hash of the N bytes of X using the method described by |
35 | | Bruno Haible in https://www.haible.de/bruno/hashfunc.html. |
36 | | Note that while many hash functions reduce their result via modulo |
37 | | to a 0..table_size-1 range, this function does not do that. |
38 | | |
39 | | This implementation has been changed from size_t -> unsigned int. */ |
40 | | |
41 | | #ifdef __clang__ |
42 | | __attribute__((no_sanitize ("integer"))) |
43 | | #endif |
44 | | _GL_ATTRIBUTE_PURE static unsigned int _asn1_hash_name (const char *x) |
45 | 353k | { |
46 | 353k | const unsigned char *s = (unsigned char *) x; |
47 | 353k | unsigned h = 0; |
48 | | |
49 | 2.44M | while (*s) |
50 | 2.08M | h = (*s++) + ((h << 9) | (h >> (WORD_BIT - 9))); |
51 | | |
52 | 353k | return h; |
53 | 353k | } |
54 | | |
55 | | /******************************************************/ |
56 | | /* Function : _asn1_add_static_node */ |
57 | | /* Description: creates a new NODE_ASN element and */ |
58 | | /* puts it in the list pointed by e_list. */ |
59 | | /* Parameters: */ |
60 | | /* e_list: of type list_type; must be NULL initially */ |
61 | | /* type: type of the new element (see ASN1_ETYPE_ */ |
62 | | /* and CONST_ constants). */ |
63 | | /* Return: pointer to the new element. */ |
64 | | /******************************************************/ |
65 | | asn1_node |
66 | | _asn1_add_static_node (list_type **e_list, unsigned int type) |
67 | 51.3k | { |
68 | 51.3k | list_type *p; |
69 | 51.3k | asn1_node punt; |
70 | | |
71 | 51.3k | punt = calloc (1, sizeof (struct asn1_node_st)); |
72 | 51.3k | if (punt == NULL) |
73 | 0 | return NULL; |
74 | | |
75 | 51.3k | p = malloc (sizeof (list_type)); |
76 | 51.3k | if (p == NULL) |
77 | 0 | { |
78 | 0 | free (punt); |
79 | 0 | return NULL; |
80 | 0 | } |
81 | | |
82 | 51.3k | p->node = punt; |
83 | 51.3k | p->next = *e_list; |
84 | 51.3k | *e_list = p; |
85 | | |
86 | 51.3k | punt->type = type; |
87 | | |
88 | 51.3k | return punt; |
89 | 51.3k | } |
90 | | |
91 | | static int |
92 | | _asn1_add_static_node2 (list_type **e_list, asn1_node node) |
93 | 65.3k | { |
94 | 65.3k | list_type *p; |
95 | | |
96 | 65.3k | p = malloc (sizeof (list_type)); |
97 | 65.3k | if (p == NULL) |
98 | 0 | { |
99 | 0 | return -1; |
100 | 0 | } |
101 | | |
102 | 65.3k | p->node = node; |
103 | 65.3k | p->next = *e_list; |
104 | 65.3k | *e_list = p; |
105 | | |
106 | 65.3k | return 0; |
107 | 65.3k | } |
108 | | |
109 | | /** |
110 | | * asn1_find_node: |
111 | | * @pointer: NODE_ASN element pointer. |
112 | | * @name: null terminated string with the element's name to find. |
113 | | * |
114 | | * Searches for an element called @name starting from @pointer. The |
115 | | * name is composed by different identifiers separated by dots. When |
116 | | * *@pointer has a name, the first identifier must be the name of |
117 | | * *@pointer, otherwise it must be the name of one child of *@pointer. |
118 | | * |
119 | | * Returns: the search result, or %NULL if not found. |
120 | | **/ |
121 | | asn1_node |
122 | | asn1_find_node (asn1_node_const pointer, const char *name) |
123 | 99.2k | { |
124 | 99.2k | asn1_node_const p; |
125 | 99.2k | char *n_end, n[ASN1_MAX_NAME_SIZE + 1]; |
126 | 99.2k | const char *n_start; |
127 | 99.2k | unsigned int nsize; |
128 | 99.2k | unsigned int nhash; |
129 | 99.2k | const struct asn1_node_array_st *numbered_children; |
130 | | |
131 | 99.2k | if (pointer == NULL) |
132 | 1.10k | return NULL; |
133 | | |
134 | 98.1k | if (name == NULL) |
135 | 0 | return NULL; |
136 | | |
137 | 98.1k | p = pointer; |
138 | 98.1k | n_start = name; |
139 | | |
140 | 98.1k | if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?') |
141 | 1.22k | { /* ?CURRENT */ |
142 | 1.22k | n_start = strchr (n_start, '.'); |
143 | 1.22k | if (n_start) |
144 | 1.14k | n_start++; |
145 | 1.22k | } |
146 | 96.8k | else if (p->name[0] != 0) |
147 | 93.9k | { /* has *pointer got a name ? */ |
148 | 93.9k | n_end = strchr (n_start, '.'); /* search the first dot */ |
149 | 93.9k | if (n_end) |
150 | 93.7k | { |
151 | 93.7k | nsize = n_end - n_start; |
152 | 93.7k | if (nsize >= sizeof (n)) |
153 | 0 | return NULL; |
154 | | |
155 | 93.7k | memcpy (n, n_start, nsize); |
156 | 93.7k | n[nsize] = 0; |
157 | 93.7k | n_start = n_end; |
158 | 93.7k | n_start++; |
159 | | |
160 | 93.7k | nhash = _asn1_hash_name (n); |
161 | 93.7k | } |
162 | 280 | else |
163 | 280 | { |
164 | 280 | _asn1_str_cpy (n, sizeof (n), n_start); |
165 | 280 | nhash = _asn1_hash_name (n); |
166 | | |
167 | 280 | n_start = NULL; |
168 | 280 | } |
169 | | |
170 | 94.0k | while (p) |
171 | 93.9k | { |
172 | 93.9k | if (nhash == p->name_hash && (!strcmp (p->name, n))) |
173 | 93.8k | break; |
174 | 106 | else |
175 | 106 | p = p->right; |
176 | 93.9k | } /* while */ |
177 | | |
178 | 93.9k | if (p == NULL) |
179 | 106 | return NULL; |
180 | 93.9k | } |
181 | 2.88k | else |
182 | 2.88k | { /* *pointer doesn't have a name */ |
183 | 2.88k | if (n_start[0] == 0) |
184 | 349 | return (asn1_node) p; |
185 | 2.88k | } |
186 | | |
187 | 197k | while (n_start) |
188 | 100k | { /* Has the end of NAME been reached? */ |
189 | 100k | n_end = strchr (n_start, '.'); /* search the next dot */ |
190 | 100k | if (n_end) |
191 | 3.24k | { |
192 | 3.24k | nsize = n_end - n_start; |
193 | 3.24k | if (nsize >= sizeof (n)) |
194 | 0 | return NULL; |
195 | | |
196 | 3.24k | memcpy (n, n_start, nsize); |
197 | 3.24k | n[nsize] = 0; |
198 | 3.24k | n_start = n_end; |
199 | 3.24k | n_start++; |
200 | | |
201 | 3.24k | nhash = _asn1_hash_name (n); |
202 | 3.24k | } |
203 | 97.2k | else |
204 | 97.2k | { |
205 | 97.2k | _asn1_str_cpy (n, sizeof (n), n_start); |
206 | 97.2k | nhash = _asn1_hash_name (n); |
207 | 97.2k | n_start = NULL; |
208 | 97.2k | } |
209 | | |
210 | 100k | if (p->down == NULL) |
211 | 69 | return NULL; |
212 | | |
213 | 100k | numbered_children = &p->numbered_children; |
214 | 100k | p = p->down; |
215 | 100k | if (p == NULL) |
216 | 0 | return NULL; |
217 | | |
218 | | /* The identifier "?LAST" indicates the last element |
219 | | in the right chain. */ |
220 | 100k | if (n[0] == '?' && n[1] == 'L') /* ?LAST */ |
221 | 3.15k | { |
222 | 27.2k | while (p->right) |
223 | 24.0k | p = p->right; |
224 | 3.15k | } |
225 | 97.2k | else |
226 | 97.2k | { /* no "?LAST" */ |
227 | 97.2k | if (n[0] == '?' && c_isdigit (n[1])) |
228 | 832 | { |
229 | 832 | long position = strtol (n + 1, NULL, 10); |
230 | 832 | if (position > 0 && position < LONG_MAX) |
231 | 194 | p = _asn1_node_array_get (numbered_children, position - 1); |
232 | 832 | } |
233 | 2.28M | while (p) |
234 | 2.28M | { |
235 | 2.28M | if (p->name_hash == nhash && !strcmp (p->name, n)) |
236 | 96.5k | break; |
237 | 2.18M | else |
238 | 2.18M | p = p->right; |
239 | 2.28M | } |
240 | 97.2k | } |
241 | 100k | if (p == NULL) |
242 | 724 | return NULL; |
243 | 100k | } /* while */ |
244 | | |
245 | 96.8k | return (asn1_node) p; |
246 | 97.6k | } |
247 | | |
248 | | |
249 | | /******************************************************************/ |
250 | | /* Function : _asn1_set_value */ |
251 | | /* Description: sets the field VALUE in a NODE_ASN element. The */ |
252 | | /* previous value (if exist) will be lost */ |
253 | | /* Parameters: */ |
254 | | /* node: element pointer. */ |
255 | | /* value: pointer to the value that you want to set. */ |
256 | | /* len: character number of value. */ |
257 | | /* Return: pointer to the NODE_ASN element. */ |
258 | | /******************************************************************/ |
259 | | asn1_node |
260 | | _asn1_set_value (asn1_node node, const void *value, unsigned int len) |
261 | 263k | { |
262 | 263k | if (node == NULL) |
263 | 0 | return node; |
264 | 263k | if (node->value) |
265 | 3.40k | { |
266 | 3.40k | if (node->value != node->small_value) |
267 | 947 | free (node->value); |
268 | 3.40k | node->value = NULL; |
269 | 3.40k | node->value_len = 0; |
270 | 3.40k | } |
271 | | |
272 | 263k | if (!len) |
273 | 6.15k | return node; |
274 | | |
275 | 257k | if (len < sizeof (node->small_value)) |
276 | 193k | { |
277 | 193k | node->value = node->small_value; |
278 | 193k | } |
279 | 63.6k | else |
280 | 63.6k | { |
281 | 63.6k | node->value = malloc (len); |
282 | 63.6k | if (node->value == NULL) |
283 | 0 | return NULL; |
284 | 63.6k | } |
285 | 257k | node->value_len = len; |
286 | | |
287 | 257k | memcpy (node->value, value, len); |
288 | 257k | return node; |
289 | 257k | } |
290 | | |
291 | | /******************************************************************/ |
292 | | /* Function : _asn1_set_value_lv */ |
293 | | /* Description: sets the field VALUE in a NODE_ASN element. The */ |
294 | | /* previous value (if exist) will be lost. The value */ |
295 | | /* given is stored as an length-value format (LV */ |
296 | | /* Parameters: */ |
297 | | /* node: element pointer. */ |
298 | | /* value: pointer to the value that you want to set. */ |
299 | | /* len: character number of value. */ |
300 | | /* Return: pointer to the NODE_ASN element. */ |
301 | | /******************************************************************/ |
302 | | asn1_node |
303 | | _asn1_set_value_lv (asn1_node node, const void *value, unsigned int len) |
304 | 5.43k | { |
305 | 5.43k | int len2; |
306 | 5.43k | void *temp; |
307 | | |
308 | 5.43k | if (node == NULL) |
309 | 0 | return node; |
310 | | |
311 | 5.43k | asn1_length_der (len, NULL, &len2); |
312 | 5.43k | temp = malloc (len + len2); |
313 | 5.43k | if (temp == NULL) |
314 | 0 | return NULL; |
315 | | |
316 | 5.43k | asn1_octet_der (value, len, temp, &len2); |
317 | 5.43k | return _asn1_set_value_m (node, temp, len2); |
318 | 5.43k | } |
319 | | |
320 | | /* the same as _asn1_set_value except that it sets an already malloc'ed |
321 | | * value. |
322 | | */ |
323 | | asn1_node |
324 | | _asn1_set_value_m (asn1_node node, void *value, unsigned int len) |
325 | 5.43k | { |
326 | 5.43k | if (node == NULL) |
327 | 0 | return node; |
328 | | |
329 | 5.43k | if (node->value) |
330 | 0 | { |
331 | 0 | if (node->value != node->small_value) |
332 | 0 | free (node->value); |
333 | 0 | node->value = NULL; |
334 | 0 | node->value_len = 0; |
335 | 0 | } |
336 | | |
337 | 5.43k | if (!len) |
338 | 0 | return node; |
339 | | |
340 | 5.43k | node->value = value; |
341 | 5.43k | node->value_len = len; |
342 | | |
343 | 5.43k | return node; |
344 | 5.43k | } |
345 | | |
346 | | /******************************************************************/ |
347 | | /* Function : _asn1_append_value */ |
348 | | /* Description: appends to the field VALUE in a NODE_ASN element. */ |
349 | | /* */ |
350 | | /* Parameters: */ |
351 | | /* node: element pointer. */ |
352 | | /* value: pointer to the value that you want to be appended. */ |
353 | | /* len: character number of value. */ |
354 | | /* Return: pointer to the NODE_ASN element. */ |
355 | | /******************************************************************/ |
356 | | asn1_node |
357 | | _asn1_append_value (asn1_node node, const void *value, unsigned int len) |
358 | 0 | { |
359 | 0 | if (node == NULL) |
360 | 0 | return node; |
361 | | |
362 | 0 | if (node->value == NULL) |
363 | 0 | return _asn1_set_value (node, value, len); |
364 | | |
365 | 0 | if (len == 0) |
366 | 0 | return node; |
367 | | |
368 | 0 | if (node->value == node->small_value) |
369 | 0 | { |
370 | | /* value is in node */ |
371 | 0 | int prev_len = node->value_len; |
372 | 0 | node->value_len += len; |
373 | 0 | node->value = malloc (node->value_len); |
374 | 0 | if (node->value == NULL) |
375 | 0 | { |
376 | 0 | node->value_len = 0; |
377 | 0 | return NULL; |
378 | 0 | } |
379 | | |
380 | 0 | if (prev_len > 0) |
381 | 0 | memcpy (node->value, node->small_value, prev_len); |
382 | |
|
383 | 0 | memcpy (&node->value[prev_len], value, len); |
384 | |
|
385 | 0 | return node; |
386 | 0 | } |
387 | 0 | else /* if (node->value != NULL && node->value != node->small_value) */ |
388 | 0 | { |
389 | | /* value is allocated */ |
390 | 0 | int prev_len = node->value_len; |
391 | 0 | node->value_len += len; |
392 | |
|
393 | 0 | node->value = _asn1_realloc (node->value, node->value_len); |
394 | 0 | if (node->value == NULL) |
395 | 0 | { |
396 | 0 | node->value_len = 0; |
397 | 0 | return NULL; |
398 | 0 | } |
399 | | |
400 | 0 | memcpy (&node->value[prev_len], value, len); |
401 | |
|
402 | 0 | return node; |
403 | 0 | } |
404 | 0 | } |
405 | | |
406 | | /******************************************************************/ |
407 | | /* Function : _asn1_set_name */ |
408 | | /* Description: sets the field NAME in a NODE_ASN element. The */ |
409 | | /* previous value (if exist) will be lost */ |
410 | | /* Parameters: */ |
411 | | /* node: element pointer. */ |
412 | | /* name: a null terminated string with the name that you want */ |
413 | | /* to set. */ |
414 | | /* Return: pointer to the NODE_ASN element. */ |
415 | | /******************************************************************/ |
416 | | asn1_node |
417 | | _asn1_set_name (asn1_node node, const char *name) |
418 | 159k | { |
419 | 159k | if (node == NULL) |
420 | 0 | return node; |
421 | | |
422 | 159k | _asn1_str_cpy (node->name, sizeof (node->name), name ? name : ""); |
423 | 159k | node->name_hash = _asn1_hash_name (node->name); |
424 | | |
425 | 159k | return node; |
426 | 159k | } |
427 | | |
428 | | /******************************************************************/ |
429 | | /* Function : _asn1_cpy_name */ |
430 | | /* Description: copies the field NAME in a NODE_ASN element. */ |
431 | | /* Parameters: */ |
432 | | /* dst: a dest element pointer. */ |
433 | | /* src: a source element pointer. */ |
434 | | /* Return: pointer to the NODE_ASN element. */ |
435 | | /******************************************************************/ |
436 | | asn1_node |
437 | | _asn1_cpy_name (asn1_node dst, asn1_node_const src) |
438 | 471k | { |
439 | 471k | if (dst == NULL) |
440 | 0 | return dst; |
441 | | |
442 | 471k | if (src == NULL) |
443 | 0 | { |
444 | 0 | dst->name[0] = 0; |
445 | 0 | dst->name_hash = _asn1_hash_name (dst->name); |
446 | 0 | return dst; |
447 | 0 | } |
448 | | |
449 | 471k | _asn1_str_cpy (dst->name, sizeof (dst->name), src->name); |
450 | 471k | dst->name_hash = src->name_hash; |
451 | | |
452 | 471k | return dst; |
453 | 471k | } |
454 | | |
455 | | /******************************************************************/ |
456 | | /* Function : _asn1_set_right */ |
457 | | /* Description: sets the field RIGHT in a NODE_ASN element. */ |
458 | | /* Parameters: */ |
459 | | /* node: element pointer. */ |
460 | | /* right: pointer to a NODE_ASN element that you want be pointed*/ |
461 | | /* by NODE. */ |
462 | | /* Return: pointer to *NODE. */ |
463 | | /******************************************************************/ |
464 | | asn1_node |
465 | | _asn1_set_right (asn1_node node, asn1_node right) |
466 | 478k | { |
467 | 478k | if (node == NULL) |
468 | 378 | return node; |
469 | 477k | node->right = right; |
470 | 477k | if (right) |
471 | 460k | right->left = node; |
472 | 477k | return node; |
473 | 478k | } |
474 | | |
475 | | |
476 | | /******************************************************************/ |
477 | | /* Function : _asn1_get_last_right */ |
478 | | /* Description: return the last element along the right chain. */ |
479 | | /* Parameters: */ |
480 | | /* node: starting element pointer. */ |
481 | | /* Return: pointer to the last element along the right chain. */ |
482 | | /******************************************************************/ |
483 | | asn1_node |
484 | | _asn1_get_last_right (asn1_node_const node) |
485 | 23.0k | { |
486 | 23.0k | asn1_node_const p; |
487 | | |
488 | 23.0k | if (node == NULL) |
489 | 0 | return NULL; |
490 | 23.0k | p = node; |
491 | 1.56M | while (p->right) |
492 | 1.53M | p = p->right; |
493 | 23.0k | return (asn1_node) p; |
494 | 23.0k | } |
495 | | |
496 | | /******************************************************************/ |
497 | | /* Function : _asn1_remove_node */ |
498 | | /* Description: gets free the memory allocated for an NODE_ASN */ |
499 | | /* element (not the elements pointed by it). */ |
500 | | /* Parameters: */ |
501 | | /* node: NODE_ASN element pointer. */ |
502 | | /* flags: ASN1_DELETE_FLAG_* */ |
503 | | /******************************************************************/ |
504 | | void |
505 | | _asn1_remove_node (asn1_node node, unsigned int flags) |
506 | 657k | { |
507 | 657k | if (node == NULL) |
508 | 2.37k | return; |
509 | | |
510 | 655k | if (node->value != NULL) |
511 | 259k | { |
512 | 259k | if (flags & ASN1_DELETE_FLAG_ZEROIZE) |
513 | 0 | { |
514 | 0 | safe_memset (node->value, 0, node->value_len); |
515 | 0 | } |
516 | | |
517 | 259k | if (node->value != node->small_value) |
518 | 68.0k | free (node->value); |
519 | 259k | } |
520 | | |
521 | 655k | free (node->numbered_children.nodes); |
522 | 655k | free (node); |
523 | 655k | } |
524 | | |
525 | | /******************************************************************/ |
526 | | /* Function : _asn1_find_up */ |
527 | | /* Description: return the father of the NODE_ASN element. */ |
528 | | /* Parameters: */ |
529 | | /* node: NODE_ASN element pointer. */ |
530 | | /* Return: Null if not found. */ |
531 | | /******************************************************************/ |
532 | | asn1_node |
533 | | _asn1_find_up (asn1_node_const node) |
534 | 1.25M | { |
535 | 1.25M | asn1_node_const p; |
536 | | |
537 | 1.25M | if (node == NULL) |
538 | 0 | return NULL; |
539 | | |
540 | 1.25M | p = node; |
541 | | |
542 | 2.54M | while ((p->left != NULL) && (p->left->right == p)) |
543 | 1.29M | p = p->left; |
544 | | |
545 | 1.25M | return p->left; |
546 | 1.25M | } |
547 | | |
548 | | static unsigned |
549 | | _asn1_is_up (asn1_node_const up_cand, asn1_node_const down) |
550 | 9.60k | { |
551 | 9.60k | asn1_node_const d, u; |
552 | | |
553 | 9.60k | if (up_cand == NULL || down == NULL) |
554 | 0 | return 0; |
555 | | |
556 | 9.60k | d = down; |
557 | | |
558 | 21.3k | while ((u = _asn1_find_up (d)) != NULL && u != d) |
559 | 11.7k | { |
560 | 11.7k | if (u == up_cand) |
561 | 1 | return 1; |
562 | 11.7k | d = u; |
563 | 11.7k | } |
564 | | |
565 | 9.60k | return 0; |
566 | 9.60k | } |
567 | | |
568 | | /******************************************************************/ |
569 | | /* Function : _asn1_delete_node_from_list */ |
570 | | /* Description: deletes the list element given */ |
571 | | /******************************************************************/ |
572 | | void |
573 | | _asn1_delete_node_from_list (list_type *list, asn1_node node) |
574 | 10.0k | { |
575 | 10.0k | list_type *p = list; |
576 | | |
577 | 1.07M | while (p) |
578 | 1.06M | { |
579 | 1.06M | if (p->node == node) |
580 | 10.0k | p->node = NULL; |
581 | 1.06M | p = p->next; |
582 | 1.06M | } |
583 | 10.0k | } |
584 | | |
585 | | /******************************************************************/ |
586 | | /* Function : _asn1_delete_list */ |
587 | | /* Description: deletes the list elements (not the elements */ |
588 | | /* pointed by them). */ |
589 | | /******************************************************************/ |
590 | | void |
591 | | _asn1_delete_list (list_type *e_list) |
592 | 891 | { |
593 | 891 | list_type *p; |
594 | | |
595 | 37.6k | while (e_list) |
596 | 36.7k | { |
597 | 36.7k | p = e_list; |
598 | 36.7k | e_list = e_list->next; |
599 | 36.7k | free (p); |
600 | 36.7k | } |
601 | 891 | } |
602 | | |
603 | | /******************************************************************/ |
604 | | /* Function : _asn1_delete_list_and nodes */ |
605 | | /* Description: deletes the list elements and the elements */ |
606 | | /* pointed by them. */ |
607 | | /******************************************************************/ |
608 | | void |
609 | | _asn1_delete_list_and_nodes (list_type *e_list) |
610 | 2.45k | { |
611 | 2.45k | list_type *p; |
612 | | |
613 | 82.3k | while (e_list) |
614 | 79.8k | { |
615 | 79.8k | p = e_list; |
616 | 79.8k | e_list = e_list->next; |
617 | 79.8k | _asn1_remove_node (p->node, 0); |
618 | 79.8k | free (p); |
619 | 79.8k | } |
620 | 2.45k | } |
621 | | |
622 | | |
623 | | char * |
624 | | _asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) |
625 | 4.47M | { |
626 | 4.47M | uint64_t d, r; |
627 | 4.47M | char temp[LTOSTR_MAX_SIZE]; |
628 | 4.47M | int count, k, start; |
629 | 4.47M | uint64_t val; |
630 | | |
631 | 4.47M | if (v < 0) |
632 | 5.63k | { |
633 | 5.63k | str[0] = '-'; |
634 | 5.63k | start = 1; |
635 | 5.63k | val = -((uint64_t) v); |
636 | 5.63k | } |
637 | 4.47M | else |
638 | 4.47M | { |
639 | 4.47M | val = v; |
640 | 4.47M | start = 0; |
641 | 4.47M | } |
642 | | |
643 | 4.47M | count = 0; |
644 | 4.47M | do |
645 | 4.86M | { |
646 | 4.86M | d = val / 10; |
647 | 4.86M | r = val - d * 10; |
648 | 4.86M | temp[start + count] = '0' + (char) r; |
649 | 4.86M | count++; |
650 | 4.86M | val = d; |
651 | 4.86M | } |
652 | 4.86M | while (val && ((start + count) < LTOSTR_MAX_SIZE - 1)); |
653 | | |
654 | 9.34M | for (k = 0; k < count; k++) |
655 | 4.86M | str[k + start] = temp[start + count - k - 1]; |
656 | 4.47M | str[count + start] = 0; |
657 | 4.47M | return str; |
658 | 4.47M | } |
659 | | |
660 | | |
661 | | /******************************************************************/ |
662 | | /* Function : _asn1_change_integer_value */ |
663 | | /* Description: converts into DER coding the value assign to an */ |
664 | | /* INTEGER constant. */ |
665 | | /* Parameters: */ |
666 | | /* node: root of an ASN1element. */ |
667 | | /* Return: */ |
668 | | /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ |
669 | | /* otherwise ASN1_SUCCESS */ |
670 | | /******************************************************************/ |
671 | | int |
672 | | _asn1_change_integer_value (asn1_node node) |
673 | 1.14k | { |
674 | 1.14k | asn1_node p; |
675 | 1.14k | unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; |
676 | 1.14k | unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1]; |
677 | 1.14k | int len; |
678 | | |
679 | 1.14k | if (node == NULL) |
680 | 0 | return ASN1_ELEMENT_NOT_FOUND; |
681 | | |
682 | 1.14k | p = node; |
683 | 21.6k | while (p) |
684 | 20.4k | { |
685 | 20.4k | if ((type_field (p->type) == ASN1_ETYPE_INTEGER) |
686 | 20.4k | && (p->type & CONST_ASSIGN)) |
687 | 2.48k | { |
688 | 2.48k | if (p->value) |
689 | 2.41k | { |
690 | 2.41k | _asn1_convert_integer (p->value, val, sizeof (val), &len); |
691 | 2.41k | asn1_octet_der (val, len, val2, &len); |
692 | 2.41k | _asn1_set_value (p, val2, len); |
693 | 2.41k | } |
694 | 2.48k | } |
695 | | |
696 | 20.4k | if (p->down) |
697 | 7.30k | { |
698 | 7.30k | p = p->down; |
699 | 7.30k | } |
700 | 13.1k | else |
701 | 13.1k | { |
702 | 13.1k | if (p == node) |
703 | 120 | p = NULL; |
704 | 13.0k | else if (p->right) |
705 | 7.97k | p = p->right; |
706 | 5.06k | else |
707 | 5.06k | { |
708 | 7.30k | while (1) |
709 | 7.30k | { |
710 | 7.30k | p = _asn1_find_up (p); |
711 | 7.30k | if (p == node) |
712 | 1.02k | { |
713 | 1.02k | p = NULL; |
714 | 1.02k | break; |
715 | 1.02k | } |
716 | 6.27k | if (p && p->right) |
717 | 4.04k | { |
718 | 4.04k | p = p->right; |
719 | 4.04k | break; |
720 | 4.04k | } |
721 | 6.27k | } |
722 | 5.06k | } |
723 | 13.1k | } |
724 | 20.4k | } |
725 | | |
726 | 1.14k | return ASN1_SUCCESS; |
727 | 1.14k | } |
728 | | |
729 | 65.4k | #define MAX_CONSTANTS 1024 |
730 | | /******************************************************************/ |
731 | | /* Function : _asn1_expand_object_id */ |
732 | | /* Description: expand the IDs of an OBJECT IDENTIFIER constant. */ |
733 | | /* Parameters: */ |
734 | | /* list: root of an object list */ |
735 | | /* node: root of an ASN1 element. */ |
736 | | /* Return: */ |
737 | | /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ |
738 | | /* otherwise ASN1_SUCCESS */ |
739 | | /******************************************************************/ |
740 | | int |
741 | | _asn1_expand_object_id (list_type **list, asn1_node node) |
742 | 1.14k | { |
743 | 1.14k | asn1_node p, p2, p3, p4, p5; |
744 | 1.14k | char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1]; |
745 | 1.14k | int move, tlen, tries; |
746 | 1.14k | unsigned max_constants; |
747 | | |
748 | 1.14k | if (node == NULL) |
749 | 0 | return ASN1_ELEMENT_NOT_FOUND; |
750 | | |
751 | 1.14k | _asn1_str_cpy (name_root, sizeof (name_root), node->name); |
752 | | |
753 | 1.14k | p = node; |
754 | 1.14k | move = DOWN; |
755 | 1.14k | tries = 0; |
756 | | |
757 | 46.3k | while (!((p == node) && (move == UP))) |
758 | 45.4k | { |
759 | 45.4k | if (move != UP) |
760 | 40.5k | { |
761 | 40.5k | if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) |
762 | 40.5k | && (p->type & CONST_ASSIGN)) |
763 | 12.9k | { |
764 | 12.9k | p2 = p->down; |
765 | 12.9k | if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) |
766 | 10.7k | { |
767 | 10.7k | if (p2->value && !c_isdigit (p2->value[0])) |
768 | 9.69k | { |
769 | 9.69k | _asn1_str_cpy (name2, sizeof (name2), name_root); |
770 | 9.69k | _asn1_str_cat (name2, sizeof (name2), "."); |
771 | 9.69k | _asn1_str_cat (name2, sizeof (name2), |
772 | 9.69k | (char *) p2->value); |
773 | 9.69k | p3 = asn1_find_node (node, name2); |
774 | 9.69k | if (!p3 || _asn1_is_up (p2, p3) || |
775 | 9.69k | (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || |
776 | 9.69k | !(p3->type & CONST_ASSIGN)) |
777 | 120 | return ASN1_ELEMENT_NOT_FOUND; |
778 | | |
779 | 9.57k | _asn1_set_down (p, p2->right); |
780 | 9.57k | if (p2->down) |
781 | 85 | _asn1_delete_structure (*list, &p2->down, 0); |
782 | 9.57k | _asn1_delete_node_from_list (*list, p2); |
783 | 9.57k | _asn1_remove_node (p2, 0); |
784 | 9.57k | p2 = p; |
785 | 9.57k | p4 = p3->down; |
786 | 9.57k | max_constants = 0; |
787 | 79.0k | while (p4) |
788 | 69.5k | { |
789 | 69.5k | if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) |
790 | 65.4k | { |
791 | 65.4k | max_constants++; |
792 | 65.4k | if (max_constants == MAX_CONSTANTS) |
793 | 18 | return ASN1_RECURSION; |
794 | | |
795 | 65.3k | p5 = |
796 | 65.3k | _asn1_add_single_node (ASN1_ETYPE_CONSTANT); |
797 | 65.3k | _asn1_set_name (p5, p4->name); |
798 | 65.3k | if (p4->value) |
799 | 60.0k | { |
800 | 60.0k | tlen = _asn1_strlen (p4->value); |
801 | 60.0k | if (tlen > 0) |
802 | 58.6k | _asn1_set_value (p5, p4->value, tlen + 1); |
803 | 60.0k | } |
804 | 65.3k | _asn1_add_static_node2 (list, p5); |
805 | | |
806 | 65.3k | if (p2 == p) |
807 | 5.82k | { |
808 | 5.82k | _asn1_set_right (p5, p->down); |
809 | 5.82k | _asn1_set_down (p, p5); |
810 | 5.82k | } |
811 | 59.5k | else |
812 | 59.5k | { |
813 | 59.5k | _asn1_set_right (p5, p2->right); |
814 | 59.5k | _asn1_set_right (p2, p5); |
815 | 59.5k | } |
816 | 65.3k | p2 = p5; |
817 | 65.3k | } |
818 | 69.5k | p4 = p4->right; |
819 | 69.5k | } |
820 | 9.56k | move = DOWN; |
821 | | |
822 | 9.56k | tries++; |
823 | 9.56k | if (tries >= EXPAND_OBJECT_ID_MAX_RECURSION) |
824 | 87 | return ASN1_RECURSION; |
825 | | |
826 | 9.47k | continue; |
827 | 9.56k | } |
828 | 10.7k | } |
829 | 12.9k | } |
830 | 30.8k | move = DOWN; |
831 | 30.8k | } |
832 | 4.95k | else |
833 | 4.95k | move = RIGHT; |
834 | | |
835 | 35.7k | tries = 0; |
836 | 35.7k | if (move == DOWN) |
837 | 30.8k | { |
838 | 30.8k | if (p->down) |
839 | 5.94k | p = p->down; |
840 | 24.8k | else |
841 | 24.8k | move = RIGHT; |
842 | 30.8k | } |
843 | | |
844 | 35.7k | if (p == node) |
845 | 120 | { |
846 | 120 | move = UP; |
847 | 120 | continue; |
848 | 120 | } |
849 | | |
850 | 35.6k | if (move == RIGHT) |
851 | 29.7k | { |
852 | 29.7k | if (p && p->right) |
853 | 23.9k | p = p->right; |
854 | 5.75k | else |
855 | 5.75k | move = UP; |
856 | 29.7k | } |
857 | 35.6k | if (move == UP) |
858 | 5.75k | p = _asn1_find_up (p); |
859 | 35.6k | } |
860 | | |
861 | | /*******************************/ |
862 | | /* expand DEFAULT */ |
863 | | /*******************************/ |
864 | 921 | p = node; |
865 | 921 | move = DOWN; |
866 | | |
867 | 34.8k | while (!((p == node) && (move == UP))) |
868 | 33.9k | { |
869 | 33.9k | if (move != UP) |
870 | 29.1k | { |
871 | 29.1k | if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && |
872 | 29.1k | (p->type & CONST_DEFAULT)) |
873 | 1.93k | { |
874 | 1.93k | p2 = p->down; |
875 | 1.93k | if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) |
876 | 1.49k | { |
877 | 1.49k | _asn1_str_cpy (name2, sizeof (name2), name_root); |
878 | 1.49k | _asn1_str_cat (name2, sizeof (name2), "."); |
879 | 1.49k | if (p2->value) |
880 | 1.11k | _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); |
881 | 1.49k | p3 = asn1_find_node (node, name2); |
882 | 1.49k | if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) |
883 | 1.49k | || !(p3->type & CONST_ASSIGN)) |
884 | 27 | return ASN1_ELEMENT_NOT_FOUND; |
885 | 1.46k | p4 = p3->down; |
886 | 1.46k | name2[0] = 0; |
887 | 7.03k | while (p4) |
888 | 5.57k | { |
889 | 5.57k | if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) |
890 | 3.32k | { |
891 | 3.32k | if (p4->value == NULL) |
892 | 3 | return ASN1_VALUE_NOT_FOUND; |
893 | | |
894 | 3.31k | if (name2[0]) |
895 | 2.09k | _asn1_str_cat (name2, sizeof (name2), "."); |
896 | 3.31k | _asn1_str_cat (name2, sizeof (name2), |
897 | 3.31k | (char *) p4->value); |
898 | 3.31k | } |
899 | 5.56k | p4 = p4->right; |
900 | 5.56k | } |
901 | 1.46k | tlen = strlen (name2); |
902 | 1.46k | if (tlen > 0) |
903 | 943 | _asn1_set_value (p2, name2, tlen + 1); |
904 | 1.46k | } |
905 | 1.93k | } |
906 | 29.1k | move = DOWN; |
907 | 29.1k | } |
908 | 4.84k | else |
909 | 4.84k | move = RIGHT; |
910 | | |
911 | 33.9k | if (move == DOWN) |
912 | 29.1k | { |
913 | 29.1k | if (p->down) |
914 | 5.61k | p = p->down; |
915 | 23.4k | else |
916 | 23.4k | move = RIGHT; |
917 | 29.1k | } |
918 | | |
919 | 33.9k | if (p == node) |
920 | 120 | { |
921 | 120 | move = UP; |
922 | 120 | continue; |
923 | 120 | } |
924 | | |
925 | 33.8k | if (move == RIGHT) |
926 | 28.2k | { |
927 | 28.2k | if (p && p->right) |
928 | 22.6k | p = p->right; |
929 | 5.61k | else |
930 | 5.61k | move = UP; |
931 | 28.2k | } |
932 | 33.8k | if (move == UP) |
933 | 5.61k | p = _asn1_find_up (p); |
934 | 33.8k | } |
935 | | |
936 | 891 | return ASN1_SUCCESS; |
937 | 921 | } |
938 | | |
939 | | |
940 | | /******************************************************************/ |
941 | | /* Function : _asn1_type_set_config */ |
942 | | /* Description: sets the CONST_SET and CONST_NOT_USED properties */ |
943 | | /* in the fields of the SET elements. */ |
944 | | /* Parameters: */ |
945 | | /* node: root of an ASN1 element. */ |
946 | | /* Return: */ |
947 | | /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ |
948 | | /* otherwise ASN1_SUCCESS */ |
949 | | /******************************************************************/ |
950 | | int |
951 | | _asn1_type_set_config (asn1_node node) |
952 | 964 | { |
953 | 964 | asn1_node p, p2; |
954 | 964 | int move; |
955 | | |
956 | 964 | if (node == NULL) |
957 | 0 | return ASN1_ELEMENT_NOT_FOUND; |
958 | | |
959 | 964 | p = node; |
960 | 964 | move = DOWN; |
961 | | |
962 | 22.3k | while (!((p == node) && (move == UP))) |
963 | 21.3k | { |
964 | 21.3k | if (move != UP) |
965 | 16.8k | { |
966 | 16.8k | if (type_field (p->type) == ASN1_ETYPE_SET) |
967 | 426 | { |
968 | 426 | p2 = p->down; |
969 | 4.13k | while (p2) |
970 | 3.70k | { |
971 | 3.70k | if (type_field (p2->type) != ASN1_ETYPE_TAG) |
972 | 3.47k | p2->type |= CONST_SET | CONST_NOT_USED; |
973 | 3.70k | p2 = p2->right; |
974 | 3.70k | } |
975 | 426 | } |
976 | 16.8k | move = DOWN; |
977 | 16.8k | } |
978 | 4.54k | else |
979 | 4.54k | move = RIGHT; |
980 | | |
981 | 21.3k | if (move == DOWN) |
982 | 16.8k | { |
983 | 16.8k | if (p->down) |
984 | 5.51k | p = p->down; |
985 | 11.3k | else |
986 | 11.3k | move = RIGHT; |
987 | 16.8k | } |
988 | | |
989 | 21.3k | if (p == node) |
990 | 0 | { |
991 | 0 | move = UP; |
992 | 0 | continue; |
993 | 0 | } |
994 | | |
995 | 21.3k | if (move == RIGHT) |
996 | 15.8k | { |
997 | 15.8k | if (p && p->right) |
998 | 10.3k | p = p->right; |
999 | 5.51k | else |
1000 | 5.51k | move = UP; |
1001 | 15.8k | } |
1002 | 21.3k | if (move == UP) |
1003 | 5.51k | p = _asn1_find_up (p); |
1004 | 21.3k | } |
1005 | | |
1006 | 964 | return ASN1_SUCCESS; |
1007 | 964 | } |
1008 | | |
1009 | | |
1010 | | /******************************************************************/ |
1011 | | /* Function : _asn1_check_identifier */ |
1012 | | /* Description: checks the definitions of all the identifiers */ |
1013 | | /* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */ |
1014 | | /* The _asn1_identifierMissing global variable is filled if */ |
1015 | | /* necessary. */ |
1016 | | /* Parameters: */ |
1017 | | /* node: root of an ASN1 element. */ |
1018 | | /* Return: */ |
1019 | | /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ |
1020 | | /* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */ |
1021 | | /* otherwise ASN1_SUCCESS */ |
1022 | | /******************************************************************/ |
1023 | | int |
1024 | | _asn1_check_identifier (asn1_node_const node) |
1025 | 1.96k | { |
1026 | 1.96k | asn1_node_const p, p2; |
1027 | 1.96k | char name2[ASN1_MAX_NAME_SIZE * 2 + 2]; |
1028 | | |
1029 | 1.96k | if (node == NULL) |
1030 | 6 | return ASN1_ELEMENT_NOT_FOUND; |
1031 | | |
1032 | 1.95k | p = node; |
1033 | 23.5k | while (p) |
1034 | 22.3k | { |
1035 | 22.3k | if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER) |
1036 | 2.44k | { |
1037 | 2.44k | _asn1_str_cpy (name2, sizeof (name2), node->name); |
1038 | 2.44k | _asn1_str_cat (name2, sizeof (name2), "."); |
1039 | 2.44k | _asn1_str_cat (name2, sizeof (name2), (char *) p->value); |
1040 | 2.44k | p2 = asn1_find_node (node, name2); |
1041 | 2.44k | if (p2 == NULL) |
1042 | 707 | { |
1043 | 707 | if (p->value) |
1044 | 707 | _asn1_str_cpy (_asn1_identifierMissing, |
1045 | 707 | sizeof (_asn1_identifierMissing), |
1046 | 707 | (char *) p->value); |
1047 | 0 | else |
1048 | 0 | _asn1_strcpy (_asn1_identifierMissing, "(null)"); |
1049 | 707 | return ASN1_IDENTIFIER_NOT_FOUND; |
1050 | 707 | } |
1051 | 2.44k | } |
1052 | 19.9k | else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && |
1053 | 19.9k | (p->type & CONST_DEFAULT)) |
1054 | 2.09k | { |
1055 | 2.09k | p2 = p->down; |
1056 | 2.09k | if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) |
1057 | 1.57k | { |
1058 | 1.57k | _asn1_str_cpy (name2, sizeof (name2), node->name); |
1059 | 1.57k | if (p2->value) |
1060 | 1.13k | { |
1061 | 1.13k | _asn1_str_cat (name2, sizeof (name2), "."); |
1062 | 1.13k | _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); |
1063 | 1.13k | _asn1_str_cpy (_asn1_identifierMissing, |
1064 | 1.13k | sizeof (_asn1_identifierMissing), |
1065 | 1.13k | (char *) p2->value); |
1066 | 1.13k | } |
1067 | 439 | else |
1068 | 439 | _asn1_strcpy (_asn1_identifierMissing, "(null)"); |
1069 | | |
1070 | 1.57k | p2 = asn1_find_node (node, name2); |
1071 | 1.57k | if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) || |
1072 | 1.57k | !(p2->type & CONST_ASSIGN)) |
1073 | 39 | return ASN1_IDENTIFIER_NOT_FOUND; |
1074 | 1.53k | else |
1075 | 1.53k | _asn1_identifierMissing[0] = 0; |
1076 | 1.57k | } |
1077 | 2.09k | } |
1078 | 17.8k | else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && |
1079 | 17.8k | (p->type & CONST_ASSIGN)) |
1080 | 2.58k | { |
1081 | 2.58k | p2 = p->down; |
1082 | 2.58k | if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) |
1083 | 2.26k | { |
1084 | 2.26k | if (p2->value && !c_isdigit (p2->value[0])) |
1085 | 1.89k | { |
1086 | 1.89k | _asn1_str_cpy (name2, sizeof (name2), node->name); |
1087 | 1.89k | _asn1_str_cat (name2, sizeof (name2), "."); |
1088 | 1.89k | _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); |
1089 | 1.89k | _asn1_str_cpy (_asn1_identifierMissing, |
1090 | 1.89k | sizeof (_asn1_identifierMissing), |
1091 | 1.89k | (char *) p2->value); |
1092 | | |
1093 | 1.89k | p2 = asn1_find_node (node, name2); |
1094 | 1.89k | if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) |
1095 | 1.89k | || !(p2->type & CONST_ASSIGN)) |
1096 | 64 | return ASN1_IDENTIFIER_NOT_FOUND; |
1097 | 1.82k | else |
1098 | 1.82k | _asn1_identifierMissing[0] = 0; |
1099 | 1.89k | } |
1100 | 2.26k | } |
1101 | 2.58k | } |
1102 | | |
1103 | 21.5k | if (p->down) |
1104 | 7.87k | { |
1105 | 7.87k | p = p->down; |
1106 | 7.87k | } |
1107 | 13.6k | else if (p->right) |
1108 | 8.49k | p = p->right; |
1109 | 5.20k | else |
1110 | 5.20k | { |
1111 | 7.55k | while (p) |
1112 | 7.43k | { |
1113 | 7.43k | p = _asn1_find_up (p); |
1114 | 7.43k | if (p == node) |
1115 | 1.02k | { |
1116 | 1.02k | p = NULL; |
1117 | 1.02k | break; |
1118 | 1.02k | } |
1119 | 6.41k | if (p && p->right) |
1120 | 4.05k | { |
1121 | 4.05k | p = p->right; |
1122 | 4.05k | break; |
1123 | 4.05k | } |
1124 | 6.41k | } |
1125 | 5.20k | } |
1126 | 21.5k | } |
1127 | | |
1128 | 1.14k | return ASN1_SUCCESS; |
1129 | 1.95k | } |
1130 | | |
1131 | | |
1132 | | /******************************************************************/ |
1133 | | /* Function : _asn1_set_default_tag */ |
1134 | | /* Description: sets the default IMPLICIT or EXPLICIT property in */ |
1135 | | /* the tagged elements that don't have this declaration. */ |
1136 | | /* Parameters: */ |
1137 | | /* node: pointer to a DEFINITIONS element. */ |
1138 | | /* Return: */ |
1139 | | /* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */ |
1140 | | /* a DEFINITIONS element, */ |
1141 | | /* otherwise ASN1_SUCCESS */ |
1142 | | /******************************************************************/ |
1143 | | int |
1144 | | _asn1_set_default_tag (asn1_node node) |
1145 | 964 | { |
1146 | 964 | asn1_node p; |
1147 | | |
1148 | 964 | if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS)) |
1149 | 0 | return ASN1_ELEMENT_NOT_FOUND; |
1150 | | |
1151 | 964 | p = node; |
1152 | 17.7k | while (p) |
1153 | 16.8k | { |
1154 | 16.8k | if ((type_field (p->type) == ASN1_ETYPE_TAG) && |
1155 | 16.8k | !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT)) |
1156 | 1.13k | { |
1157 | 1.13k | if (node->type & CONST_EXPLICIT) |
1158 | 565 | p->type |= CONST_EXPLICIT; |
1159 | 566 | else |
1160 | 566 | p->type |= CONST_IMPLICIT; |
1161 | 1.13k | } |
1162 | | |
1163 | 16.8k | if (p->down) |
1164 | 5.51k | { |
1165 | 5.51k | p = p->down; |
1166 | 5.51k | } |
1167 | 11.3k | else if (p->right) |
1168 | 6.89k | p = p->right; |
1169 | 4.42k | else |
1170 | 4.42k | { |
1171 | 5.51k | while (1) |
1172 | 5.51k | { |
1173 | 5.51k | p = _asn1_find_up (p); |
1174 | 5.51k | if (p == node) |
1175 | 964 | { |
1176 | 964 | p = NULL; |
1177 | 964 | break; |
1178 | 964 | } |
1179 | 4.54k | if (p && p->right) |
1180 | 3.45k | { |
1181 | 3.45k | p = p->right; |
1182 | 3.45k | break; |
1183 | 3.45k | } |
1184 | 4.54k | } |
1185 | 4.42k | } |
1186 | 16.8k | } |
1187 | | |
1188 | 964 | return ASN1_SUCCESS; |
1189 | 964 | } |