Note that we could save some overhead if we require the name argument to
[obnox/wireshark/wip.git] / asn1.c
1 /* asn1.c
2  * Routines for ASN.1 BER dissection
3  *
4  * $Id: asn1.c,v 1.10 2002/02/21 02:05:53 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  *
9  * Based on "g_asn1.c" from:
10  *
11  * GXSNMP -- An snmp mangament application
12  * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
13  * Beholder RMON ethernet network monitor, Copyright (C) 1993 DNPAP group
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28  */
29
30 /*
31  * MODULE INFORMATION
32  * ------------------ 
33  *     FILE     NAME:       g_asn1.c
34  *     SYSTEM   NAME:       ASN1 Basic Encoding
35  *     ORIGINAL AUTHOR(S):  Dirk Wisse
36  *     VERSION  NUMBER:     1
37  *     CREATION DATE:       1990/11/22
38  *
39  * DESCRIPTION: ASN1 Basic Encoding Rules.
40  *
41  *              To decode this we must do:
42  *
43  *              asn1_open (asn1, tvb, offset);
44  *              asn1_header_decode (asn1, &end_of_seq, cls, con, tag, def, len);
45  *              asn1_header_decode (asn1, &end_of_octs, cls, con, tag, def, len);
46  *              asn1_octets_decode (asn1, end_of_octs, str, len);
47  *              asn1_header_decode (asn1, &end_of_int, cls, con, tag);
48  *              asn1_int_decode (asn1, end_of_int, &integer);
49  *              asn1_eoc_decode (asn1, end_of_seq);
50  *              asn1_close (asn1, &offset);
51  *              
52  *              For indefinite encoding end_of_seq and &end_of_seq in the
53  *              example above should be replaced by NULL.
54  *              For indefinite decoding nothing has to be changed.
55  *              This can be very useful if you want to decode both
56  *              definite and indefinite encodings.
57  */
58
59 #ifdef HAVE_CONFIG_H
60 # include "config.h"
61 #endif
62
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
65 #endif
66
67 #ifdef HAVE_WINSOCK_H
68 #include <winsock.h>
69 #endif
70
71 #include <limits.h>
72
73 #include <glib.h>
74 #include <epan/tvbuff.h>
75 #include "asn1.h"
76
77 /*
78  * NAME:        asn1_open                                   [API]
79  * SYNOPSIS:    void asn1_open
80  *                  (
81  *                      ASN1_SCK *asn1,
82  *                      tvbuff_t *tvb,
83  *                      int       offset
84  *                  )
85  * DESCRIPTION: Opens an ASN1 socket.
86  *              Parameters:
87  *              asn1:   pointer to ASN1 socket.
88  *              tvb:    Tvbuff for encoding.
89  *              offset: Current offset in tvbuff.
90  *              Encoding starts at the end of the buffer, and
91  *              proceeds to the beginning.
92  * RETURNS:     void
93  */
94
95 void
96 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
97 {
98     asn1->tvb = tvb;
99     asn1->offset = offset;
100 }
101
102 /*
103  * NAME:        asn1_close                                  [API]
104  * SYNOPSIS:    void asn1_close
105  *                  (
106  *                      ASN1_SCK   *asn1,
107  *                      int        *offset
108  *                  )
109  * DESCRIPTION: Closes an ASN1 socket.
110  *              Parameters:
111  *              asn1:   pointer to ASN1 socket.
112  *              offset: pointer to variable into which current offset is
113  *              to be put.
114  * RETURNS:     void
115  */
116
117 void 
118 asn1_close(ASN1_SCK *asn1, int *offset)
119 {
120     *offset = asn1->offset;
121 }
122
123 /*
124  * NAME:        asn1_octet_decode
125  * SYNOPSIS:    int asn1_octet_decode
126  *                  (
127  *                      ASN1_SCK *asn1,
128  *                      guchar   *ch
129  *                  )
130  * DESCRIPTION: Decodes an octet.
131  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
132  */
133 int
134 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
135 {
136     *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
137     asn1->offset++;
138     return ASN1_ERR_NOERROR;
139 }
140
141 /*
142  * NAME:        asn1_tag_decode
143  * SYNOPSIS:    int asn1_tag_decode
144  *                  (
145  *                      ASN1_SCK *asn1,
146  *                      guint    *tag
147  *                  )
148  * DESCRIPTION: Decodes a tag.
149  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
150  */
151 int
152 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
153 {
154     int    ret;
155     guchar ch;
156
157     *tag = 0;
158     do {
159         ret = asn1_octet_decode (asn1, &ch);
160         if (ret != ASN1_ERR_NOERROR)
161             return ret;
162         *tag <<= 7;
163         *tag |= ch & 0x7F;
164     } while ((ch & 0x80) == 0x80);
165     return ASN1_ERR_NOERROR;
166 }
167
168 /*
169  * NAME:        asn1_id_decode
170  * SYNOPSIS:    int asn1_id_decode
171  *                  (
172  *                      ASN1_SCK *asn1,
173  *                      guint    *cls,
174  *                      guint    *con,
175  *                      guint    *tag
176  *                  )
177  * DESCRIPTION: Decodes an identifier.
178  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
179  */
180 int
181 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
182 {
183     int    ret;
184     guchar ch;
185
186     ret = asn1_octet_decode (asn1, &ch);
187     if (ret != ASN1_ERR_NOERROR)
188         return ret;
189     *cls = (ch & 0xC0) >> 6;
190     *con = (ch & 0x20) >> 5;
191     *tag = (ch & 0x1F);
192     if (*tag == 0x1F) {
193         ret = asn1_tag_decode (asn1, tag);
194         if (ret != ASN1_ERR_NOERROR)
195             return ret;
196     }
197     return ASN1_ERR_NOERROR;
198 }
199
200 /*
201  * NAME:        asn1_length_decode
202  * SYNOPSIS:    int asn1_length_decode
203  *                  (
204  *                      ASN1_SCK *asn1,
205  *                      gboolean *def,
206  *                      guint    *len
207  *                  )
208  * DESCRIPTION: Decodes an ASN1 length.
209  *              Parameters:
210  *              asn1: pointer to ASN1 socket.
211  *              def: Boolean - TRUE if length definite, FALSE if not
212  *              len: length, if length is definite
213  * DESCRIPTION: Decodes a definite or indefinite length.
214  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
215  */
216 int
217 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
218 {
219     int    ret;
220     guchar ch, cnt;
221
222     ret = asn1_octet_decode (asn1, &ch);
223     if (ret != ASN1_ERR_NOERROR)
224         return ret;
225     if (ch == 0x80)
226         *def = FALSE;           /* indefinite length */
227     else {
228         *def = TRUE;            /* definite length */
229         if (ch < 0x80)
230             *len = ch;
231         else {
232             cnt = (guchar) (ch & 0x7F);
233             *len = 0;
234             while (cnt > 0) {
235                 ret = asn1_octet_decode (asn1, &ch);
236                 if (ret != ASN1_ERR_NOERROR)
237                     return ret;
238                 *len <<= 8;
239                 *len |= ch;
240                 cnt--;
241             }
242         }
243     }
244     return ASN1_ERR_NOERROR;
245 }
246
247 /*
248  * NAME:        asn1_header_decode                                [API]
249  * SYNOPSIS:    int asn1_header_decode
250  *                  (
251  *                      ASN1_SCK *asn1,
252  *                      guint    *cls,
253  *                      guint    *con,
254  *                      guint    *tag
255  *                      gboolean *defp,
256  *                      guint    *lenp
257  *                  )
258  * DESCRIPTION: Decodes an ASN1 header.
259  *              Parameters:
260  *              asn1: pointer to ASN1 socket.
261  *              cls:  Class (see asn1.h)
262  *              con:  Primitive, Constructed (ASN1_PRI, ASN1_CON)
263  *              tag:  Tag (see asn1.h)
264  *              defp: Boolean - TRUE if length definite, FALSE if not
265  *              lenp: length, if length is definite
266  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
267  */
268 int
269 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
270                         gboolean *defp, guint *lenp)
271 {
272     int   ret;
273     guint def, len;
274
275     ret = asn1_id_decode (asn1, cls, con, tag);
276     if (ret != ASN1_ERR_NOERROR)
277         return ret;
278     ret = asn1_length_decode (asn1, &def, &len);
279     if (ret != ASN1_ERR_NOERROR)
280         return ret;
281     *defp = def;
282     *lenp = len;
283     return ASN1_ERR_NOERROR;
284 }
285
286
287 /*
288  * NAME:        asn1_eoc                                   [API]
289  * SYNOPSIS:    gboolean asn1_eoc
290  *                  (
291  *                      ASN1_SCK *asn1,
292  *                      int       eoc
293  *                  )
294  * DESCRIPTION: Checks if decoding is at End Of Contents.
295  *              Parameters:
296  *              asn1: pointer to ASN1 socket.
297  *              eoc: offset of end of encoding, or -1 if indefinite.
298  * RETURNS:     gboolean success
299  */
300 gboolean
301 asn1_eoc ( ASN1_SCK *asn1, int eoc)
302 {
303     if (eoc == -1)
304         return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
305                 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
306     else
307         return (asn1->offset >= eoc);
308 }
309
310 /*
311  * NAME:        asn1_eoc_decode                                [API]
312  * SYNOPSIS:    int asn1_eoc_decode
313  *                  (
314  *                      ASN1_SCK  *asn1,
315  *                      int       eoc
316  *                  )
317  * DESCRIPTION: Decodes End Of Contents.
318  *              Parameters:
319  *              asn1: pointer to ASN1 socket.
320  *              eoc: offset of end of encoding, or -1 if indefinite.
321  *              If eoc is -1 it decodes an ASN1 End Of
322  *              Contents (0x00 0x00), so it has to be an
323  *              indefinite length encoding. If eoc is a non-negative
324  *              integer, it probably was filled by asn1_header_decode,
325  *              and should refer to the octet after the last of the encoding.
326  *              It is checked if this offset refers to the octet to be
327  *              decoded. This only takes place in decoding a
328  *              definite length encoding.
329  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
330  */
331 int
332 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
333 {
334     int    ret;
335     guchar ch;
336     
337     if (eoc == -1) {
338         ret = asn1_octet_decode (asn1, &ch);
339         if (ret != ASN1_ERR_NOERROR)
340             return ret;
341       if (ch != 0x00)
342         return ASN1_ERR_EOC_MISMATCH;
343       ret = asn1_octet_decode (asn1, &ch);
344       if (ret != ASN1_ERR_NOERROR)
345         return ret;
346       if (ch != 0x00)
347         return ASN1_ERR_EOC_MISMATCH;
348       return ASN1_ERR_NOERROR;
349   } else {
350       if (asn1->offset != eoc)
351         return ASN1_ERR_LENGTH_MISMATCH;
352       return ASN1_ERR_NOERROR;
353     }
354 }
355
356 /*
357  * NAME:        asn1_null_decode                                [API]
358  * SYNOPSIS:    int asn1_null_decode
359  *                  (
360  *                      ASN1_SCK *asn1,
361  *                      int      enc_len
362  *                  )
363  * DESCRIPTION: Decodes Null.
364  *              Parameters:
365  *              asn1:    pointer to ASN1 socket.
366  *              enc_len: length of encoding of value.
367  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
368  */
369 int
370 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
371 {
372     asn1->offset += enc_len;
373     return ASN1_ERR_NOERROR;
374 }
375
376 /*
377  * NAME:        asn1_bool_decode                                [API]
378  * SYNOPSIS:    int asn1_bool_decode
379  *                  (
380  *                      ASN1_SCK *asn1,
381  *                      int      enc_len,
382  *                      gboolean *bool
383  *                  )
384  * DESCRIPTION: Decodes Boolean.
385  *              Parameters:
386  *              asn1:    pointer to ASN1 socket.
387  *              enc_len: length of encoding of value.
388  *              bool:    False, True (0, !0).
389  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
390  */
391 int
392 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *bool)
393 {
394     int    ret;
395     guchar ch;
396
397     if (enc_len != 1)
398       return ASN1_ERR_LENGTH_MISMATCH;
399     ret = asn1_octet_decode (asn1, &ch);
400     if (ret != ASN1_ERR_NOERROR)
401         return ret;
402     *bool = ch ? TRUE : FALSE;
403     return ASN1_ERR_NOERROR;
404 }
405
406 /*
407  * NAME:        asn1_int32_value_decode                                [API]
408  * SYNOPSIS:    int asn1_int32_value_decode
409  *                  (
410  *                      ASN1_SCK *asn1,
411  *                      int      enc_len,
412  *                      gint32   *integer
413  *                  )
414  * DESCRIPTION: Decodes value portion of Integer (which must be no more
415  *              than 32 bits).
416  *              Parameters:
417  *              asn1:    pointer to ASN1 socket.
418  *              enc_len: length of encoding of value.
419  *              integer: Integer.
420  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
421  */
422 int
423 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
424 {
425     int          ret;
426     int          eoc;
427     guchar       ch;
428     guint        len;
429
430     eoc = asn1->offset + enc_len;
431     ret = asn1_octet_decode (asn1, &ch);
432     if (ret != ASN1_ERR_NOERROR)
433         return ret;
434     *integer = (gint) ch;
435     len = 1;
436     while (asn1->offset < eoc) {
437         if (++len > sizeof (gint32))
438             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
439         ret = asn1_octet_decode (asn1, &ch);
440         if (ret != ASN1_ERR_NOERROR)
441             return ret;
442         *integer <<= 8;
443         *integer |= ch;
444     }
445     return ASN1_ERR_NOERROR;
446 }
447
448 /*
449  * NAME:        asn1_int32_decode                                [API]
450  * SYNOPSIS:    int asn1_int32_decode
451  *                  (
452  *                      ASN1_SCK *asn1,
453  *                      gint32   *integer,
454  *                      guint    *nbytes,
455  *                  )
456  * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
457  *              Parameters:
458  *              asn1:    pointer to ASN1 socket.
459  *              integer: Integer.
460  *              nbytes:  number of bytes used to encode it.
461  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
462  */
463 int
464 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
465 {
466     int          ret;
467     int          start;
468     guint        cls;
469     guint        con;
470     guint        tag;
471     gboolean     def;
472     guint        enc_len;
473
474     start = asn1->offset;
475     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
476     if (ret != ASN1_ERR_NOERROR)
477         goto done;
478     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
479         ret = ASN1_ERR_WRONG_TYPE;
480         goto done;
481     }
482     if (!def) {
483         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
484         goto done;
485     }
486     ret = asn1_int32_value_decode (asn1, enc_len, integer);
487
488 done:
489     *nbytes = asn1->offset - start;
490     return ret;
491 }
492
493 /*
494  * NAME:        asn1_uint32_value_decode                             [API]
495  * SYNOPSIS:    int asn1_uint32_value_decode
496  *                  (
497  *                      ASN1_SCK *asn1,
498  *                      int      enc_len,
499  *                      guint32  *integer
500  *                  )
501  * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
502  *              more than 32 bits).
503  *              Parameters:
504  *              asn1:    pointer to ASN1 socket.
505  *              enc_len: length of encoding of value.
506  *              integer: Integer.
507  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
508  */
509 int
510 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint *integer)
511 {
512     int          ret;
513     int          eoc;
514     guchar       ch;
515     guint        len;
516
517     eoc = asn1->offset + enc_len;
518     ret = asn1_octet_decode (asn1, &ch);
519     if (ret != ASN1_ERR_NOERROR)
520         return ret;
521     *integer = ch;
522     if (ch == 0)
523         len = 0;
524     else
525         len = 1;
526     while (asn1->offset < eoc) {
527         if (++len > sizeof (guint32))
528             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
529         ret = asn1_octet_decode (asn1, &ch);
530         if (ret != ASN1_ERR_NOERROR)
531             return ret;
532         *integer <<= 8;
533         *integer |= ch;
534     }
535     return ASN1_ERR_NOERROR;
536 }
537
538 /*
539  * NAME:        asn1_uint32_decode                             [API]
540  * SYNOPSIS:    int asn1_uint32_decode
541  *                  (
542  *                      ASN1_SCK *asn1,
543  *                      guint32  *integer,
544  *                      guint    *nbytes,
545  *                  )
546  * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
547  *              Parameters:
548  *              asn1:    pointer to ASN1 socket.
549  *              integer: Integer.
550  *              nbytes:  number of bytes used to encode it.
551  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
552  */
553 int
554 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
555 {
556     int          ret;
557     int          start;
558     guint        cls;
559     guint        con;
560     guint        tag;
561     gboolean     def;
562     guint        enc_len;
563
564     start = asn1->offset;
565     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
566     if (ret != ASN1_ERR_NOERROR)
567         goto done;
568     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
569         ret = ASN1_ERR_WRONG_TYPE;
570         goto done;
571     }
572     if (!def) {
573         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
574         goto done;
575     }
576     ret = asn1_uint32_value_decode (asn1, enc_len, integer);
577
578 done:
579     *nbytes = asn1->offset - start;
580     return ret;
581 }
582
583 /*
584  * NAME:        asn1_bits_decode                                [API]
585  * SYNOPSIS:    int asn1_bits_decode
586  *                  (
587  *                      ASN1_SCK  *asn1,
588  *                      int        eoc,
589  *                      guchar    *bits,
590  *                      guint      size,
591  *                      guint      len,
592  *                      guchar     unused
593  *                  )
594  * DESCRIPTION: Decodes Bit String.
595  *              Parameters:
596  *              asn1:   pointer to ASN1 socket.
597  *              eoc: offset of end of encoding, or -1 if indefinite.
598  *              bits:   pointer to begin of Bit String.
599  *              size:   Size of Bit String in characters.
600  *              len:    Length of Bit String in characters.
601  *              unused: Number of unused bits in last character.
602  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
603  */
604 int
605 asn1_bits_decode ( ASN1_SCK *asn1, int eoc, guchar **bits,
606                      guint *len, guchar *unused)
607
608 {
609     int ret;
610
611     *bits = NULL;
612     ret = asn1_octet_decode (asn1, unused);
613     if (ret != ASN1_ERR_NOERROR)
614         return ret;
615     *len = 0;
616     *bits = g_malloc(eoc - asn1->offset);
617     while (asn1->offset < eoc) {
618         ret = asn1_octet_decode (asn1, (guchar *)bits++);
619         if (ret != ASN1_ERR_NOERROR) {
620             g_free(*bits);
621             *bits = NULL;
622             return ret;
623           }
624     }
625     return ASN1_ERR_NOERROR;
626 }
627
628 /*
629  * NAME:        asn1_string_value_decode                       [API]
630  * SYNOPSIS:    int asn1_string_value_decode
631  *                  (
632  *                      ASN1_SCK *asn1,
633  *                      int      enc_len,
634  *                      guchar   **octets
635  *                  )
636  * DESCRIPTION: Decodes value portion of string (Octet String, various
637  *              character string types)
638  *              Parameters:
639  *              asn1:    pointer to ASN1 socket.
640  *              enc_len: length of encoding of value.
641  *              octets:  pointer to variable we set to point to string.
642  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
643  */
644 int
645 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
646 {
647     int          ret;
648     int          eoc;
649     guchar       *ptr;
650
651     eoc = asn1->offset + enc_len;
652
653     /*
654      * Check for an overflow, and clamp "eoc" at the maximum if we
655      * get it.
656      */
657     if (eoc < asn1->offset || eoc < 0)
658         eoc = INT_MAX;
659
660     /*
661      * First, make sure the entire string is in the tvbuff, and throw
662      * an exception if it isn't.  If the length is bogus, this should
663      * keep us from trying to allocate an immensely large buffer.
664      * (It won't help if the length is *valid* but immensely large,
665      * but that's another matter.)
666      *
667      * We do that by attempting to fetch the last byte (if the length
668      * isn't 0).
669      */
670     if (enc_len != 0)
671         tvb_get_guint8(asn1->tvb, eoc - 1);
672
673     *octets = g_malloc (enc_len);
674     ptr = *octets;
675     while (asn1->offset < eoc) {
676         ret = asn1_octet_decode (asn1, (guchar *)ptr++);
677         if (ret != ASN1_ERR_NOERROR) {
678             g_free(*octets);
679             *octets = NULL;
680             return ret;
681         }
682     }
683     return ASN1_ERR_NOERROR;
684 }
685
686 /*
687  * NAME:        asn1_string_decode                             [API]
688  * SYNOPSIS:    int asn1_string_decode
689  *                  (
690  *                      ASN1_SCK  *asn1,
691  *                      guchar    **octets,
692  *                      guint     *str_len,
693  *                      guint     *nbytes,
694  *                      guint     expected_tag
695  *                  )
696  * DESCRIPTION: Decodes string (Octet String, various character string
697  *              types)
698  *              Parameters:
699  *              asn1:         pointer to ASN1 socket.
700  *              octets:       pointer to variable we set to point to string.
701  *              str_len:      length of octet_string.
702  *              nbytes:       number of bytes used to encode.
703  *              expected_tag: tag expected for this type of string.
704  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
705  */
706 int
707 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
708                         guint *nbytes, guint expected_tag)
709 {
710     int          ret;
711     int          start;
712     int          enc_len;
713     guint        cls;
714     guint        con;
715     guint        tag;
716     gboolean     def;
717
718     start = asn1->offset;
719     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
720     if (ret != ASN1_ERR_NOERROR)
721         goto done;
722     if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
723         /* XXX - handle the constructed encoding? */
724         ret = ASN1_ERR_WRONG_TYPE;
725         goto done;
726     }
727     if (!def) {
728         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
729         goto done;
730     }
731
732     ret = asn1_string_value_decode (asn1, enc_len, octets);
733     *str_len = enc_len;
734
735 done:
736     *nbytes = asn1->offset - start;
737     return ret;
738 }
739
740 /*
741  * NAME:        asn1_octet_string_decode                             [API]
742  * SYNOPSIS:    int asn1_octet_string_decode
743  *                  (
744  *                      ASN1_SCK  *asn1,
745  *                      guchar    **octets,
746  *                      guint     *str_len,
747  *                      guint     *nbytes,
748  *                  )
749  * DESCRIPTION: Decodes Octet String.
750  *              Parameters:
751  *              asn1:    pointer to ASN1 socket.
752  *              octets:  pointer to variable we set to point to string.
753  *              str_len: length of octet_string.
754  *              nbytes:  number of bytes used to encode.
755  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
756  */
757 int
758 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
759                         guint *nbytes)
760 {
761     return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
762 }
763
764 /*
765  * NAME:        asn1_subid_decode
766  * SYNOPSIS:    int asn1_subid_decode
767  *                  (
768  *                      ASN1_SCK *asn1,
769  *                      subid_t  *subid
770  *                  )
771  * DESCRIPTION: Decodes Sub Identifier.
772  *              Parameters:
773  *              asn1:  pointer to ASN1 socket.
774  *              subid: Sub Identifier.
775  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
776  */
777 int
778 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
779 {
780     int    ret;
781     guchar ch;
782
783     *subid = 0;
784     do {
785         ret = asn1_octet_decode(asn1, &ch);
786         if (ret != ASN1_ERR_NOERROR)
787             return ret;
788         *subid <<= 7;
789         *subid |= ch & 0x7F;
790     } while ((ch & 0x80) == 0x80);
791     return ASN1_ERR_NOERROR;
792 }
793
794 /*
795  * NAME:        asn1_oid_value_decode                                [API]
796  * SYNOPSIS:    int asn1_oid_value_decode
797  *                  (
798  *                      ASN1_SCK *asn1,
799  *                      int      enc_len,
800  *                      subid_t  **oid,
801  *                      guint    *len
802  *                  )
803  * DESCRIPTION: Decodes value portion of Object Identifier.
804  *              Parameters:
805  *              asn1:    pointer to ASN1 socket.
806  *              enc_len: length of encoding of value.
807  *              oid:     pointer to variable we set to Object Identifier.
808  *              len:     Length of Object Identifier in gulongs.
809  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
810  */
811 int
812 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
813 {
814     int          ret;
815     int          eoc;
816     subid_t      subid;
817     guint        size;
818     subid_t      *optr;
819
820     eoc = asn1->offset + enc_len;
821
822     /*
823      * Check for an overflow, and clamp "eoc" at the maximum if we
824      * get it.
825      */
826     if (eoc < asn1->offset || eoc < 0)
827         eoc = INT_MAX;
828
829     /*
830      * First, make sure the entire string is in the tvbuff, and throw
831      * an exception if it isn't.  If the length is bogus, this should
832      * keep us from trying to allocate an immensely large buffer.
833      * (It won't help if the length is *valid* but immensely large,
834      * but that's another matter.)
835      *
836      * We do that by attempting to fetch the last byte (if the length
837      * isn't 0).
838      */
839     if (enc_len != 0)
840         tvb_get_guint8(asn1->tvb, eoc - 1);
841
842     size = enc_len + 1;
843     *oid = g_malloc(size * sizeof(gulong));
844     optr = *oid;
845  
846     ret = asn1_subid_decode (asn1, &subid);
847     if (ret != ASN1_ERR_NOERROR) {
848         g_free(*oid);
849         *oid = NULL;
850         return ret;
851     }
852     if (subid < 40) {
853         optr[0] = 0;
854         optr[1] = subid;
855     } else if (subid < 80) {
856         optr[0] = 1;
857         optr[1] = subid - 40;
858     } else {
859         optr[0] = 2;
860         optr[1] = subid - 80;
861     }
862     *len = 2;
863     optr += 2;
864     while (asn1->offset < eoc) {
865         if (++(*len) > size) {
866             g_free(*oid);
867             *oid = NULL;
868             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
869         }
870         ret = asn1_subid_decode (asn1, optr++);
871         if (ret != ASN1_ERR_NOERROR) {
872             g_free(*oid);
873             *oid = NULL;
874             return ret;
875         }
876     }
877     return ASN1_ERR_NOERROR;
878 }
879
880 /*
881  * NAME:        asn1_oid_decode                                [API]
882  * SYNOPSIS:    int asn1_oid_decode
883  *                  (
884  *                      ASN1_SCK *asn1,
885  *                      subid_t  **oid,
886  *                      guint    *len,
887  *                      guint    *nbytes
888  *                  )
889  * DESCRIPTION: Decodes Object Identifier.
890  *              Parameters:
891  *              asn1:   pointer to ASN1 socket.
892  *              oid:    pointer to variable we set to Object Identifier.
893  *              len:    Length of Object Identifier in gulongs.
894  *              nbytes: number of bytes used to encode.
895  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
896  */
897 int
898 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
899 {
900     int          ret;
901     int          start;
902     guint        cls;
903     guint        con;
904     guint        tag;
905     gboolean     def;
906     guint        enc_len;
907
908     start = asn1->offset;
909     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
910     if (ret != ASN1_ERR_NOERROR)
911         goto done;
912     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
913         ret = ASN1_ERR_WRONG_TYPE;
914         goto done;
915     }
916     if (!def) {
917         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
918         goto done;
919     }
920
921     ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
922
923 done:
924     *nbytes = asn1->offset - start;
925     return ret;
926 }
927
928 /*
929  * NAME:        asn1_sequence_decode                             [API]
930  * SYNOPSIS:    int asn1_sequence_decode
931  *                  (
932  *                      ASN1_SCK  *asn1,
933  *                      guint     *seq_len,
934  *                      guint     *nbytes
935  *                  )
936  * DESCRIPTION: Decodes header for SEQUENCE.
937  *              Parameters:
938  *              asn1:    pointer to ASN1 socket.
939  *              seq_len: length of sequence.
940  *              nbytes:  number of bytes used to encode header.
941  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
942  */
943 int
944 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
945 {
946     int          ret;
947     int          start;
948     guint        cls;
949     guint        con;
950     guint        tag;
951     gboolean     def;
952
953     start = asn1->offset;
954     ret = asn1_header_decode(asn1, &cls, &con, &tag,
955             &def, seq_len);
956     if (ret != ASN1_ERR_NOERROR)
957         goto done;
958     if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
959         ret = ASN1_ERR_WRONG_TYPE;
960         goto done;
961     }
962     if (!def) {
963         /* XXX - might some sequences have an indefinite length? */
964         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
965         goto done;
966     }
967     ret = ASN1_ERR_NOERROR;
968
969 done:
970     *nbytes = asn1->offset - start;
971     return ret;
972 }