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 /************************** ASN.1 Decoder routines **************************/
26 /* Internal SEQUENCE OF and SET OF decoder. This is used only when decoding
27 these two special tags. Other normal ASN.1 decoding is done in the
28 silc_asn1_decoder function. This parses the sequence of types and returns
29 them as raw BER buffers in an array of SilcBuffers. */
31 static SilcBool silc_asn1_decoder_sof(SilcAsn1 asn1, SilcBuffer src)
37 SilcUInt32 *retc, rtag;
38 const unsigned char *rdata;
39 SilcUInt32 rdata_len, len = 0;
40 SilcBool found = FALSE, rindef;
42 struct SilcAsn1SofStruct {
44 struct SilcAsn1SofStruct *next;
47 SILC_LOG_DEBUG(("Decoding sequence of types"));
49 silc_list_init(types, struct SilcAsn1SofStruct, next);
51 /* Take the return arguments */
52 retb = va_arg(asn1->ap, SilcBuffer *);
53 retc = va_arg(asn1->ap, SilcUInt32 *);
57 /* Get the sequence type(s). If the type is CHOICE tag then the sequence
58 may include multiple different types. All types are considered
59 separately. If CHOICE is not given then only single type is expected. */
60 type = va_arg(asn1->ap, SilcUInt32);
61 assert(type != SILC_ASN1_END);
63 if (type == SILC_ASN1_TAG_CHOICE) {
64 /* The sequence may consist of the following types. */
65 type = va_arg(asn1->ap, SilcUInt32);
66 assert(type != SILC_ASN1_END);
67 while (type != SILC_ASN1_END) {
68 t = silc_smalloc(asn1->stack1, sizeof(*t));
72 silc_list_add(types, t);
74 SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
75 silc_asn1_tag_name(type), type));
77 type = va_arg(asn1->ap, SilcUInt32);
80 /* The sequence consists of this type. */
81 t = silc_smalloc(asn1->stack1, sizeof(*t));
85 silc_list_add(types, t);
87 SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
88 silc_asn1_tag_name(type), type));
91 /* END marker for the sequence */
92 type = va_arg(asn1->ap, SilcUInt32);
93 assert(type == SILC_ASN1_END);
95 /* Decode the SEQUENCE or SET */
96 ret = silc_ber_decode(src, NULL, NULL, &rtag, &rdata,
97 &rdata_len, &rindef, &len);
99 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
102 if (rtag != SILC_ASN1_TAG_SEQUENCE && rtag != SILC_ASN1_TAG_SET) {
103 SILC_LOG_DEBUG(("Invalid sequence of/set of"));
106 silc_buffer_pull(src, len);
108 while (silc_buffer_len(src)) {
109 /* Decode the BER data. */
110 ret = silc_ber_decode(src, NULL, NULL, &rtag, &rdata,
111 &rdata_len, &rindef, &len);
113 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
117 /* Now check the type(s) that it is supposed to be */
119 silc_list_start(types);
120 while ((t = silc_list_get(types)) != SILC_LIST_END) {
124 *retb = silc_srealloc(asn1->stack1, sizeof(**retb) * (*retc), *retb,
125 sizeof(**retb) * (*retc + 1));
129 SILC_LOG_DEBUG(("Decode %s [%d] from sequence of types",
130 silc_asn1_tag_name(rtag), rtag));
132 /* Data is duplicated only if SILC_ASN1_ALLOC flag is set */
134 rdata = silc_memdup(rdata - len, rdata_len + len);
140 silc_buffer_set(&(*retb)[*retc], (unsigned char *)rdata, rdata_len);
146 /* If type was not found we consider it the end of the sequence */
151 silc_buffer_pull(src, rdata_len);
154 SILC_LOG_DEBUG(("Decoded %d types", *retc));
159 silc_list_start(types);
160 while ((t = silc_list_get(types)) != SILC_LIST_END)
167 /* Macro for decoder to get argument for a type. If OPTIONAL option is
168 set then the argument is a pointer to the type pointer. The `type'
169 must be a non-pointer type, eg. int, SilcBufferStruct. */
170 #define SILC_ASN1_VAD(asn1, opts, type, name) \
172 if ((opts) & SILC_ASN1_OPTIONAL && !choice) { \
173 name = va_arg(asn1->ap, type **); \
181 *name = silc_scalloc(asn1->stack1, 1, sizeof(**name)); \
185 type *name ## tmp = va_arg(asn1->ap, type *); \
186 if (choice && found && !len) \
188 if (name ## tmp == NULL) \
190 name = &name ## tmp; \
193 /* Same as SILC_ASN1_VAD but for unsigned char and SilcUInt32 */
194 #define SILC_ASN1_VAD_UCHAR(asn1, opts, type, name, namelen) \
195 type **name = va_arg(asn1->ap, type **); \
196 SilcUInt32 *namelen = va_arg(asn1->ap, SilcUInt32 *); \
197 if (choice && found && !len) \
207 /* Same as SILC_ASN1_VAD but for char only */
208 #define SILC_ASN1_VAD_CHAR(asn1, opts, type, name) \
209 type **name = va_arg(asn1->ap, type **); \
210 if (choice && found && !len) \
220 #define SILC_ASN1_VA_FREE(opts, name) \
221 if ((opts) & SILC_ASN1_OPTIONAL) \
224 /* Decodes string to UTF-8 string which is our internal representation
226 #define SILC_ASN1_DECODE_STRING(enc, s, s_len) \
227 *s_len = silc_utf8_encoded_len(rdata, rdata_len, (enc)); \
229 SILC_LOG_DEBUG(("Malformed %d string value", (enc))); \
233 *s = silc_smalloc(stack1, *s_len + 1); \
235 silc_utf8_encode(rdata, rdata_len, (enc), *s, *s_len); \
236 (*s)[*s_len] = '\0'; \
240 /* Internal ASN.1 decoder. The `type', `tag' and `opts' are the first
241 arguments (either very first or first for recursion) for a type.
242 The `depth' includes the current depth of recursion. */
245 silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type,
246 SilcAsn1Tag tag, SilcBerClass ber_class,
247 SilcAsn1Options opts, SilcBuffer src, SilcUInt32 depth,
250 unsigned char *ptr = src->data;
252 SilcAsn1Options ropts;
254 SilcBerEncoding renc;
255 SilcUInt32 len = 0, rtag;
256 SilcBool ret, indef, rindef, found = FALSE, choice = FALSE;
257 const unsigned char *rdata;
258 SilcUInt32 rdata_len;
262 char sp[SILC_ASN1_RECURSION_DEPTH + 1];
263 memset(sp, 0, sizeof(sp));
265 memset(sp, 32, depth);
266 #endif /* SILC_DEBUG */
268 if (depth >= SILC_ASN1_RECURSION_DEPTH) {
269 SILC_LOG_DEBUG(("Maximum recursion depth reached"));
275 /* If requested type is SEQUENCE OF or SET OF then we decode the sequence
276 of types separately in an own decoder which returns array of buffers. */
277 if (type == SILC_ASN1_TAG_SEQUENCE_OF) {
278 /* Decode the sequence */
279 if (!silc_asn1_decoder_sof(asn1, src)) {
280 SILC_LOG_DEBUG(("Error decoding SEQUENCE OF"));
285 /* Continue with rest of the decodings if any */
286 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
287 if (type == SILC_ASN1_END) {
293 /* Get length encoding */
294 indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
296 /* By default UNIVERSAL is implied unless the following conditions
297 are met when CONTEXT will apply. For SILC_ASN1_TAG_ANY_PRIMITIVE
298 the class is changed only if flags dictate it. */
299 if (ber_class == SILC_BER_CLASS_UNIVERSAL) {
300 if (type == SILC_ASN1_TAG_ANY_PRIMITIVE) {
301 if (opts & SILC_ASN1_IMPLICIT ||
302 opts & SILC_ASN1_EXPLICIT)
303 ber_class = SILC_BER_CLASS_CONTEXT;
306 opts & SILC_ASN1_IMPLICIT ||
307 opts & SILC_ASN1_EXPLICIT)
308 ber_class = SILC_BER_CLASS_CONTEXT;
312 /* Short integer is actually big integer in the BER data, so handle
314 if (type == SILC_ASN1_TAG_SHORT_INTEGER && type == tag)
315 tag = SILC_ASN1_TAG_INTEGER;
317 /* Now decode a BER encoded block from the source buffer. It must be
318 exactly the same user is expecting. */
319 ret = silc_ber_decode(src, &rclass, &renc, &rtag, &rdata,
320 &rdata_len, &rindef, &len);
322 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
326 /* Now verify that the decoded BER is the one user wanted to get. If
327 requested type is OPTIONAL, then ignore all the sanity tests. The
328 while() loop is for re-considering OPTIONAL types without parsing
329 new BER object. For CHOICE (tag) all the choice considerations are
330 also done within the while(). */
333 /* If type is CHOICE then at least one type must match before next
334 SILC_ASN1_END is reached. The considerations act interally as
335 having OPTIONAL flag set, except that at the end one must have
337 if (type == SILC_ASN1_TAG_CHOICE) {
339 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
340 opts |= SILC_ASN1_OPTIONAL;
346 ("%04d: %sDecode %s [%d] %s %s %s %s", depth, sp[0] ? sp : "",
347 silc_asn1_tag_name(type), rtag,
348 rclass == SILC_BER_CLASS_UNIVERSAL ? "univ" :
349 rclass == SILC_BER_CLASS_APPLICATION ? "appl" :
350 rclass == SILC_BER_CLASS_CONTEXT ? "cont" : "priv",
351 renc == SILC_BER_ENC_PRIMITIVE ? "primit" : "constr",
352 rindef ? "indef" : "defin",
353 choice ? "choice" : opts & SILC_ASN1_OPTIONAL ? "option" : ""));
354 #endif /* SILC_DEBUG */
356 if (type != SILC_ASN1_TAG_ANY && tag != rtag) {
357 if (!(opts & SILC_ASN1_OPTIONAL)) {
358 SILC_LOG_DEBUG(("Invalid ASN.1 tag %u, expected %u", rtag, tag));
364 } else if (ber_class != rclass) {
365 if (!(opts & SILC_ASN1_OPTIONAL)) {
366 SILC_LOG_DEBUG(("Invalid ASN.1 class %d, expected %d",
373 } else if (!(opts & SILC_ASN1_EXPLICIT) && indef != rindef) {
374 SILC_LOG_DEBUG(("Invalid ASN.1 length encoding %s, expected %s",
375 rindef ? "indefinite" : "definite",
376 indef ? "indefinite" : "definite"));
379 } else if (rindef && renc == SILC_BER_ENC_PRIMITIVE) {
380 SILC_LOG_DEBUG(("Invalid length encoding for primitive type"));
387 /* If tagging is explicit we have additional sequence we need to decode
388 before we decode the actual underlaying type. */
389 if (opts & SILC_ASN1_EXPLICIT) {
390 silc_buffer_pull(src, len);
393 primitive = (type != SILC_ASN1_TAG_SEQUENCE &&
394 type != SILC_ASN1_TAG_SET &&
395 type != SILC_ASN1_TAG_ANY);
396 opts &= ~SILC_ASN1_EXPLICIT;
398 ret = silc_asn1_decoder(asn1, stack1, type, type,
399 SILC_BER_CLASS_UNIVERSAL, opts, src,
400 depth + 1, primitive);
410 /* Decode by the type user expects the data to be. */
413 case SILC_ASN1_TAG_ANY:
415 /* ANY is another ASN.1 node. We return the raw BER buffer as
417 SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, node);
419 *node = silc_buffer_srealloc_size(stack1, *node, len + rdata_len);
420 silc_buffer_put(*node, rdata - len, rdata_len + len);
424 case SILC_ASN1_TAG_ANY_PRIMITIVE:
426 /* ANY_PRIMITIVE returns the raw data blob of any primitive type. */
427 SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, prim);
429 *prim = silc_buffer_srealloc_size(stack1, *prim, rdata_len);
430 silc_buffer_put(*prim, rdata, rdata_len);
434 case SILC_ASN1_TAG_SEQUENCE:
435 case SILC_ASN1_TAG_SET:
437 /* SEQUENCE/SET is a sequence of types. */
438 silc_buffer_pull(src, len);
441 /* Get type, tag and options for the first argument in recursion */
442 SILC_ASN1_ARGS(asn1, rtype, rtag, rclass, ropts);
444 /* Decode the sequence recursively */
445 ret = silc_asn1_decoder(asn1, stack1, rtype, rtag, rclass,
446 ropts, src, depth + 1, FALSE);
452 case SILC_ASN1_TAG_INTEGER:
453 case SILC_ASN1_TAG_ENUM:
455 /* Integer/enum value. */
457 SILC_ASN1_VAD(asn1, opts, SilcMPInt, intval);
460 SILC_LOG_DEBUG(("Malformed integer value"));
461 SILC_ASN1_VA_FREE(opts, intval);
466 silc_mp_sinit(asn1->stack1, *intval);
468 /* Check whether the integer is positive or negative */
469 if (rdata[0] & 0x80) {
470 /* Negative integer stored in 1s complement.*/
471 for (i = 0; i < rdata_len; i++) {
472 silc_mp_mul_2exp(*intval, *intval, 8);
473 silc_mp_add_ui(*intval, *intval, ~rdata[i] & 0xff);
476 /* 2s complement and change sign */
478 silc_mp_set_ui(&z, 0);
479 silc_mp_add_ui(*intval, *intval, 1);
480 silc_mp_sub(*intval, &z, *intval);
484 silc_mp_bin2mp((unsigned char *)rdata, rdata_len, *intval);
490 case SILC_ASN1_TAG_SHORT_INTEGER:
494 SILC_ASN1_VAD(asn1, opts, SilcUInt32, intval);
497 SILC_LOG_DEBUG(("Malformed integer value"));
498 SILC_ASN1_VA_FREE(opts, intval);
503 silc_stack_push(asn1->stack1, NULL);
504 silc_mp_sinit(asn1->stack1, &z);
505 silc_mp_bin2mp((unsigned char *)rdata, rdata_len, &z);
506 *(*intval) = silc_mp_get_ui(&z);
508 silc_stack_pop(asn1->stack1);
512 case SILC_ASN1_TAG_OID:
514 /* Object identifier */
515 SilcBufferStruct tmpb;
518 SILC_ASN1_VAD_CHAR(asn1, opts, char, oidstr);
521 SILC_LOG_DEBUG(("Malformed object identifier value"));
522 SILC_ASN1_VA_FREE(opts, oidstr);
527 /* Set two OID values */
528 memset(&tmpb, 0, sizeof(tmpb));
529 memset(tmpstr, 0, sizeof(tmpstr));
530 silc_snprintf(tmpstr, sizeof(tmpstr) - 1, "%lu.%lu",
531 (unsigned long)(rdata[0] & 0xff) / 40,
532 (unsigned long)(rdata[0] & 0xff) % 40);
533 silc_buffer_sstrformat(asn1->stack1, &tmpb, tmpstr, SILC_STR_END);
535 /* Set rest of the OID values, each octet having 7 bits of the
536 OID value with bit 8 set. An octet not having bit 8 set
537 means end of that OID value. */
538 for (i = 1; i < rdata_len; i++) {
540 while (rdata[i] & 0x80) {
542 oid |= rdata[i++] & 0x7f;
543 if (i >= rdata_len) {
544 SILC_LOG_DEBUG(("Malformed object identifier value"));
551 memset(tmpstr, 0, sizeof(tmpstr));
552 silc_snprintf(tmpstr, sizeof(tmpstr) - 1, ".%lu", (unsigned long)oid);
553 silc_buffer_sstrformat(asn1->stack1, &tmpb, tmpstr, SILC_STR_END);
560 case SILC_ASN1_TAG_BOOLEAN:
562 /* Decode boolean (TRUE/FALSE) value */
563 SILC_ASN1_VAD(asn1, opts, SilcBool, val);
565 if (rdata_len != 1) {
566 SILC_LOG_DEBUG(("Malformed boolean value"));
567 SILC_ASN1_VA_FREE(opts, val);
572 *(*val) = (rdata[0] == 0xff ? TRUE : FALSE);
576 case SILC_ASN1_TAG_BIT_STRING:
578 /* Bit string contains data with exact bit length of the data */
579 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, d, d_len);
582 SILC_LOG_DEBUG(("Malformed bit string value"));
583 SILC_ASN1_VA_FREE(opts, d);
588 *d = silc_smemdup(stack1, rdata + 1, rdata_len - 1);
589 *d_len = (rdata_len - 1) * 8;
593 case SILC_ASN1_TAG_NULL:
595 /* Decode empty BER block */
596 if (rdata_len != 0) {
597 SILC_LOG_DEBUG(("Malformed null value"));
603 case SILC_ASN1_TAG_UTC_TIME:
605 /* Universal encoded time string */
606 SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
609 SILC_LOG_DEBUG(("Malformed UTC time value"));
610 SILC_ASN1_VA_FREE(opts, t);
615 /* Parse the time string */
616 if (!silc_time_universal(rdata, *t)) {
617 SILC_LOG_DEBUG(("Malformed UTC time value"));
625 case SILC_ASN1_TAG_GENERALIZED_TIME:
627 /* Generalized encoded time string */
628 SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
631 SILC_LOG_DEBUG(("Malformed generalized time value"));
632 SILC_ASN1_VA_FREE(opts, t);
637 /* Parse the time string */
638 if (!silc_time_generalized(rdata, *t)) {
639 SILC_LOG_DEBUG(("Malformed generalized time value"));
640 SILC_ASN1_VA_FREE(opts, t);
648 case SILC_ASN1_TAG_UTF8_STRING:
650 /* UTF-8 encoded string */
651 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
653 if (!silc_utf8_valid(rdata, rdata_len)) {
654 SILC_LOG_DEBUG(("Malformed UTF-8 string value"));
655 SILC_ASN1_VA_FREE(opts, s);
660 *s = silc_smemdup(stack1, rdata, rdata_len);
665 case SILC_ASN1_TAG_OCTET_STRING:
667 /* Octet string. Take data as is. */
668 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
669 *s = silc_smemdup(stack1, rdata, rdata_len);
674 case SILC_ASN1_TAG_NUMERIC_STRING:
676 /* Numerical (digit) string */
677 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
678 SILC_ASN1_DECODE_STRING(SILC_STRING_NUMERICAL, s, s_len);
682 case SILC_ASN1_TAG_PRINTABLE_STRING:
684 /* Printable string */
685 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
686 SILC_ASN1_DECODE_STRING(SILC_STRING_PRINTABLE, s, s_len);
690 case SILC_ASN1_TAG_TELETEX_STRING:
692 /* Teletex (T61) string */
693 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
694 SILC_ASN1_DECODE_STRING(SILC_STRING_TELETEX, s, s_len);
698 case SILC_ASN1_TAG_IA5_STRING:
700 /* US ASCII string */
701 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
702 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_len);
706 case SILC_ASN1_TAG_VISIBLE_STRING:
709 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
710 SILC_ASN1_DECODE_STRING(SILC_STRING_VISIBLE, s, s_len);
714 case SILC_ASN1_TAG_UNIVERSAL_STRING:
716 /* Universal (UCS-4) string */
717 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
718 SILC_ASN1_DECODE_STRING(SILC_STRING_UNIVERSAL, s, s_len);
722 case SILC_ASN1_TAG_UNRESTRICTED_STRING:
723 case SILC_ASN1_TAG_GENERAL_STRING:
725 /* Handle now unrestricted and general as 8-bit ascii, which
726 probably isn't correct. */
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_BMP_STRING:
734 /* BMP (UCS-2) string */
735 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
736 SILC_ASN1_DECODE_STRING(SILC_STRING_BMP, s, s_len);
740 case SILC_ASN1_TAG_ODE:
741 case SILC_ASN1_TAG_ETI:
742 case SILC_ASN1_TAG_REAL:
743 case SILC_ASN1_TAG_EMBEDDED:
744 case SILC_ASN1_TAG_ROI:
745 case SILC_ASN1_TAG_VIDEOTEX_STRING:
746 case SILC_ASN1_TAG_GRAPHIC_STRING:
748 SILC_NOT_IMPLEMENTED("Unsupported ASN.1 tag");
755 SILC_LOG_DEBUG(("Invalid ASN.1 tag `%d'. Cannot decode ASN.1.",
763 /* Pull the current data from source which reveals next BER object */
764 if (found && len + rdata_len)
765 silc_buffer_pull(src, len + rdata_len);
771 /* Get next type, tag and options */
773 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
774 if (type == SILC_ASN1_END) {
777 /* No choices were found, error */
778 SILC_LOG_DEBUG(("Invalid ASN.1 choice: no choices present"));
783 /* Take next type and new BER object, choices are over */
785 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
786 if (type == SILC_ASN1_END) {
793 /* SEQUENCE/SET end */
799 /* Even if the choice was found we must go through rest of
802 SILC_LOG_DEBUG(("Found choice %s type", silc_asn1_tag_name(rtype)));
805 opts |= SILC_ASN1_OPTIONAL;
809 /* Optional type not present, check next one for match */
818 SILC_LOG_DEBUG(("Error decoding type %d (depth %d)", type, depth));
822 len = src->data - ptr;
824 len = src->data - src->head;
825 silc_buffer_push(src, len);
830 SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...)
832 SilcAsn1Tag type, tag;
833 SilcAsn1Options opts;
834 SilcBerClass ber_class;
835 SilcStackFrame frame1, frame2;
836 SilcStack stack1 = NULL, stack2 = NULL;
842 va_start(asn1->ap, src);
844 /* Get the first arguments and call the decoder. */
845 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
851 /* Handle internal options for decoder. */
852 if (type == SILC_ASN1_TAG_OPTS) {
853 SilcUInt32 o = va_arg(asn1->ap, SilcUInt32);
855 if (o & SILC_ASN1_ALLOC) {
856 /* User wants to alloate everything. Set the stacks to NULL so
857 that stack aware calls revert to normal allocation routines. */
858 stack1 = asn1->stack1;
859 stack2 = asn1->stack2;
864 if (o & SILC_ASN1_ACCUMUL) {
865 /* If accumul flag is not set yet, then push the stacks. */
866 if (!asn1->accumul) {
867 silc_stack_push(asn1->stack1, NULL);
868 silc_stack_push(asn1->stack2, NULL);
873 /* Take again the arguments */
874 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
876 /* No flags set, all flags will be reset. */
878 /* If accumul flag is set now pop the stack so that all accumulated
879 memory becomes free again. */
881 silc_stack_pop(asn1->stack1);
882 silc_stack_pop(asn1->stack2);
887 /* Push stacks for normal allocation from stack */
888 if (!asn1->accumul) {
889 silc_stack_push(asn1->stack1, &frame1);
890 silc_stack_push(asn1->stack2, &frame2);
894 ret = silc_asn1_decoder(asn1, asn1->stack1, type, tag, ber_class,
895 opts, src, 0, FALSE);
897 /* Pop stacks to free normal allocations from stack. They remain valid
898 for every second call to this function. */
899 if (!asn1->accumul) {
900 silc_stack_pop(asn1->stack1);
901 silc_stack_pop(asn1->stack2);
903 /* Switch the asn1->stack1 and asn1->stack2. This way next call to
904 this function does not invalidate these results. Every second call
905 invalidates the results of every second previous results. */
906 if (asn1->stack1 && asn1->stack2) {
907 stack1 = asn1->stack1;
908 asn1->stack1 = asn1->stack2;
909 asn1->stack2 = stack1;
913 if (stack1 && stack2 && !asn1->stack1 && !asn1->stack2) {
914 /* SILC_ASN1_ALLOC flag was set, restore the stacks. */
915 asn1->stack1 = stack1;
916 asn1->stack2 = stack2;