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