5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 - 2007 Pekka Riikonen
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.
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.
24 #define SILC_ASN1_STACK(stack, asn1) stack ? stack : asn1->orig_stack
26 /************************** ASN.1 Decoder routines **************************/
28 /* Internal SEQUENCE OF and SET OF decoder. This is used only when decoding
29 these two special tags. Other normal ASN.1 decoding is done in the
30 silc_asn1_decoder function. This parses the sequence of types and returns
31 them as raw BER buffers in an array of SilcBuffers. */
33 static SilcBool silc_asn1_decoder_sof(SilcAsn1 asn1, SilcBuffer src)
39 SilcUInt32 *retc, rtag;
40 const unsigned char *rdata;
41 SilcUInt32 rdata_len, len = 0, *choice_index = NULL;
42 SilcBool found = FALSE, rindef, chosen = FALSE;
44 struct SilcAsn1SofStruct {
46 struct SilcAsn1SofStruct *next;
49 SILC_LOG_DEBUG(("Decoding sequence of types"));
51 silc_list_init(types, struct SilcAsn1SofStruct, next);
53 /* Take the return arguments */
54 retb = va_arg(asn1->ap, SilcBuffer *);
55 retc = va_arg(asn1->ap, SilcUInt32 *);
59 /* Get the sequence type(s). If the type is CHOICE tag then the sequence
60 may include multiple different types. All types are considered
61 separately. If CHOICE is not given then only single type is expected. */
62 type = va_arg(asn1->ap, SilcUInt32);
63 assert(type != SILC_ASN1_END);
65 if (type == SILC_ASN1_TAG_CHOICE) {
66 /* The sequence may consist of the following types. */
67 choice_index = va_arg(asn1->ap, SilcUInt32 *);
70 type = va_arg(asn1->ap, SilcUInt32);
71 assert(type != SILC_ASN1_END);
72 while (type != SILC_ASN1_END) {
73 t = silc_smalloc(SILC_ASN1_STACK(asn1->stack1, asn1), sizeof(*t));
77 silc_list_add(types, t);
79 SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
80 silc_asn1_tag_name(type), type));
82 type = va_arg(asn1->ap, SilcUInt32);
85 /* The sequence consists of this type. */
86 t = silc_smalloc(SILC_ASN1_STACK(asn1->stack1, asn1), sizeof(*t));
90 silc_list_add(types, t);
92 SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
93 silc_asn1_tag_name(type), type));
96 /* END marker for the sequence */
97 type = va_arg(asn1->ap, SilcUInt32);
98 assert(type == SILC_ASN1_END);
100 /* Decode the SEQUENCE or SET */
101 ret = silc_ber_decode(src, NULL, NULL, &rtag, &rdata,
102 &rdata_len, &rindef, &len);
104 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
107 if (rtag != SILC_ASN1_TAG_SEQUENCE && rtag != SILC_ASN1_TAG_SET) {
108 SILC_LOG_DEBUG(("Invalid sequence of/set of"));
111 silc_buffer_pull(src, len);
113 while (silc_buffer_len(src)) {
114 /* Decode the BER data. */
115 ret = silc_ber_decode(src, NULL, NULL, &rtag, &rdata,
116 &rdata_len, &rindef, &len);
118 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
122 /* Now check the type(s) that it is supposed to be */
124 silc_list_start(types);
125 while ((t = silc_list_get(types)) != SILC_LIST_END) {
126 if (choice_index && !chosen)
132 *retb = silc_srealloc(SILC_ASN1_STACK(asn1->stack1, asn1),
133 sizeof(**retb) * (*retc), *retb,
134 sizeof(**retb) * (*retc + 1));
138 SILC_LOG_DEBUG(("Decode %s [%d] from sequence of types",
139 silc_asn1_tag_name(rtag), rtag));
141 /* Data is duplicated only if SILC_ASN1_ALLOC flag is set, ie.
142 asn1->stack1 == NULL */
144 rdata = silc_smemdup(asn1->orig_stack, rdata - len, rdata_len + len);
150 silc_buffer_set(&(*retb)[*retc], (unsigned char *)rdata, rdata_len);
157 /* If type was not found we consider it the end of the sequence */
162 silc_buffer_pull(src, rdata_len);
165 SILC_LOG_DEBUG(("Decoded %d types", *retc));
170 silc_list_start(types);
171 while ((t = silc_list_get(types)) != SILC_LIST_END)
172 silc_sfree(asn1->orig_stack, t);
178 /* Macro for decoder to get argument for a type. If OPTIONAL option is
179 set then the argument is a pointer to the type pointer. The `type'
180 must be a non-pointer type, eg. int, SilcBufferStruct. */
181 #define SILC_ASN1_VAD(asn1, opts, type, name) \
183 if ((opts) & SILC_ASN1_OPTIONAL && !choice) { \
184 name = va_arg(asn1->ap, type **); \
192 *name = silc_scalloc(SILC_ASN1_STACK(stack1, asn1), \
193 1, sizeof(**name)); \
197 type *name ## tmp = va_arg(asn1->ap, type *); \
198 if (choice && found && !len) \
200 if (name ## tmp == NULL) \
202 name = &name ## tmp; \
205 /* Same as SILC_ASN1_VAD but for unsigned char and SilcUInt32 */
206 #define SILC_ASN1_VAD_UCHAR(asn1, opts, type, name, namelen) \
207 type **name = va_arg(asn1->ap, type **); \
208 SilcUInt32 *namelen = va_arg(asn1->ap, SilcUInt32 *); \
209 if (choice && found && !len) \
219 /* Same as SILC_ASN1_VAD but for char only */
220 #define SILC_ASN1_VAD_CHAR(asn1, opts, type, name) \
221 type **name = va_arg(asn1->ap, type **); \
222 if (choice && found && !len) \
232 #define SILC_ASN1_VA_FREE(opts, name) \
233 if ((opts) & SILC_ASN1_OPTIONAL) \
234 silc_sfree(SILC_ASN1_STACK(stack1, asn1), *name);
236 /* Decodes string to UTF-8 string which is our internal representation
238 #define SILC_ASN1_DECODE_STRING(enc, s, s_len) \
239 *s_len = silc_utf8_encoded_len(rdata, rdata_len, (enc)); \
241 SILC_LOG_DEBUG(("Malformed %d string value", (enc))); \
245 *s = silc_smalloc(SILC_ASN1_STACK(stack1, asn1), *s_len + 1); \
247 silc_utf8_encode(rdata, rdata_len, (enc), *s, *s_len); \
248 (*s)[*s_len] = '\0'; \
252 /* Internal ASN.1 decoder. The `type', `tag' and `opts' are the first
253 arguments (either very first or first for recursion) for a type.
254 The `depth' includes the current depth of recursion. */
257 silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type,
258 SilcAsn1Tag tag, SilcBerClass ber_class,
259 SilcAsn1Options opts, SilcBuffer src, SilcUInt32 depth,
262 unsigned char *ptr = src->data;
264 SilcAsn1Options ropts;
266 SilcBerEncoding renc;
267 SilcUInt32 len = 0, rtag;
268 SilcBool ret, indef, rindef, found = FALSE, choice = FALSE;
269 SilcBool choice_found = FALSE;
270 const unsigned char *rdata;
271 SilcUInt32 rdata_len, *choice_index = NULL;
275 char sp[SILC_ASN1_RECURSION_DEPTH + 1];
276 memset(sp, 0, sizeof(sp));
278 memset(sp, 32, depth);
279 #endif /* SILC_DEBUG */
281 if (depth >= SILC_ASN1_RECURSION_DEPTH) {
282 SILC_LOG_DEBUG(("Maximum recursion depth reached"));
288 /* If requested type is SEQUENCE OF or SET OF then we decode the sequence
289 of types separately in an own decoder which returns array of buffers. */
290 if (type == SILC_ASN1_TAG_SEQUENCE_OF) {
291 /* Decode the sequence */
292 if (!silc_asn1_decoder_sof(asn1, src)) {
293 SILC_LOG_DEBUG(("Error decoding SEQUENCE OF"));
298 /* Continue with rest of the decodings if any */
299 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
300 if (type == SILC_ASN1_END) {
306 /* Get length encoding */
307 indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
309 /* By default UNIVERSAL is implied unless the following conditions
310 are met when CONTEXT will apply. For SILC_ASN1_TAG_ANY_PRIMITIVE
311 the class is changed only if flags dictate it. */
312 if (ber_class == SILC_BER_CLASS_UNIVERSAL) {
313 if (type == SILC_ASN1_TAG_ANY_PRIMITIVE) {
314 if (opts & SILC_ASN1_IMPLICIT ||
315 opts & SILC_ASN1_EXPLICIT)
316 ber_class = SILC_BER_CLASS_CONTEXT;
319 opts & SILC_ASN1_IMPLICIT ||
320 opts & SILC_ASN1_EXPLICIT)
321 ber_class = SILC_BER_CLASS_CONTEXT;
325 /* Short integer is actually big integer in the BER data, so handle
327 if (type == SILC_ASN1_TAG_SHORT_INTEGER && type == tag)
328 tag = SILC_ASN1_TAG_INTEGER;
330 /* Now decode a BER encoded block from the source buffer. It must be
331 exactly the same user is expecting. */
332 ret = silc_ber_decode(src, &rclass, &renc, &rtag, &rdata,
333 &rdata_len, &rindef, &len);
335 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
339 /* Now verify that the decoded BER is the one user wanted to get. If
340 requested type is OPTIONAL, then ignore all the sanity tests. The
341 while() loop is for re-considering OPTIONAL types without parsing
342 new BER object. For CHOICE (tag) all the choice considerations are
343 also done within the while(). */
346 /* If type is CHOICE then at least one type must match before next
347 SILC_ASN1_END is reached. The considerations act interally as
348 having OPTIONAL flag set, except that at the end one must have
350 if (type == SILC_ASN1_TAG_CHOICE) {
351 choice_index = va_arg(asn1->ap, SilcUInt32 *);
354 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
355 opts |= SILC_ASN1_OPTIONAL;
361 ("%04d: %sDecode %s [%d] %s %s %s %s", depth, sp[0] ? sp : "",
362 silc_asn1_tag_name(type), rtag,
363 rclass == SILC_BER_CLASS_UNIVERSAL ? "univ" :
364 rclass == SILC_BER_CLASS_APPLICATION ? "appl" :
365 rclass == SILC_BER_CLASS_CONTEXT ? "cont" : "priv",
366 renc == SILC_BER_ENC_PRIMITIVE ? "primit" : "constr",
367 rindef ? "indef" : "defin",
368 choice ? "choice" : opts & SILC_ASN1_OPTIONAL ? "option" : ""));
369 #endif /* SILC_DEBUG */
371 if (type != SILC_ASN1_TAG_ANY && tag != rtag) {
372 if (!(opts & SILC_ASN1_OPTIONAL)) {
373 SILC_LOG_DEBUG(("Invalid ASN.1 tag %u, expected %u", rtag, tag));
379 } else if (ber_class != rclass) {
380 if (!(opts & SILC_ASN1_OPTIONAL)) {
381 SILC_LOG_DEBUG(("Invalid ASN.1 class %d, expected %d",
388 } else if (!(opts & SILC_ASN1_EXPLICIT) && indef != rindef) {
389 SILC_LOG_DEBUG(("Invalid ASN.1 length encoding %s, expected %s",
390 rindef ? "indefinite" : "definite",
391 indef ? "indefinite" : "definite"));
394 } else if (rindef && renc == SILC_BER_ENC_PRIMITIVE) {
395 SILC_LOG_DEBUG(("Invalid length encoding for primitive type"));
402 /* If tagging is explicit we have additional sequence we need to decode
403 before we decode the actual underlaying type. */
404 if (opts & SILC_ASN1_EXPLICIT) {
405 silc_buffer_pull(src, len);
408 primitive = (type != SILC_ASN1_TAG_SEQUENCE &&
409 type != SILC_ASN1_TAG_SET &&
410 type != SILC_ASN1_TAG_ANY);
411 opts &= ~SILC_ASN1_EXPLICIT;
413 ret = silc_asn1_decoder(asn1, stack1, type, type,
414 SILC_BER_CLASS_UNIVERSAL, opts, src,
415 depth + 1, primitive);
425 /* Decode by the type user expects the data to be. */
428 case SILC_ASN1_TAG_ANY:
430 /* ANY is another ASN.1 node. We return the raw BER buffer as
432 SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, node);
434 *node = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1),
435 *node, len + rdata_len);
436 silc_buffer_put(*node, rdata - len, rdata_len + len);
440 case SILC_ASN1_TAG_ANY_PRIMITIVE:
442 /* ANY_PRIMITIVE returns the raw data blob of any primitive type. */
443 SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, prim);
445 *prim = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1),
447 silc_buffer_put(*prim, rdata, rdata_len);
451 case SILC_ASN1_TAG_SEQUENCE:
452 case SILC_ASN1_TAG_SET:
454 /* SEQUENCE/SET is a sequence of types. */
455 silc_buffer_pull(src, len);
458 /* Get type, tag and options for the first argument in recursion */
459 SILC_ASN1_ARGS(asn1, rtype, rtag, rclass, ropts);
461 /* Decode the sequence recursively */
462 ret = silc_asn1_decoder(asn1, SILC_ASN1_STACK(stack1, asn1),
463 rtype, rtag, rclass, ropts, src,
470 case SILC_ASN1_TAG_INTEGER:
471 case SILC_ASN1_TAG_ENUM:
473 /* Integer/enum value. */
475 SILC_ASN1_VAD(asn1, opts, SilcMPInt, intval);
478 SILC_LOG_DEBUG(("Malformed integer value"));
479 SILC_ASN1_VA_FREE(opts, intval);
484 silc_mp_sinit(SILC_ASN1_STACK(stack1, asn1), *intval);
486 /* Check whether the integer is positive or negative */
487 if (rdata[0] & 0x80) {
488 /* Negative integer stored in 1s complement.*/
489 for (i = 0; i < rdata_len; i++) {
490 silc_mp_mul_2exp(*intval, *intval, 8);
491 silc_mp_add_ui(*intval, *intval, ~rdata[i] & 0xff);
494 /* 2s complement and change sign */
496 silc_mp_set_ui(&z, 0);
497 silc_mp_add_ui(*intval, *intval, 1);
498 silc_mp_sub(*intval, &z, *intval);
502 silc_mp_bin2mp((unsigned char *)rdata, rdata_len, *intval);
508 case SILC_ASN1_TAG_SHORT_INTEGER:
512 SILC_ASN1_VAD(asn1, opts, SilcUInt32, intval);
515 SILC_LOG_DEBUG(("Malformed integer value"));
516 SILC_ASN1_VA_FREE(opts, intval);
521 silc_stack_push(SILC_ASN1_STACK(stack1, asn1), NULL);
522 silc_mp_sinit(SILC_ASN1_STACK(stack1, asn1), &z);
523 silc_mp_bin2mp((unsigned char *)rdata, rdata_len, &z);
524 *(*intval) = silc_mp_get_ui(&z);
526 silc_stack_pop(SILC_ASN1_STACK(stack1, asn1));
530 case SILC_ASN1_TAG_OID:
532 /* Object identifier */
533 SilcBufferStruct tmpb;
536 SILC_ASN1_VAD_CHAR(asn1, opts, char, oidstr);
539 SILC_LOG_DEBUG(("Malformed object identifier value"));
540 SILC_ASN1_VA_FREE(opts, oidstr);
545 /* Set two OID values */
546 memset(&tmpb, 0, sizeof(tmpb));
547 memset(tmpstr, 0, sizeof(tmpstr));
548 silc_snprintf(tmpstr, sizeof(tmpstr) - 1, "%lu.%lu",
549 (unsigned long)(rdata[0] & 0xff) / 40,
550 (unsigned long)(rdata[0] & 0xff) % 40);
551 silc_buffer_sstrformat(SILC_ASN1_STACK(stack1, asn1),
552 &tmpb, tmpstr, SILC_STR_END);
554 /* Set rest of the OID values, each octet having 7 bits of the
555 OID value with bit 8 set. An octet not having bit 8 set
556 means end of that OID value. */
557 for (i = 1; i < rdata_len; i++) {
559 while (rdata[i] & 0x80) {
561 oid |= rdata[i++] & 0x7f;
562 if (i >= rdata_len) {
563 SILC_LOG_DEBUG(("Malformed object identifier value"));
570 memset(tmpstr, 0, sizeof(tmpstr));
571 silc_snprintf(tmpstr, sizeof(tmpstr) - 1, ".%lu",
573 silc_buffer_sstrformat(SILC_ASN1_STACK(stack1, asn1),
574 &tmpb, tmpstr, SILC_STR_END);
581 case SILC_ASN1_TAG_BOOLEAN:
583 /* Decode boolean (TRUE/FALSE) value */
584 SILC_ASN1_VAD(asn1, opts, SilcBool, val);
586 if (rdata_len != 1) {
587 SILC_LOG_DEBUG(("Malformed boolean value"));
588 SILC_ASN1_VA_FREE(opts, val);
593 *(*val) = (rdata[0] == 0xff ? TRUE : FALSE);
597 case SILC_ASN1_TAG_BIT_STRING:
599 /* Bit string contains data with exact bit length of the data */
600 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, d, d_len);
603 SILC_LOG_DEBUG(("Malformed bit string value"));
604 SILC_ASN1_VA_FREE(opts, d);
609 *d = silc_smemdup(SILC_ASN1_STACK(stack1, asn1),
610 rdata + 1, rdata_len - 1);
611 *d_len = (rdata_len - 1) * 8;
615 case SILC_ASN1_TAG_NULL:
617 SILC_ASN1_VAD(asn1, opts, SilcBool, val);
619 /* Decode empty BER block */
620 if (rdata_len != 0) {
621 SILC_LOG_DEBUG(("Malformed null value"));
629 case SILC_ASN1_TAG_UTC_TIME:
631 /* Universal encoded time string */
632 SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
635 SILC_LOG_DEBUG(("Malformed UTC time value"));
636 SILC_ASN1_VA_FREE(opts, t);
641 /* Parse the time string */
642 if (!silc_time_universal(rdata, *t)) {
643 SILC_LOG_DEBUG(("Malformed UTC time value"));
651 case SILC_ASN1_TAG_GENERALIZED_TIME:
653 /* Generalized encoded time string */
654 SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
657 SILC_LOG_DEBUG(("Malformed generalized time value"));
658 SILC_ASN1_VA_FREE(opts, t);
663 /* Parse the time string */
664 if (!silc_time_generalized(rdata, *t)) {
665 SILC_LOG_DEBUG(("Malformed generalized time value"));
666 SILC_ASN1_VA_FREE(opts, t);
674 case SILC_ASN1_TAG_UTF8_STRING:
676 /* UTF-8 encoded string */
677 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
679 if (!silc_utf8_valid(rdata, rdata_len)) {
680 SILC_LOG_DEBUG(("Malformed UTF-8 string value"));
681 SILC_ASN1_VA_FREE(opts, s);
686 *s = silc_smemdup(SILC_ASN1_STACK(stack1, asn1), rdata, rdata_len);
691 case SILC_ASN1_TAG_OCTET_STRING:
693 /* Octet string. Take data as is. */
694 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
695 *s = silc_smemdup(SILC_ASN1_STACK(stack1, asn1), rdata, rdata_len);
700 case SILC_ASN1_TAG_NUMERIC_STRING:
702 /* Numerical (digit) string */
703 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
704 SILC_ASN1_DECODE_STRING(SILC_STRING_NUMERICAL, s, s_len);
708 case SILC_ASN1_TAG_PRINTABLE_STRING:
710 /* Printable string */
711 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
712 SILC_ASN1_DECODE_STRING(SILC_STRING_PRINTABLE, s, s_len);
716 case SILC_ASN1_TAG_TELETEX_STRING:
718 /* Teletex (T61) string */
719 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
720 SILC_ASN1_DECODE_STRING(SILC_STRING_TELETEX, s, s_len);
724 case SILC_ASN1_TAG_IA5_STRING:
726 /* US ASCII string */
727 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
728 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_len);
732 case SILC_ASN1_TAG_VISIBLE_STRING:
735 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
736 SILC_ASN1_DECODE_STRING(SILC_STRING_VISIBLE, s, s_len);
740 case SILC_ASN1_TAG_UNIVERSAL_STRING:
742 /* Universal (UCS-4) string */
743 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
744 SILC_ASN1_DECODE_STRING(SILC_STRING_UNIVERSAL, s, s_len);
748 case SILC_ASN1_TAG_UNRESTRICTED_STRING:
749 case SILC_ASN1_TAG_GENERAL_STRING:
751 /* Handle now unrestricted and general as 8-bit ascii, which
752 probably isn't correct. */
753 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
754 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_len);
758 case SILC_ASN1_TAG_BMP_STRING:
760 /* BMP (UCS-2) string */
761 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
762 SILC_ASN1_DECODE_STRING(SILC_STRING_BMP, s, s_len);
766 case SILC_ASN1_TAG_ODE:
767 case SILC_ASN1_TAG_ETI:
768 case SILC_ASN1_TAG_REAL:
769 case SILC_ASN1_TAG_EMBEDDED:
770 case SILC_ASN1_TAG_ROI:
771 case SILC_ASN1_TAG_VIDEOTEX_STRING:
772 case SILC_ASN1_TAG_GRAPHIC_STRING:
774 SILC_NOT_IMPLEMENTED("Unsupported ASN.1 tag");
781 SILC_LOG_DEBUG(("Invalid ASN.1 tag `%d'. Cannot decode ASN.1.",
789 /* Pull the current data from source which reveals next BER object */
790 if (found && len + rdata_len)
791 silc_buffer_pull(src, len + rdata_len);
797 /* Get next type, tag and options */
799 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
800 if (type == SILC_ASN1_END) {
803 /* No choices were found, error */
804 SILC_LOG_DEBUG(("Invalid ASN.1 choice: no choices present"));
812 SILC_LOG_DEBUG(("Found choice %s type, index %d",
813 silc_asn1_tag_name(rtype), *choice_index));
816 /* Take next type and new BER object, choices are over */
818 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
819 if (type == SILC_ASN1_END) {
826 /* SEQUENCE/SET end */
835 /* Even if the choice was found we must go through rest of
839 SILC_LOG_DEBUG(("Found choice %s type, index %d",
840 silc_asn1_tag_name(rtype), *choice_index));
843 opts |= SILC_ASN1_OPTIONAL;
847 /* Optional type not present, check next one for match */
856 SILC_LOG_DEBUG(("Error decoding type %d (depth %d)", type, depth));
860 len = src->data - ptr;
862 len = src->data - src->head;
863 silc_buffer_push(src, len);
868 SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...)
870 SilcAsn1Tag type, tag;
871 SilcAsn1Options opts;
872 SilcBerClass ber_class;
873 SilcStackFrame frame1, frame2;
874 SilcStack stack1 = NULL, stack2 = NULL, orig;
880 va_start(asn1->ap, src);
882 orig = asn1->orig_stack;
884 /* Get the first arguments and call the decoder. */
885 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
891 /* Handle internal options for decoder. */
892 if (type == SILC_ASN1_TAG_OPTS) {
893 SilcUInt32 o = va_arg(asn1->ap, SilcUInt32);
895 if (o & SILC_ASN1_ALLOC) {
896 /* User wants to alloate everything. Set the stacks to NULL so
897 that stack aware calls revert to normal allocation routines. */
898 stack1 = asn1->stack1;
899 stack2 = asn1->stack2;
902 asn1->orig_stack = orig;
905 if (o & SILC_ASN1_ACCUMUL) {
906 /* If accumul flag is not set yet, then push the stacks. */
907 if (!asn1->accumul) {
908 silc_stack_push(asn1->stack1, NULL);
909 silc_stack_push(asn1->stack2, NULL);
914 /* Take again the arguments */
915 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
917 /* No flags set, all flags will be reset. */
919 /* If accumul flag is set now pop the stack so that all accumulated
920 memory becomes free again. */
922 silc_stack_pop(asn1->stack1);
923 silc_stack_pop(asn1->stack2);
928 /* Push stacks for normal allocation from stack */
929 if (!asn1->accumul) {
930 silc_stack_push(asn1->stack1, &frame1);
931 silc_stack_push(asn1->stack2, &frame2);
935 ret = silc_asn1_decoder(asn1, asn1->stack1, type, tag, ber_class,
936 opts, src, 0, FALSE);
938 /* Pop stacks to free normal allocations from stack. They remain valid
939 for every second call to this function. */
940 if (!asn1->accumul) {
941 silc_stack_pop(asn1->stack1);
942 silc_stack_pop(asn1->stack2);
944 /* Switch the asn1->stack1 and asn1->stack2. This way next call to
945 this function does not invalidate these results. Every second call
946 invalidates the results of every second previous results. */
947 if (asn1->stack1 && asn1->stack2) {
948 stack1 = asn1->stack1;
949 asn1->stack1 = asn1->stack2;
950 asn1->stack2 = stack1;
954 if (stack1 && stack2 && !asn1->stack1 && !asn1->stack2) {
955 /* SILC_ASN1_ALLOC flag was set, restore the stacks. */
956 asn1->stack1 = stack1;
957 asn1->stack2 = stack2;
960 asn1->orig_stack = orig;