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, so handle it correctly */
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, (SilcUInt32 *)&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 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 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. We take it as 8-bit ASCII */
668 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
669 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_len);
673 case SILC_ASN1_TAG_NUMERIC_STRING:
675 /* Numerical (digit) string */
676 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
677 SILC_ASN1_DECODE_STRING(SILC_STRING_NUMERICAL, s, s_len);
681 case SILC_ASN1_TAG_PRINTABLE_STRING:
683 /* Printable string */
684 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
685 SILC_ASN1_DECODE_STRING(SILC_STRING_PRINTABLE, s, s_len);
689 case SILC_ASN1_TAG_TELETEX_STRING:
691 /* Teletex (T61) string */
692 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
693 SILC_ASN1_DECODE_STRING(SILC_STRING_TELETEX, s, s_len);
697 case SILC_ASN1_TAG_IA5_STRING:
699 /* US ASCII string */
700 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
701 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_len);
705 case SILC_ASN1_TAG_VISIBLE_STRING:
708 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
709 SILC_ASN1_DECODE_STRING(SILC_STRING_VISIBLE, s, s_len);
713 case SILC_ASN1_TAG_UNIVERSAL_STRING:
715 /* Universal (UCS-4) string */
716 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
717 SILC_ASN1_DECODE_STRING(SILC_STRING_UNIVERSAL, s, s_len);
721 case SILC_ASN1_TAG_UNRESTRICTED_STRING:
722 case SILC_ASN1_TAG_GENERAL_STRING:
724 /* Handle now unrestricted and general as 8-bit ascii, which
725 probably isn't correct. */
726 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
727 SILC_ASN1_DECODE_STRING(SILC_STRING_ASCII, s, s_len);
731 case SILC_ASN1_TAG_BMP_STRING:
733 /* BMP (UCS-2) string */
734 SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
735 SILC_ASN1_DECODE_STRING(SILC_STRING_BMP, s, s_len);
739 case SILC_ASN1_TAG_ODE:
740 case SILC_ASN1_TAG_ETI:
741 case SILC_ASN1_TAG_REAL:
742 case SILC_ASN1_TAG_EMBEDDED:
743 case SILC_ASN1_TAG_ROI:
744 case SILC_ASN1_TAG_VIDEOTEX_STRING:
745 case SILC_ASN1_TAG_GRAPHIC_STRING:
747 SILC_NOT_IMPLEMENTED("Unsupported ASN.1 tag");
754 SILC_LOG_DEBUG(("Invalid ASN.1 tag `%d'. Cannot decode ASN.1.",
762 /* Pull the current data from source which reveals next BER object */
763 if (found && len + rdata_len)
764 silc_buffer_pull(src, len + rdata_len);
770 /* Get next type, tag and options */
772 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
773 if (type == SILC_ASN1_END) {
776 /* No choices were found, error */
777 SILC_LOG_DEBUG(("Invalid ASN.1 choice: no choices present"));
782 /* Take next type and new BER object, choices are over */
784 SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
785 if (type == SILC_ASN1_END) {
792 /* SEQUENCE/SET end */
798 /* Even if the choice was found we must go through rest of
801 SILC_LOG_DEBUG(("Found choice %s type", silc_asn1_tag_name(rtype)));
804 opts |= SILC_ASN1_OPTIONAL;
808 /* Optional type not present, check next one for match */
817 SILC_LOG_DEBUG(("Error decoding type %d (depth %d)", type, depth));
821 len = src->data - ptr;
823 len = src->data - src->head;
824 silc_buffer_push(src, len);
829 SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...)
831 SilcAsn1Tag type, tag;
832 SilcAsn1Options opts;
833 SilcBerClass ber_class;
834 SilcStackFrame frame1, frame2;
835 SilcStack stack1 = NULL, stack2 = NULL;
841 va_start(asn1->ap, src);
843 /* Get the first arguments and call the decoder. */
844 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;