5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2003 - 2006 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)
39 const unsigned char *rdata;
40 SilcUInt32 rdata_len, len = 0;
41 SilcBool found = FALSE, rindef;
43 struct SilcAsn1SofStruct {
45 struct SilcAsn1SofStruct *next;
48 SILC_LOG_DEBUG(("Decoding sequence of types"));
50 silc_list_init(types, struct SilcAsn1SofStruct, next);
52 /* Take the return arguments */
53 retb = va_arg(asn1->ap, SilcBuffer *);
54 retc = va_arg(asn1->ap, SilcUInt32 *);
58 /* Get the sequence type(s). If the type is CHOICE tag then the sequence
59 may include multiple different types. All types are considered
60 separately. If CHOICE is not given then only single type is expected. */
61 type = va_arg(asn1->ap, SilcUInt32);
62 assert(type != SILC_ASN1_END);
64 if (type == SILC_ASN1_TAG_CHOICE) {
65 /* The sequence may consist of the following types. */
66 type = va_arg(asn1->ap, SilcUInt32);
67 assert(type != SILC_ASN1_END);
68 while (type != SILC_ASN1_END) {
69 t = silc_smalloc(asn1->stack1, sizeof(*t));
73 silc_list_add(types, t);
75 SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
76 silc_asn1_tag_name(type), type));
78 type = va_arg(asn1->ap, SilcUInt32);
81 /* The sequence consists of this type. */
82 t = silc_smalloc(asn1->stack1, sizeof(*t));
86 silc_list_add(types, t);
88 SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
89 silc_asn1_tag_name(type), type));
92 /* END marker for the sequence */
93 type = va_arg(asn1->ap, SilcUInt32);
94 assert(type == SILC_ASN1_END);
96 /* Decode the SEQUENCE or SET */
97 ret = silc_ber_decode(src, NULL, NULL, (SilcUInt32 *)&rtag, &rdata,
98 &rdata_len, &rindef, &len);
100 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
103 if (rtag != SILC_ASN1_TAG_SEQUENCE && rtag != SILC_ASN1_TAG_SET) {
104 SILC_LOG_DEBUG(("Invalid sequence of/set of"));
107 silc_buffer_pull(src, len);
109 while (silc_buffer_len(src)) {
110 /* Decode the BER data. */
111 ret = silc_ber_decode(src, NULL, NULL, (SilcUInt32 *)&rtag, &rdata,
112 &rdata_len, &rindef, &len);
114 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
118 /* Now check the type(s) that it is supposed to be */
120 silc_list_start(types);
121 while ((t = silc_list_get(types)) != SILC_LIST_END) {
125 *retb = silc_srealloc(asn1->stack1, sizeof(**retb) * (*retc), *retb,
126 sizeof(**retb) * (*retc + 1));
130 SILC_LOG_DEBUG(("Decode %s [%d] from sequence of types",
131 silc_asn1_tag_name(rtag), rtag));
133 /* Data is duplicated only if SILC_ASN1_ALLOC flag is set */
135 rdata = silc_memdup(rdata - len, rdata_len + len);
141 silc_buffer_set(&(*retb)[*retc], (unsigned char *)rdata, rdata_len);
147 /* If type was not found we consider it the end of the sequence */
152 silc_buffer_pull(src, rdata_len);
155 SILC_LOG_DEBUG(("Decoded %d types", *retc));
160 silc_list_start(types);
161 while ((t = silc_list_get(types)) != SILC_LIST_END)
168 /* Macro for decoder to get argument for a type. If OPTIONAL option is
169 set then the argument is a pointer to the type pointer. The `type'
170 must be a non-pointer type, eg. int, SilcBufferStruct. */
171 #define SILC_ASN1_VAD(asn1, opts, type, name) \
173 if ((opts) & SILC_ASN1_OPTIONAL && !choice) { \
174 name = va_arg(asn1->ap, type **); \
182 *name = silc_scalloc(asn1->stack1, 1, sizeof(**name)); \
186 type *name ## tmp = va_arg(asn1->ap, type *); \
187 if (choice && found && !len) \
189 if (name ## tmp == NULL) \
191 name = &name ## tmp; \
194 /* Same as SILC_ASN1_VAD but for unsigned char and SilcUInt32 */
195 #define SILC_ASN1_VAD_UCHAR(asn1, opts, type, name, namelen) \
196 type **name = va_arg(asn1->ap, type **); \
197 SilcUInt32 *namelen = va_arg(asn1->ap, SilcUInt32 *); \
198 if (choice && found && !len) \
208 /* Same as SILC_ASN1_VAD but for char only */
209 #define SILC_ASN1_VAD_CHAR(asn1, opts, type, name) \
210 type **name = va_arg(asn1->ap, type **); \
211 if (choice && found && !len) \
221 #define SILC_ASN1_VA_FREE(opts, name) \
222 if ((opts) & SILC_ASN1_OPTIONAL) \
225 /* Decodes string to UTF-8 string which is our internal representation
227 #define SILC_ASN1_DECODE_STRING(enc, s, s_len) \
228 *s_len = silc_utf8_encoded_len(rdata, rdata_len, (enc)); \
230 SILC_LOG_DEBUG(("Malformed %d string value", (enc))); \
234 *s = silc_smalloc_ua(stack1, *s_len + 1); \
236 silc_utf8_encode(rdata, rdata_len, (enc), *s, *s_len); \
237 (*s)[*s_len] = '\0'; \
241 /* Internal ASN.1 decoder. The `type', `tag' and `opts' are the first
242 arguments (either very first or first for recursion) for a type.
243 The `depth' includes the current depth of recursion. */
246 silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type,
247 SilcAsn1Tag tag, SilcBerClass ber_class,
248 SilcAsn1Options opts, SilcBuffer src, SilcUInt32 depth,
251 unsigned char *ptr = src->data;
252 SilcAsn1Tag rtype, rtag;
253 SilcAsn1Options ropts;
255 SilcBerEncoding renc;
257 SilcBool ret, indef, rindef, found = FALSE, choice = FALSE;
258 const unsigned char *rdata;
259 SilcUInt32 rdata_len;
263 char sp[SILC_ASN1_RECURSION_DEPTH + 1];
264 memset(sp, 0, sizeof(sp));
266 memset(sp, 32, depth);
267 #endif /* SILC_DEBUG */
269 if (depth >= SILC_ASN1_RECURSION_DEPTH) {
270 SILC_LOG_DEBUG(("Maximum recursion depth reached"));
276 /* If requested type is SEQUENCE OF or SET OF then we decode the sequence
277 of types separately in an own decoder which returns array of buffers. */
278 if (type == SILC_ASN1_TAG_SEQUENCE_OF) {
279 /* Decode the sequence */
280 if (!silc_asn1_decoder_sof(asn1, src)) {
281 SILC_LOG_DEBUG(("Error decoding SEQUENCE OF"));
286 /* Continue with rest of the decodings if any */
287 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
288 if (type == SILC_ASN1_END) {
294 /* Get length encoding */
295 indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
297 /* By default UNIVERSAL is implied unless the following conditions
298 are met when CONTEXT will apply. For SILC_ASN1_TAG_ANY_PRIMITIVE
299 the class is changed only if flags dictate it. */
300 if (ber_class == SILC_BER_CLASS_UNIVERSAL) {
301 if (type == SILC_ASN1_TAG_ANY_PRIMITIVE) {
302 if (opts & SILC_ASN1_IMPLICIT ||
303 opts & SILC_ASN1_EXPLICIT)
304 ber_class = SILC_BER_CLASS_CONTEXT;
307 opts & SILC_ASN1_IMPLICIT ||
308 opts & SILC_ASN1_EXPLICIT)
309 ber_class = SILC_BER_CLASS_CONTEXT;
313 /* Short integer is actually big integer in the BER data, so handle
315 if (type == SILC_ASN1_TAG_SHORT_INTEGER && type == tag)
316 tag = SILC_ASN1_TAG_INTEGER;
318 /* Now decode a BER encoded block from the source buffer. It must be
319 exactly the same user is expecting. */
320 ret = silc_ber_decode(src, &rclass, &renc, (SilcUInt32 *)&rtag, &rdata,
321 &rdata_len, &rindef, &len);
323 SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
327 /* Now verify that the decoded BER is the one user wanted to get. If
328 requested type is OPTIONAL, then ignore all the sanity tests. The
329 while() loop is for re-considering OPTIONAL types without parsing
330 new BER object. For CHOICE (tag) all the choice considerations are
331 also done within the while(). */
334 /* If type is CHOICE then at least one type must match before next
335 SILC_ASN1_END is reached. The considerations act interally as
336 having OPTIONAL flag set, except that at the end one must have
338 if (type == SILC_ASN1_TAG_CHOICE) {
340 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
341 opts |= SILC_ASN1_OPTIONAL;
347 ("%04d: %sDecode %s [%d] %s %s %s %s", depth, sp[0] ? sp : "",
348 silc_asn1_tag_name(type), rtag,
349 rclass == SILC_BER_CLASS_UNIVERSAL ? "univ" :
350 rclass == SILC_BER_CLASS_APPLICATION ? "appl" :
351 rclass == SILC_BER_CLASS_CONTEXT ? "cont" : "priv",
352 renc == SILC_BER_ENC_PRIMITIVE ? "primit" : "constr",
353 rindef ? "indef" : "defin",
354 choice ? "choice" : opts & SILC_ASN1_OPTIONAL ? "option" : ""));
355 #endif /* SILC_DEBUG */
357 if (type != SILC_ASN1_TAG_ANY && tag != rtag) {
358 if (!(opts & SILC_ASN1_OPTIONAL)) {
359 SILC_LOG_DEBUG(("Invalid ASN.1 tag %u, expected %u", rtag, tag));
365 } else if (ber_class != rclass) {
366 if (!(opts & SILC_ASN1_OPTIONAL)) {
367 SILC_LOG_DEBUG(("Invalid ASN.1 class %d, expected %d",
374 } else if (!(opts & SILC_ASN1_EXPLICIT) && indef != rindef) {
375 SILC_LOG_DEBUG(("Invalid ASN.1 length encoding %s, expected %s",
376 rindef ? "indefinite" : "definite",
377 indef ? "indefinite" : "definite"));
380 } else if (rindef && renc == SILC_BER_ENC_PRIMITIVE) {
381 SILC_LOG_DEBUG(("Invalid length encoding for primitive type"));
388 /* If tagging is explicit we have additional sequence we need to decode
389 before we decode the actual underlaying type. */
390 if (opts & SILC_ASN1_EXPLICIT) {
391 silc_buffer_pull(src, len);
394 primitive = (type != SILC_ASN1_TAG_SEQUENCE &&
395 type != SILC_ASN1_TAG_SET &&
396 type != SILC_ASN1_TAG_ANY);
397 opts &= ~SILC_ASN1_EXPLICIT;
399 ret = silc_asn1_decoder(asn1, stack1, type, type,
400 SILC_BER_CLASS_UNIVERSAL, opts, src,
401 depth + 1, primitive);
411 /* Decode by the type user expects the data to be. */
414 case SILC_ASN1_TAG_ANY:
416 /* ANY is another ASN.1 node. We return the raw BER buffer as
418 SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, node);
420 *node = silc_buffer_srealloc_size(stack1, *node, len + rdata_len);
421 silc_buffer_put(*node, rdata - len, rdata_len + len);
425 case SILC_ASN1_TAG_ANY_PRIMITIVE:
427 /* ANY_PRIMITIVE returns the raw data blob of any primitive type. */
428 SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, prim);
430 *prim = silc_buffer_srealloc_size(stack1, *prim, rdata_len);
431 silc_buffer_put(*prim, rdata, rdata_len);
435 case SILC_ASN1_TAG_SEQUENCE:
436 case SILC_ASN1_TAG_SET:
438 /* SEQUENCE/SET is a sequence of types. */
439 silc_buffer_pull(src, len);
442 /* Get type, tag and options for the first argument in recursion */
443 SILC_ASN1_ARGS(asn1, rtype, rtag, rclass, ropts);
445 /* Decode the sequence recursively */
446 ret = silc_asn1_decoder(asn1, stack1, rtype, rtag, rclass,
447 ropts, src, depth + 1, FALSE);
453 case SILC_ASN1_TAG_INTEGER:
454 case SILC_ASN1_TAG_ENUM:
456 /* Integer/enum value. */
458 SILC_ASN1_VAD(asn1, opts, SilcMPInt, intval);
461 SILC_LOG_DEBUG(("Malformed integer value"));
462 SILC_ASN1_VA_FREE(opts, intval);
467 silc_mp_sinit(asn1->stack1, *intval);
469 /* Check whether the integer is positive or negative */
470 if (rdata[0] & 0x80) {
471 /* Negative integer stored in 1s complement.*/
472 for (i = 0; i < rdata_len; i++) {
473 silc_mp_mul_2exp(*intval, *intval, 8);
474 silc_mp_add_ui(*intval, *intval, ~rdata[i] & 0xff);
477 /* 2s complement and change sign */
479 silc_mp_set_ui(&z, 0);
480 silc_mp_add_ui(*intval, *intval, 1);
481 silc_mp_sub(*intval, &z, *intval);
485 silc_mp_bin2mp((unsigned char *)rdata, rdata_len, *intval);
491 case SILC_ASN1_TAG_SHORT_INTEGER:
495 SILC_ASN1_VAD(asn1, opts, SilcUInt32, intval);
498 SILC_LOG_DEBUG(("Malformed integer value"));
499 SILC_ASN1_VA_FREE(opts, intval);
504 silc_stack_push(asn1->stack1, NULL);
505 silc_mp_sinit(asn1->stack1, &z);
506 silc_mp_bin2mp((unsigned char *)rdata, rdata_len, &z);
507 *(*intval) = silc_mp_get_ui(&z);
509 silc_stack_pop(asn1->stack1);
513 case SILC_ASN1_TAG_OID:
515 /* Object identifier */
516 SilcBufferStruct tmpb;
519 SILC_ASN1_VAD_CHAR(asn1, opts, char, oidstr);
522 SILC_LOG_DEBUG(("Malformed object identifier value"));
523 SILC_ASN1_VA_FREE(opts, oidstr);
528 /* Set two OID values */
529 memset(&tmpb, 0, sizeof(tmpb));
530 memset(tmpstr, 0, sizeof(tmpstr));
531 snprintf(tmpstr, sizeof(tmpstr) - 1, "%lu.%lu",
532 (unsigned long)(rdata[0] & 0xff) / 40,
533 (unsigned long)(rdata[0] & 0xff) % 40);
534 silc_buffer_sstrformat(asn1->stack1, &tmpb, tmpstr, SILC_STR_END);
536 /* Set rest of the OID values, each octet having 7 bits of the
537 OID value with bit 8 set. An octet not having bit 8 set
538 means end of that OID value. */
539 for (i = 1; i < rdata_len; i++) {
541 while (rdata[i] & 0x80) {
543 oid |= rdata[i++] & 0x7f;
544 if (i >= rdata_len) {
545 SILC_LOG_DEBUG(("Malformed object identifier value"));
552 memset(tmpstr, 0, sizeof(tmpstr));
553 snprintf(tmpstr, sizeof(tmpstr) - 1, ".%lu", (unsigned long)oid);
554 silc_buffer_sstrformat(asn1->stack1, &tmpb, tmpstr, SILC_STR_END);
561 case SILC_ASN1_TAG_BOOLEAN:
563 /* Decode boolean (TRUE/FALSE) value */
564 SILC_ASN1_VAD(asn1, opts, SilcBool, val);
566 if (rdata_len != 1) {
567 SILC_LOG_DEBUG(("Malformed boolean value"));
568 SILC_ASN1_VA_FREE(opts, val);
573 *(*val) = (rdata[0] == 0xff ? TRUE : FALSE);
577 case SILC_ASN1_TAG_BIT_STRING:
579 /* Bit string contains data with exact bit length of the data */
580 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, d, d_len);
583 SILC_LOG_DEBUG(("Malformed bit string value"));
584 SILC_ASN1_VA_FREE(opts, d);
589 *d = silc_smemdup(stack1, rdata + 1, rdata_len - 1);
590 *d_len = (rdata_len - 1) * 8;
594 case SILC_ASN1_TAG_NULL:
596 /* Decode empty BER block */
597 if (rdata_len != 0) {
598 SILC_LOG_DEBUG(("Malformed null value"));
604 case SILC_ASN1_TAG_UTC_TIME:
606 /* Universal encoded time string */
607 SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
610 SILC_LOG_DEBUG(("Malformed UTC time value"));
611 SILC_ASN1_VA_FREE(opts, t);
616 /* Parse the time string */
617 if (!silc_time_universal(rdata, *t)) {
618 SILC_LOG_DEBUG(("Malformed UTC time value"));
626 case SILC_ASN1_TAG_GENERALIZED_TIME:
628 /* Generalized encoded time string */
629 SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
632 SILC_LOG_DEBUG(("Malformed generalized time value"));
633 SILC_ASN1_VA_FREE(opts, t);
638 /* Parse the time string */
639 if (!silc_time_generalized(rdata, *t)) {
640 SILC_LOG_DEBUG(("Malformed generalized time value"));
641 SILC_ASN1_VA_FREE(opts, t);
649 case SILC_ASN1_TAG_UTF8_STRING:
651 /* UTF-8 encoded string */
652 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
654 if (!silc_utf8_valid(rdata, rdata_len)) {
655 SILC_LOG_DEBUG(("Malformed UTF-8 string value"));
656 SILC_ASN1_VA_FREE(opts, s);
661 *s = silc_smemdup(stack1, rdata, rdata_len);
666 case SILC_ASN1_TAG_OCTET_STRING:
668 /* Octet string. We take it as 8-bit ASCII */
669 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
670 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_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;