Merged silc_1_1_branch to trunk.
[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 /************************** ASN.1 Decoder routines **************************/
25
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. */
30
31 static SilcBool silc_asn1_decoder_sof(SilcAsn1 asn1, SilcBuffer src)
32 {
33   SilcBool ret = FALSE;
34   SilcList types;
35   SilcAsn1Tag type;
36   SilcBuffer *retb;
37   SilcUInt32 *retc, rtag;
38   const unsigned char *rdata;
39   SilcUInt32 rdata_len, len = 0;
40   SilcBool found = FALSE, rindef;
41
42   struct SilcAsn1SofStruct {
43     SilcAsn1Tag type;
44     struct SilcAsn1SofStruct *next;
45   } *t = NULL;
46
47   SILC_LOG_DEBUG(("Decoding sequence of types"));
48
49   silc_list_init(types, struct SilcAsn1SofStruct, next);
50
51   /* Take the return arguments */
52   retb = va_arg(asn1->ap, SilcBuffer *);
53   retc = va_arg(asn1->ap, SilcUInt32 *);
54   *retb = NULL;
55   *retc = 0;
56
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);
62
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));
69       if (!t)
70         goto out;
71       t->type = type;
72       silc_list_add(types, t);
73
74       SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
75                       silc_asn1_tag_name(type), type));
76
77       type = va_arg(asn1->ap, SilcUInt32);
78     }
79   } else {
80     /* The sequence consists of this type. */
81     t = silc_smalloc(asn1->stack1, sizeof(*t));
82     if (!t)
83       goto out;
84     t->type = type;
85     silc_list_add(types, t);
86
87     SILC_LOG_DEBUG(("Looking for %s [%d] from sequence of types",
88                     silc_asn1_tag_name(type), type));
89   }
90
91   /* END marker for the sequence */
92   type = va_arg(asn1->ap, SilcUInt32);
93   assert(type == SILC_ASN1_END);
94
95   /* Decode the SEQUENCE or SET */
96   ret = silc_ber_decode(src, NULL, NULL, &rtag, &rdata,
97                         &rdata_len, &rindef, &len);
98   if (!ret) {
99     SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
100     goto out;
101   }
102   if (rtag != SILC_ASN1_TAG_SEQUENCE && rtag != SILC_ASN1_TAG_SET) {
103     SILC_LOG_DEBUG(("Invalid sequence of/set of"));
104     goto out;
105   }
106   silc_buffer_pull(src, len);
107
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);
112     if (!ret) {
113       SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
114       goto out;
115     }
116
117     /* Now check the type(s) that it is supposed to be */
118     found = FALSE;
119     silc_list_start(types);
120     while ((t = silc_list_get(types)) != SILC_LIST_END) {
121       if (t->type != rtag)
122         continue;
123
124       *retb = silc_srealloc(asn1->stack1, sizeof(**retb) * (*retc), *retb,
125                             sizeof(**retb) * (*retc + 1));
126       if (*retb == NULL)
127         goto out;
128
129       SILC_LOG_DEBUG(("Decode %s [%d] from sequence of types",
130                       silc_asn1_tag_name(rtag), rtag));
131
132       /* Data is duplicated only if SILC_ASN1_ALLOC flag is set */
133       if (!asn1->stack1)
134         rdata = silc_memdup(rdata - len, rdata_len + len);
135       else
136         rdata = rdata - len;
137       rdata_len += len;
138
139       /* Save the data */
140       silc_buffer_set(&(*retb)[*retc], (unsigned char *)rdata, rdata_len);
141       (*retc)++;
142       found = TRUE;
143       break;
144     }
145
146     /* If type was not found we consider it the end of the sequence */
147     if (found == FALSE)
148       break;
149
150     if (rdata_len)
151       silc_buffer_pull(src, rdata_len);
152   }
153
154   SILC_LOG_DEBUG(("Decoded %d types", *retc));
155   ret = TRUE;
156
157  out:
158   if (!asn1->stack1) {
159     silc_list_start(types);
160     while ((t = silc_list_get(types)) != SILC_LIST_END)
161       silc_free(t);
162   }
163
164   return ret;
165 }
166
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)                   \
171   type **name;                                                  \
172   if ((opts) & SILC_ASN1_OPTIONAL && !choice) {                 \
173     name = va_arg(asn1->ap, type **);                           \
174     if (!found) {                                               \
175       if (name)                                                 \
176         *name = NULL;                                           \
177       break;                                                    \
178     }                                                           \
179     if (name == NULL)                                           \
180       break;                                                    \
181     *name = silc_scalloc(asn1->stack1, 1, sizeof(**name));      \
182     if (*name == NULL)                                          \
183       break;                                                    \
184   } else {                                                      \
185     type *name ## tmp = va_arg(asn1->ap, type *);               \
186     if (choice && found && !len)                                \
187       break;                                                    \
188     if (name ## tmp == NULL)                                    \
189       break;                                                    \
190     name = &name ## tmp;                                        \
191   }
192
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)                                  \
198     break;                                                      \
199   if (!found) {                                                 \
200     if (name)                                                   \
201       *name = NULL;                                             \
202     break;                                                      \
203   }                                                             \
204   if (name == NULL)                                             \
205     break;
206
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)                          \
211     break;                                              \
212   if (!found) {                                         \
213     if (name)                                           \
214       *name = NULL;                                     \
215     break;                                              \
216   }                                                     \
217   if (name == NULL)                                     \
218     break;
219
220 #define SILC_ASN1_VA_FREE(opts, name)           \
221   if ((opts) & SILC_ASN1_OPTIONAL)              \
222     silc_free(*name);
223
224 /* Decodes string to UTF-8 string which is our internal representation
225    of any string. */
226 #define SILC_ASN1_DECODE_STRING(enc, s, s_len)                  \
227   *s_len = silc_utf8_encoded_len(rdata, rdata_len, (enc));      \
228   if (*s_len == 0) {                                            \
229     SILC_LOG_DEBUG(("Malformed %d string value", (enc)));       \
230     ret = FALSE;                                                \
231     goto fail;                                                  \
232   }                                                             \
233   *s = silc_smalloc(stack1, *s_len + 1);                        \
234   if (*s) {                                                     \
235     silc_utf8_encode(rdata, rdata_len, (enc), *s, *s_len);      \
236     (*s)[*s_len] = '\0';                                        \
237   }
238
239
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. */
243
244 static SilcBool
245 silc_asn1_decoder(SilcAsn1 asn1, SilcStack stack1, SilcAsn1Tag type,
246                   SilcAsn1Tag tag, SilcBerClass ber_class,
247                   SilcAsn1Options opts, SilcBuffer src, SilcUInt32 depth,
248                   SilcBool primitive)
249 {
250   unsigned char *ptr = src->data;
251   SilcAsn1Tag rtype;
252   SilcAsn1Options ropts;
253   SilcBerClass rclass;
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;
259   int i;
260
261 #ifdef SILC_DEBUG
262   char sp[SILC_ASN1_RECURSION_DEPTH + 1];
263   memset(sp, 0, sizeof(sp));
264   if (depth)
265     memset(sp, 32, depth);
266 #endif /* SILC_DEBUG */
267
268   if (depth >= SILC_ASN1_RECURSION_DEPTH) {
269     SILC_LOG_DEBUG(("Maximum recursion depth reached"));
270     return FALSE;
271   }
272
273   while (1) {
274
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"));
281         ret = FALSE;
282         goto fail;
283       }
284
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) {
288         ret = TRUE;
289         goto ok;
290       }
291     }
292
293     /* Get length encoding */
294     indef = (opts & SILC_ASN1_INDEFINITE ? TRUE : FALSE);
295
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;
304       } else {
305         if (tag != type ||
306             opts & SILC_ASN1_IMPLICIT ||
307             opts & SILC_ASN1_EXPLICIT)
308           ber_class = SILC_BER_CLASS_CONTEXT;
309       }
310     }
311
312     /* Short integer is actually big integer in the BER data, so handle
313        it correctly */
314     if (type == SILC_ASN1_TAG_SHORT_INTEGER && type == tag)
315       tag = SILC_ASN1_TAG_INTEGER;
316
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);
321     if (!ret) {
322       SILC_LOG_DEBUG(("Error parsing BER block, malformed ASN.1 data"));
323       return FALSE;
324     }
325
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(). */
331     while (1) {
332
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
336          been found. */
337       if (type == SILC_ASN1_TAG_CHOICE) {
338         choice = TRUE;
339         SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
340         opts |= SILC_ASN1_OPTIONAL;
341         found = FALSE;
342       }
343
344 #ifdef SILC_DEBUG
345       SILC_LOG_DEBUG(
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 */
355
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));
359           return FALSE;
360         }
361         if (!choice)
362           found = FALSE;
363
364       } else if (ber_class != rclass) {
365         if (!(opts & SILC_ASN1_OPTIONAL)) {
366           SILC_LOG_DEBUG(("Invalid ASN.1 class %d, expected %d",
367                           rclass, ber_class));
368           return FALSE;
369         }
370         if (!choice)
371           found = FALSE;
372
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"));
377         return FALSE;
378
379       } else if (rindef && renc == SILC_BER_ENC_PRIMITIVE) {
380         SILC_LOG_DEBUG(("Invalid length encoding for primitive type"));
381         return FALSE;
382
383       } else {
384         found = TRUE;
385       }
386
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);
391         len = 0;
392
393         primitive = (type != SILC_ASN1_TAG_SEQUENCE &&
394                      type != SILC_ASN1_TAG_SET &&
395                      type != SILC_ASN1_TAG_ANY);
396         opts &= ~SILC_ASN1_EXPLICIT;
397
398         ret = silc_asn1_decoder(asn1, stack1, type, type,
399                                 SILC_BER_CLASS_UNIVERSAL, opts, src,
400                                 depth + 1, primitive);
401         if (!ret)
402           goto fail;
403         if (primitive) {
404           primitive = FALSE;
405           goto cont;
406         }
407         goto ok;
408       }
409
410       /* Decode by the type user expects the data to be. */
411       switch (type) {
412
413       case SILC_ASN1_TAG_ANY:
414         {
415           /* ANY is another ASN.1 node.  We return the raw BER buffer as
416              the node */
417           SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, node);
418
419           *node = silc_buffer_srealloc_size(stack1, *node, len + rdata_len);
420           silc_buffer_put(*node, rdata - len, rdata_len + len);
421           break;
422         }
423
424       case SILC_ASN1_TAG_ANY_PRIMITIVE:
425         {
426           /* ANY_PRIMITIVE returns the raw data blob of any primitive type. */
427           SILC_ASN1_VAD(asn1, opts, SilcBufferStruct, prim);
428
429           *prim = silc_buffer_srealloc_size(stack1, *prim, rdata_len);
430           silc_buffer_put(*prim, rdata, rdata_len);
431           break;
432         }
433
434       case SILC_ASN1_TAG_SEQUENCE:
435       case SILC_ASN1_TAG_SET:
436         {
437           /* SEQUENCE/SET is a sequence of types. */
438           silc_buffer_pull(src, len);
439           len = 0;
440
441           /* Get type, tag and options for the first argument in recursion */
442           SILC_ASN1_ARGS(asn1, rtype, rtag, rclass, ropts);
443
444           /* Decode the sequence recursively */
445           ret = silc_asn1_decoder(asn1, stack1, rtype, rtag, rclass,
446                                   ropts, src, depth + 1, FALSE);
447           if (!ret)
448             goto fail;
449           break;
450         }
451
452       case SILC_ASN1_TAG_INTEGER:
453       case SILC_ASN1_TAG_ENUM:
454         {
455           /* Integer/enum value. */
456           SilcMPInt z;
457           SILC_ASN1_VAD(asn1, opts, SilcMPInt, intval);
458
459           if (rdata_len < 1) {
460             SILC_LOG_DEBUG(("Malformed integer value"));
461             SILC_ASN1_VA_FREE(opts, intval);
462             ret = FALSE;
463             goto fail;
464           }
465
466           silc_mp_sinit(asn1->stack1, *intval);
467
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);
474             }
475
476             /* 2s complement and change sign */
477             silc_mp_init(&z);
478             silc_mp_set_ui(&z, 0);
479             silc_mp_add_ui(*intval, *intval, 1);
480             silc_mp_sub(*intval, &z, *intval);
481             silc_mp_uninit(&z);
482           } else {
483             /* Positive */
484             silc_mp_bin2mp((unsigned char *)rdata, rdata_len, *intval);
485           }
486
487           break;
488         }
489
490       case SILC_ASN1_TAG_SHORT_INTEGER:
491         {
492           /* Short Integer */
493           SilcMPInt z;
494           SILC_ASN1_VAD(asn1, opts, SilcUInt32, intval);
495
496           if (rdata_len < 1) {
497             SILC_LOG_DEBUG(("Malformed integer value"));
498             SILC_ASN1_VA_FREE(opts, intval);
499             ret = FALSE;
500             goto fail;
501           }
502
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);
507           silc_mp_uninit(&z);
508           silc_stack_pop(asn1->stack1);
509           break;
510         }
511
512       case SILC_ASN1_TAG_OID:
513         {
514           /* Object identifier */
515           SilcBufferStruct tmpb;
516           char tmpstr[24];
517           SilcUInt32 oid;
518           SILC_ASN1_VAD_CHAR(asn1, opts, char, oidstr);
519
520           if (rdata_len < 1) {
521             SILC_LOG_DEBUG(("Malformed object identifier value"));
522             SILC_ASN1_VA_FREE(opts, oidstr);
523             ret = FALSE;
524             goto fail;
525           }
526
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);
534
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++) {
539             oid = 0;
540             while (rdata[i] & 0x80) {
541               oid <<= 7;
542               oid |= rdata[i++] & 0x7f;
543               if (i >= rdata_len) {
544                 SILC_LOG_DEBUG(("Malformed object identifier value"));
545                 break;
546               }
547             }
548             oid <<= 7;
549             oid |= rdata[i];
550
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);
554           }
555           *oidstr = tmpb.head;
556
557           break;
558         }
559
560       case SILC_ASN1_TAG_BOOLEAN:
561         {
562           /* Decode boolean (TRUE/FALSE) value */
563           SILC_ASN1_VAD(asn1, opts, SilcBool, val);
564
565           if (rdata_len != 1) {
566             SILC_LOG_DEBUG(("Malformed boolean value"));
567             SILC_ASN1_VA_FREE(opts, val);
568             ret = FALSE;
569             goto fail;
570           }
571
572           *(*val) = (rdata[0] == 0xff ? TRUE : FALSE);
573           break;
574         }
575
576       case SILC_ASN1_TAG_BIT_STRING:
577         {
578           /* Bit string contains data with exact bit length of the data */
579           SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, d, d_len);
580
581           if (rdata_len < 2) {
582             SILC_LOG_DEBUG(("Malformed bit string value"));
583             SILC_ASN1_VA_FREE(opts, d);
584             ret = FALSE;
585             goto fail;
586           }
587
588           *d = silc_smemdup(stack1, rdata + 1, rdata_len - 1);
589           *d_len = (rdata_len - 1) * 8;
590           break;
591         }
592
593       case SILC_ASN1_TAG_NULL:
594         {
595           /* Decode empty BER block */
596           if (rdata_len != 0) {
597             SILC_LOG_DEBUG(("Malformed null value"));
598             goto fail;
599           }
600           break;
601         }
602
603       case SILC_ASN1_TAG_UTC_TIME:
604         {
605           /* Universal encoded time string */
606           SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
607
608           if (rdata_len < 1) {
609             SILC_LOG_DEBUG(("Malformed UTC time value"));
610             SILC_ASN1_VA_FREE(opts, t);
611             ret = FALSE;
612             goto fail;
613           }
614
615           /* Parse the time string */
616           if (!silc_time_universal(rdata, *t)) {
617             SILC_LOG_DEBUG(("Malformed UTC time value"));
618             ret = FALSE;
619             goto fail;
620           }
621
622           break;
623         }
624
625       case SILC_ASN1_TAG_GENERALIZED_TIME:
626         {
627           /* Generalized encoded time string */
628           SILC_ASN1_VAD(asn1, opts, SilcTimeStruct, t);
629
630           if (rdata_len < 1) {
631             SILC_LOG_DEBUG(("Malformed generalized time value"));
632             SILC_ASN1_VA_FREE(opts, t);
633             ret = FALSE;
634             goto fail;
635           }
636
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);
641             ret = FALSE;
642             goto fail;
643           }
644
645           break;
646         }
647
648       case SILC_ASN1_TAG_UTF8_STRING:
649         {
650           /* UTF-8 encoded string */
651           SILC_ASN1_VAD_UCHAR(asn1, opts, unsigned char, s, s_len);
652
653           if (!silc_utf8_valid(rdata, rdata_len)) {
654             SILC_LOG_DEBUG(("Malformed UTF-8 string value"));
655             SILC_ASN1_VA_FREE(opts, s);
656             ret = FALSE;
657             goto fail;
658           }
659
660           *s = silc_smemdup(stack1, rdata, rdata_len);
661           *s_len = rdata_len;
662           break;
663         }
664
665       case SILC_ASN1_TAG_OCTET_STRING:
666         {
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);
670           *s_len = rdata_len;
671           break;
672         }
673
674       case SILC_ASN1_TAG_NUMERIC_STRING:
675         {
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);
679           break;
680         }
681
682       case SILC_ASN1_TAG_PRINTABLE_STRING:
683         {
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);
687           break;
688         }
689
690       case SILC_ASN1_TAG_TELETEX_STRING:
691         {
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);
695           break;
696         }
697
698       case SILC_ASN1_TAG_IA5_STRING:
699         {
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);
703           break;
704         }
705
706       case SILC_ASN1_TAG_VISIBLE_STRING:
707         {
708           /* 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);
711           break;
712         }
713
714       case SILC_ASN1_TAG_UNIVERSAL_STRING:
715         {
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);
719           break;
720         }
721
722       case SILC_ASN1_TAG_UNRESTRICTED_STRING:
723       case SILC_ASN1_TAG_GENERAL_STRING:
724         {
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);
729           break;
730         }
731
732       case SILC_ASN1_TAG_BMP_STRING:
733         {
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);
737           break;
738         }
739
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:
747         {
748           SILC_NOT_IMPLEMENTED("Unsupported ASN.1 tag");
749           ret = FALSE;
750           goto fail;
751           break;
752         }
753
754       default:
755         SILC_LOG_DEBUG(("Invalid ASN.1 tag `%d'. Cannot decode ASN.1.",
756                         type));
757         ret = FALSE;
758         goto fail;
759         break;
760       }
761
762     cont:
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);
766       if (primitive) {
767         ret = TRUE;
768         goto ok;
769       }
770
771       /* Get next type, tag and options */
772       rtype = type;
773       SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
774       if (type == SILC_ASN1_END) {
775         if (choice) {
776           if (!found) {
777             /* No choices were found, error */
778             SILC_LOG_DEBUG(("Invalid ASN.1 choice: no choices present"));
779             ret = FALSE;
780             goto fail;
781           }
782
783           /* Take next type and new BER object, choices are over */
784           choice = FALSE;
785           SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
786           if (type == SILC_ASN1_END) {
787             ret = TRUE;
788             goto ok;
789           }
790           break;
791         }
792
793         /* SEQUENCE/SET end */
794         ret = TRUE;
795         goto ok;
796       }
797
798       if (choice) {
799         /* Even if the choice was found we must go through rest of
800            the choices. */
801         if (found && len) {
802           SILC_LOG_DEBUG(("Found choice %s type", silc_asn1_tag_name(rtype)));
803           rdata_len = len = 0;
804         }
805         opts |= SILC_ASN1_OPTIONAL;
806         continue;
807       }
808
809       /* Optional type not present, check next one for match */
810       if (!found)
811         continue;
812
813       break;
814     }
815   }
816
817  fail:
818   SILC_LOG_DEBUG(("Error decoding type %d (depth %d)", type, depth));
819
820  ok:
821   if (ptr)
822     len = src->data - ptr;
823   else
824     len = src->data - src->head;
825   silc_buffer_push(src, len);
826
827   return ret;
828 }
829
830 SilcBool silc_asn1_decode(SilcAsn1 asn1, SilcBuffer src, ...)
831 {
832   SilcAsn1Tag type, tag;
833   SilcAsn1Options opts;
834   SilcBerClass ber_class;
835   SilcStackFrame frame1, frame2;
836   SilcStack stack1 = NULL, stack2 = NULL;
837   SilcBool ret;
838
839   if (!asn1)
840     return FALSE;
841
842   va_start(asn1->ap, src);
843
844   /* Get the first arguments and call the decoder. */
845   SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
846   if (!type) {
847     va_end(asn1->ap);
848     return FALSE;
849   }
850
851   /* Handle internal options for decoder. */
852   if (type == SILC_ASN1_TAG_OPTS) {
853     SilcUInt32 o = va_arg(asn1->ap, SilcUInt32);
854
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;
860       asn1->stack1 = NULL;
861       asn1->stack2 = NULL;
862     }
863
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);
869         asn1->accumul = 1;
870       }
871     }
872
873     /* Take again the arguments */
874     SILC_ASN1_ARGS(asn1, type, tag, ber_class, opts);
875   } else {
876     /* No flags set, all flags will be reset. */
877
878     /* If accumul flag is set now pop the stack so that all accumulated
879        memory becomes free again. */
880     if (asn1->accumul) {
881       silc_stack_pop(asn1->stack1);
882       silc_stack_pop(asn1->stack2);
883       asn1->accumul = 0;
884     }
885   }
886
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);
891   }
892
893   /* Start decoding */
894   ret = silc_asn1_decoder(asn1, asn1->stack1, type, tag, ber_class,
895                           opts, src, 0, FALSE);
896
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);
902
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;
910     }
911   }
912
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;
917   }
918
919   va_end(asn1->ap);
920
921   return ret;
922 }