Added SILC Thread Queue API
[silc.git] / lib / silcasn1 / silcasn1_decode.c
1 /*
2
3   silcasn1_decode.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2003 - 2007 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 #include "silc.h"
21 #include "silcasn1.h"
22 #include "silcber.h"
23
24 #define SILC_ASN1_STACK(stack, asn1) stack ? stack : asn1->orig_stack
25
26 /************************** ASN.1 Decoder routines **************************/
27
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. */
32
33 static SilcBool silc_asn1_decoder_sof(SilcAsn1 asn1, SilcBuffer src)
34 {
35   SilcBool ret = FALSE;
36   SilcList types;
37   SilcAsn1Tag type;
38   SilcBuffer *retb;
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;
43
44   struct SilcAsn1SofStruct {
45     SilcAsn1Tag type;
46     struct SilcAsn1SofStruct *next;
47   } *t = NULL;
48
49   SILC_LOG_DEBUG(("Decoding sequence of types"));
50
51   silc_list_init(types, struct SilcAsn1SofStruct, next);
52
53   /* Take the return arguments */
54   retb = va_arg(asn1->ap, SilcBuffer *);
55   retc = va_arg(asn1->ap, SilcUInt32 *);
56   *retb = NULL;
57   *retc = 0;
58
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);
64
65   if (type == SILC_ASN1_TAG_CHOICE) {
66     /* The sequence may consist of the following types. */
67     choice_index = va_arg(asn1->ap, SilcUInt32 *);
68     *choice_index = 0;
69
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));
74       if (!t)
75         goto out;
76       t->type = type;
77       silc_list_add(types, t);
78
79       SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
80                       silc_asn1_tag_name(type), type));
81
82       type = va_arg(asn1->ap, SilcUInt32);
83     }
84   } else {
85     /* The sequence consists of this type. */
86     t = silc_smalloc(SILC_ASN1_STACK(asn1->stack1, asn1), sizeof(*t));
87     if (!t)
88       goto out;
89     t->type = type;
90     silc_list_add(types, t);
91
92     SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
93                     silc_asn1_tag_name(type), type));
94   }
95
96   /* END marker for the sequence */
97   type = va_arg(asn1->ap, SilcUInt32);
98   assert(type == SILC_ASN1_END);
99
100   /* Decode the SEQUENCE or SET */
101   ret = silc_ber_decode(src, NULL, NULL, &rtag, &rdata,
102                         &rdata_len, &rindef, &len);
103   if (!ret) {
104     SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
105     goto out;
106   }
107   if (rtag != SILC_ASN1_TAG_SEQUENCE && rtag != SILC_ASN1_TAG_SET) {
108     SILC_LOG_DEBUG(("Invalid sequence of/set of"));
109     goto out;
110   }
111   silc_buffer_pull(src, len);
112
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);
117     if (!ret) {
118       SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
119       goto out;
120     }
121
122     /* Now check the type(s) that it is supposed to be */
123     found = FALSE;
124     silc_list_start(types);
125     while ((t = silc_list_get(types)) != SILC_LIST_END) {
126       if (choice_index && !chosen)
127         (*choice_index)++;
128
129       if (t->type != rtag)
130         continue;
131
132       *retb = silc_srealloc(SILC_ASN1_STACK(asn1->stack1, asn1),
133                             sizeof(**retb) * (*retc), *retb,
134                             sizeof(**retb) * (*retc + 1));
135       if (*retb == NULL)
136         goto out;
137
138       SILC_LOG_DEBUG(("Decode %s [%d] from sequence of types",
139                       silc_asn1_tag_name(rtag), rtag));
140
141       /* Data is duplicated only if SILC_ASN1_ALLOC flag is set, ie.
142          asn1->stack1 == NULL */
143       if (!asn1->stack1)
144         rdata = silc_smemdup(asn1->orig_stack, rdata - len, rdata_len + len);
145       else
146         rdata = rdata - len;
147       rdata_len += len;
148
149       /* Save the data */
150       silc_buffer_set(&(*retb)[*retc], (unsigned char *)rdata, rdata_len);
151       (*retc)++;
152       found = TRUE;
153       chosen = TRUE;
154       break;
155     }
156
157     /* If type was not found we consider it the end of the sequence */
158     if (found == FALSE)
159       break;
160
161     if (rdata_len)
162       silc_buffer_pull(src, rdata_len);
163   }
164
165   SILC_LOG_DEBUG(("Decoded %d types", *retc));
166   ret = TRUE;
167
168  out:
169   if (!asn1->stack1) {
170     silc_list_start(types);
171     while ((t = silc_list_get(types)) != SILC_LIST_END)
172       silc_sfree(asn1->orig_stack, t);
173   }
174
175   return ret;
176 }
177
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)                   \
182   type **name;                                                  \
183   if ((opts) & SILC_ASN1_OPTIONAL && !choice) {                 \
184     name = va_arg(asn1->ap, type **);                           \
185     if (!found) {                                               \
186       if (name)                                                 \
187         *name = NULL;                                           \
188       break;                                                    \
189     }                                                           \
190     if (name == NULL)                                           \
191       break;                                                    \
192     *name = silc_scalloc(SILC_ASN1_STACK(stack1, asn1),         \
193                          1, sizeof(**name));                    \
194     if (*name == NULL)                                          \
195       break;                                                    \
196   } else {                                                      \
197     type *name ## tmp = va_arg(asn1->ap, type *);               \
198     if (choice && found && !len)                                \
199       break;                                                    \
200     if (name ## tmp == NULL)                                    \
201       break;                                                    \
202     name = &name ## tmp;                                        \
203   }
204
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)                                  \
210     break;                                                      \
211   if (!found) {                                                 \
212     if (name)                                                   \
213       *name = NULL;                                             \
214     break;                                                      \
215   }                                                             \
216   if (name == NULL)                                             \
217     break;
218
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)                          \
223     break;                                              \
224   if (!found) {                                         \
225     if (name)                                           \
226       *name = NULL;                                     \
227     break;                                              \
228   }                                                     \
229   if (name == NULL)                                     \
230     break;
231
232 #define SILC_ASN1_VA_FREE(opts, name)           \
233   if ((opts) & SILC_ASN1_OPTIONAL)              \
234     silc_sfree(SILC_ASN1_STACK(stack1, asn1), *name);
235
236 /* Decodes string to UTF-8 string which is our internal representation
237    of any string. */
238 #define SILC_ASN1_DECODE_STRING(enc, s, s_len)                  \
239   *s_len = silc_utf8_encoded_len(rdata, rdata_len, (enc));      \
240   if (*s_len == 0) {                                            \
241     SILC_LOG_DEBUG(("Malformed %d string value", (enc)));       \
242     ret = FALSE;                                                \
243     goto fail;                                                  \
244   }                                                             \
245   *s = silc_smalloc(SILC_ASN1_STACK(stack1, asn1), *s_len + 1); \
246   if (*s) {                                                     \
247     silc_utf8_encode(rdata, rdata_len, (enc), *s, *s_len);      \
248     (*s)[*s_len] = '\0';                                        \
249   }
250
251
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. */
255
256 static SilcBool
257 silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type,
258                   SilcAsn1Tag tag, SilcBerClass ber_class,
259                   SilcAsn1Options opts, SilcBuffer src, SilcUInt32 depth,
260                   SilcBool primitive)
261 {
262   unsigned char *ptr = src->data;
263   SilcAsn1Tag rtype;
264   SilcAsn1Options ropts;
265   SilcBerClass rclass;
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;
272   int i;
273
274 #ifdef SILC_DEBUG
275   char sp[SILC_ASN1_RECURSION_DEPTH + 1];
276   memset(sp, 0, sizeof(sp));
277   if (depth)
278     memset(sp, 32, depth);
279 #endif /* SILC_DEBUG */
280
281   if (depth >= SILC_ASN1_RECURSION_DEPTH) {
282     SILC_LOG_DEBUG(("Maximum recursion depth reached"));
283     return FALSE;
284   }
285
286   while (1) {
287
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"));
294         ret = FALSE;
295         goto fail;
296       }
297
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) {
301         ret = TRUE;
302         goto ok;
303       }
304     }
305
306     /* Get length encoding */
307     indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
308
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;
317       } else {
318         if (tag != type ||
319             opts & SILC_ASN1_IMPLICIT ||
320             opts & SILC_ASN1_EXPLICIT)
321           ber_class = SILC_BER_CLASS_CONTEXT;
322       }
323     }
324
325     /* Short integer is actually big integer in the BER data, so handle
326        it correctly */
327     if (type == SILC_ASN1_TAG_SHORT_INTEGER && type == tag)
328       tag = SILC_ASN1_TAG_INTEGER;
329
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);
334     if (!ret) {
335       SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
336       return FALSE;
337     }
338
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(). */
344     while (1) {
345
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
349          been found. */
350       if (type == SILC_ASN1_TAG_CHOICE) {
351         choice_index = va_arg(asn1->ap, SilcUInt32 *);
352         *choice_index = 0;
353         choice = TRUE;
354         SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
355         opts |= SILC_ASN1_OPTIONAL;
356         found = FALSE;
357       }
358
359 #ifdef SILC_DEBUG
360       SILC_LOG_DEBUG(
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 */
370
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));
374           return FALSE;
375         }
376         if (!choice)
377           found = FALSE;
378
379       } else if (ber_class != rclass) {
380         if (!(opts & SILC_ASN1_OPTIONAL)) {
381           SILC_LOG_DEBUG(("Invalid ASN.1 class %d, expected %d",
382                           rclass, ber_class));
383           return FALSE;
384         }
385         if (!choice)
386           found = FALSE;
387
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"));
392         return FALSE;
393
394       } else if (rindef && renc == SILC_BER_ENC_PRIMITIVE) {
395         SILC_LOG_DEBUG(("Invalid length encoding for primitive type"));
396         return FALSE;
397
398       } else {
399         found = TRUE;
400       }
401
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);
406         len = 0;
407
408         primitive = (type != SILC_ASN1_TAG_SEQUENCE &&
409                      type != SILC_ASN1_TAG_SET &&
410                      type != SILC_ASN1_TAG_ANY);
411         opts &= ~SILC_ASN1_EXPLICIT;
412
413         ret = silc_asn1_decoder(asn1, stack1, type, type,
414                                 SILC_BER_CLASS_UNIVERSAL, opts, src,
415                                 depth + 1, primitive);
416         if (!ret)
417           goto fail;
418         if (primitive) {
419           primitive = FALSE;
420           goto cont;
421         }
422         goto ok;
423       }
424
425       /* Decode by the type user expects the data to be. */
426       switch (type) {
427
428       case SILC_ASN1_TAG_ANY:
429         {
430           /* ANY is another ASN.1 node.  We return the raw BER buffer as
431              the node */
432           SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, node);
433
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);
437           break;
438         }
439
440       case SILC_ASN1_TAG_ANY_PRIMITIVE:
441         {
442           /* ANY_PRIMITIVE returns the raw data blob of any primitive type. */
443           SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, prim);
444
445           *prim = silc_buffer_srealloc_size(SILC_ASN1_STACK(stack1, asn1),
446                                             *prim, rdata_len);
447           silc_buffer_put(*prim, rdata, rdata_len);
448           break;
449         }
450
451       case SILC_ASN1_TAG_SEQUENCE:
452       case SILC_ASN1_TAG_SET:
453         {
454           /* SEQUENCE/SET is a sequence of types. */
455           silc_buffer_pull(src, len);
456           len = 0;
457
458           /* Get type, tag and options for the first argument in recursion */
459           SILC_ASN1_ARGS(asn1, rtype, rtag, rclass, ropts);
460
461           /* Decode the sequence recursively */
462           ret = silc_asn1_decoder(asn1, SILC_ASN1_STACK(stack1, asn1),
463                                   rtype, rtag, rclass, ropts, src,
464                                   depth + 1, FALSE);
465           if (!ret)
466             goto fail;
467           break;
468         }
469
470       case SILC_ASN1_TAG_INTEGER:
471       case SILC_ASN1_TAG_ENUM:
472         {
473           /* Integer/enum value. */
474           SilcMPInt z;
475           SILC_ASN1_VAD(asn1, opts, SilcMPInt, intval);
476
477           if (rdata_len < 1) {
478             SILC_LOG_DEBUG(("Malformed integer value"));
479             SILC_ASN1_VA_FREE(opts, intval);
480             ret = FALSE;
481             goto fail;
482           }
483
484           silc_mp_sinit(SILC_ASN1_STACK(stack1, asn1), *intval);
485
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);
492             }
493
494             /* 2s complement and change sign */
495             silc_mp_init(&z);
496             silc_mp_set_ui(&z, 0);
497             silc_mp_add_ui(*intval, *intval, 1);
498             silc_mp_sub(*intval, &z, *intval);
499             silc_mp_uninit(&z);
500           } else {
501             /* Positive */
502             silc_mp_bin2mp((unsigned char *)rdata, rdata_len, *intval);
503           }
504
505           break;
506         }
507
508       case SILC_ASN1_TAG_SHORT_INTEGER:
509         {
510           /* Short Integer */
511           SilcMPInt z;
512           SILC_ASN1_VAD(asn1, opts, SilcUInt32, intval);
513
514           if (rdata_len < 1) {
515             SILC_LOG_DEBUG(("Malformed integer value"));
516             SILC_ASN1_VA_FREE(opts, intval);
517             ret = FALSE;
518             goto fail;
519           }
520
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);
525           silc_mp_uninit(&z);
526           silc_stack_pop(SILC_ASN1_STACK(stack1, asn1));
527           break;
528         }
529
530       case SILC_ASN1_TAG_OID:
531         {
532           /* Object identifier */
533           SilcBufferStruct tmpb;
534           char tmpstr[24];
535           SilcUInt32 oid;
536           SILC_ASN1_VAD_CHAR(asn1, opts, char, oidstr);
537
538           if (rdata_len < 1) {
539             SILC_LOG_DEBUG(("Malformed object identifier value"));
540             SILC_ASN1_VA_FREE(opts, oidstr);
541             ret = FALSE;
542             goto fail;
543           }
544
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);
553
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++) {
558             oid = 0;
559             while (rdata[i] & 0x80) {
560               oid <<= 7;
561               oid |= rdata[i++] & 0x7f;
562               if (i >= rdata_len) {
563                 SILC_LOG_DEBUG(("Malformed object identifier value"));
564                 break;
565               }
566             }
567             oid <<= 7;
568             oid |= rdata[i];
569
570             memset(tmpstr, 0, sizeof(tmpstr));
571             silc_snprintf(tmpstr, sizeof(tmpstr) - 1, ".%lu",
572                           (unsigned long)oid);
573             silc_buffer_sstrformat(SILC_ASN1_STACK(stack1, asn1),
574                                    &tmpb, tmpstr, SILC_STR_END);
575           }
576           *oidstr = tmpb.head;
577
578           break;
579         }
580
581       case SILC_ASN1_TAG_BOOLEAN:
582         {
583           /* Decode boolean (TRUE/FALSE) value */
584           SILC_ASN1_VAD(asn1, opts, SilcBool, val);
585
586           if (rdata_len != 1) {
587             SILC_LOG_DEBUG(("Malformed boolean value"));
588             SILC_ASN1_VA_FREE(opts, val);
589             ret = FALSE;
590             goto fail;
591           }
592
593           *(*val) = (rdata[0] == 0xff ? TRUE : FALSE);
594           break;
595         }
596
597       case SILC_ASN1_TAG_BIT_STRING:
598         {
599           /* Bit string contains data with exact bit length of the data */
600           SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, d, d_len);
601
602           if (rdata_len < 2) {
603             SILC_LOG_DEBUG(("Malformed bit string value"));
604             SILC_ASN1_VA_FREE(opts, d);
605             ret = FALSE;
606             goto fail;
607           }
608
609           *d = silc_smemdup(SILC_ASN1_STACK(stack1, asn1),
610                             rdata + 1, rdata_len - 1);
611           *d_len = (rdata_len - 1) * 8;
612           break;
613         }
614
615       case SILC_ASN1_TAG_NULL:
616         {
617           SILC_ASN1_VAD(asn1, opts, SilcBool, val);
618
619           /* Decode empty BER block */
620           if (rdata_len != 0) {
621             SILC_LOG_DEBUG(("Malformed null value"));
622             goto fail;
623           }
624
625           *(*val) = TRUE;
626           break;
627         }
628
629       case SILC_ASN1_TAG_UTC_TIME:
630         {
631           /* Universal encoded time string */
632           SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
633
634           if (rdata_len < 1) {
635             SILC_LOG_DEBUG(("Malformed UTC time value"));
636             SILC_ASN1_VA_FREE(opts, t);
637             ret = FALSE;
638             goto fail;
639           }
640
641           /* Parse the time string */
642           if (!silc_time_universal(rdata, *t)) {
643             SILC_LOG_DEBUG(("Malformed UTC time value"));
644             ret = FALSE;
645             goto fail;
646           }
647
648           break;
649         }
650
651       case SILC_ASN1_TAG_GENERALIZED_TIME:
652         {
653           /* Generalized encoded time string */
654           SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
655
656           if (rdata_len < 1) {
657             SILC_LOG_DEBUG(("Malformed generalized time value"));
658             SILC_ASN1_VA_FREE(opts, t);
659             ret = FALSE;
660             goto fail;
661           }
662
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);
667             ret = FALSE;
668             goto fail;
669           }
670
671           break;
672         }
673
674       case SILC_ASN1_TAG_UTF8_STRING:
675         {
676           /* UTF-8 encoded string */
677           SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
678
679           if (!silc_utf8_valid(rdata, rdata_len)) {
680             SILC_LOG_DEBUG(("Malformed UTF-8 string value"));
681             SILC_ASN1_VA_FREE(opts, s);
682             ret = FALSE;
683             goto fail;
684           }
685
686           *s = silc_smemdup(SILC_ASN1_STACK(stack1, asn1), rdata, rdata_len);
687           *s_len = rdata_len;
688           break;
689         }
690
691       case SILC_ASN1_TAG_OCTET_STRING:
692         {
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);
696           *s_len = rdata_len;
697           break;
698         }
699
700       case SILC_ASN1_TAG_NUMERIC_STRING:
701         {
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);
705           break;
706         }
707
708       case SILC_ASN1_TAG_PRINTABLE_STRING:
709         {
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);
713           break;
714         }
715
716       case SILC_ASN1_TAG_TELETEX_STRING:
717         {
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);
721           break;
722         }
723
724       case SILC_ASN1_TAG_IA5_STRING:
725         {
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);
729           break;
730         }
731
732       case SILC_ASN1_TAG_VISIBLE_STRING:
733         {
734           /* 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);
737           break;
738         }
739
740       case SILC_ASN1_TAG_UNIVERSAL_STRING:
741         {
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);
745           break;
746         }
747
748       case SILC_ASN1_TAG_UNRESTRICTED_STRING:
749       case SILC_ASN1_TAG_GENERAL_STRING:
750         {
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);
755           break;
756         }
757
758       case SILC_ASN1_TAG_BMP_STRING:
759         {
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);
763           break;
764         }
765
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:
773         {
774           SILC_NOT_IMPLEMENTED("Unsupported ASN.1 tag");
775           ret = FALSE;
776           goto fail;
777           break;
778         }
779
780       default:
781         SILC_LOG_DEBUG(("Invalid ASN.1 tag `%d'. Cannot decode ASN.1.",
782                         type));
783         ret = FALSE;
784         goto fail;
785         break;
786       }
787
788     cont:
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);
792       if (primitive) {
793         ret = TRUE;
794         goto ok;
795       }
796
797       /* Get next type, tag and options */
798       rtype = type;
799       SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
800       if (type == SILC_ASN1_END) {
801         if (choice) {
802           if (!found) {
803             /* No choices were found, error */
804             SILC_LOG_DEBUG(("Invalid ASN.1 choice: no choices present"));
805             *choice_index = 0;
806             ret = FALSE;
807             goto fail;
808           }
809
810           if (!choice_found) {
811             (*choice_index)++;
812             SILC_LOG_DEBUG(("Found choice %s type, index %d",
813                             silc_asn1_tag_name(rtype), *choice_index));
814           }
815
816           /* Take next type and new BER object, choices are over */
817           choice = FALSE;
818           SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
819           if (type == SILC_ASN1_END) {
820             ret = TRUE;
821             goto ok;
822           }
823           break;
824         }
825
826         /* SEQUENCE/SET end */
827         ret = TRUE;
828         goto ok;
829       }
830
831       if (choice) {
832         if (!choice_found)
833           (*choice_index)++;
834
835         /* Even if the choice was found we must go through rest of
836            the choices. */
837         if (found && len) {
838           choice_found = TRUE;
839           SILC_LOG_DEBUG(("Found choice %s type, index %d",
840                           silc_asn1_tag_name(rtype), *choice_index));
841           rdata_len = len = 0;
842         }
843         opts |= SILC_ASN1_OPTIONAL;
844         continue;
845       }
846
847       /* Optional type not present, check next one for match */
848       if (!found)
849         continue;
850
851       break;
852     }
853   }
854
855  fail:
856   SILC_LOG_DEBUG(("Error decoding type %d (depth %d)", type, depth));
857
858  ok:
859   if (ptr)
860     len = src->data - ptr;
861   else
862     len = src->data - src->head;
863   silc_buffer_push(src, len);
864
865   return ret;
866 }
867
868 SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...)
869 {
870   SilcAsn1Tag type, tag;
871   SilcAsn1Options opts;
872   SilcBerClass ber_class;
873   SilcStackFrame frame1, frame2;
874   SilcStack stack1 = NULL, stack2 = NULL, orig;
875   SilcBool ret;
876
877   if (!asn1)
878     return FALSE;
879
880   va_start(asn1->ap, src);
881
882   orig = asn1->orig_stack;
883
884   /* Get the first arguments and call the decoder. */
885   SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
886   if (!type) {
887     va_end(asn1->ap);
888     return FALSE;
889   }
890
891   /* Handle internal options for decoder. */
892   if (type == SILC_ASN1_TAG_OPTS) {
893     SilcUInt32 o = va_arg(asn1->ap, SilcUInt32);
894
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;
900       asn1->stack1 = NULL;
901       asn1->stack2 = NULL;
902       asn1->orig_stack = orig;
903     }
904
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);
910         asn1->accumul = 1;
911       }
912     }
913
914     /* Take again the arguments */
915     SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
916   } else {
917     /* No flags set, all flags will be reset. */
918
919     /* If accumul flag is set now pop the stack so that all accumulated
920        memory becomes free again. */
921     if (asn1->accumul) {
922       silc_stack_pop(asn1->stack1);
923       silc_stack_pop(asn1->stack2);
924       asn1->accumul = 0;
925     }
926   }
927
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);
932   }
933
934   /* Start decoding */
935   ret = silc_asn1_decoder(asn1, asn1->stack1, type, tag, ber_class,
936                           opts, src, 0, FALSE);
937
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);
943
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;
951       asn1->switched = !asn1->switched;
952     }
953   }
954
955   if (stack1 && stack2 && !asn1->stack1 && !asn1->stack2) {
956     /* SILC_ASN1_ALLOC flag was set, restore the stacks. */
957     asn1->stack1 = stack1;
958     asn1->stack2 = stack2;
959   }
960
961   asn1->orig_stack = orig;
962
963   va_end(asn1->ap);
964
965   return ret;
966 }