Get rid of some GCC warnings about unused code.
[obnox/wireshark/wip.git] / epan / asn1.c
1 /* asn1.c
2  * Routines for ASN.1 BER dissection
3  *
4  * $Id$
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 #include <stdio.h>
64
65 #include <limits.h>
66
67 #include <glib.h>
68
69 #include <epan/tvbuff.h>
70 #include <epan/asn1.h>
71
72 /*
73  * NAME:        asn1_open                                   [API]
74  * SYNOPSIS:    void asn1_open
75  *                  (
76  *                      ASN1_SCK *asn1,
77  *                      tvbuff_t *tvb,
78  *                      int       offset
79  *                  )
80  * DESCRIPTION: Opens an ASN1 socket.
81  *              Parameters:
82  *              asn1:   pointer to ASN1 socket.
83  *              tvb:    Tvbuff for encoding.
84  *              offset: Current offset in tvbuff.
85  *              Encoding starts at the end of the buffer, and
86  *              proceeds to the beginning.
87  * RETURNS:     void
88  */
89
90 void
91 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
92 {
93     asn1->tvb = tvb;
94     asn1->offset = offset;
95 }
96
97 /*
98  * NAME:        asn1_close                                  [API]
99  * SYNOPSIS:    void asn1_close
100  *                  (
101  *                      ASN1_SCK   *asn1,
102  *                      int        *offset
103  *                  )
104  * DESCRIPTION: Closes an ASN1 socket.
105  *              Parameters:
106  *              asn1:   pointer to ASN1 socket.
107  *              offset: pointer to variable into which current offset is
108  *              to be put.
109  * RETURNS:     void
110  */
111
112 void
113 asn1_close(ASN1_SCK *asn1, int *offset)
114 {
115     *offset = asn1->offset;
116 }
117
118 /*
119  * NAME:        asn1_octet_decode
120  * SYNOPSIS:    int asn1_octet_decode
121  *                  (
122  *                      ASN1_SCK *asn1,
123  *                      guchar   *ch
124  *                  )
125  * DESCRIPTION: Decodes an octet.
126  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
127  */
128 int
129 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
130 {
131     *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
132     asn1->offset++;
133     return ASN1_ERR_NOERROR;
134 }
135
136 /*
137  * NAME:        asn1_tag_get
138  * SYNOPSIS:    int asn1_tag_get
139  *                  (
140  *                      ASN1_SCK *asn1,
141  *                      guint    *tag
142  *                  )
143  * DESCRIPTION: Decodes a tag number, combining it with existing tag bits.
144  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
145  */
146 static int
147 asn1_tag_get(ASN1_SCK *asn1, guint *tag)
148 {
149     int    ret;
150     guchar ch;
151
152     do {
153         ret = asn1_octet_decode (asn1, &ch);
154         if (ret != ASN1_ERR_NOERROR)
155             return ret;
156         *tag <<= 7;
157         *tag |= ch & 0x7F;
158     } while ((ch & 0x80) == 0x80);
159     return ASN1_ERR_NOERROR;
160 }
161
162 /*
163  * NAME:        asn1_tag_decode
164  * SYNOPSIS:    int asn1_tag_decode
165  *                  (
166  *                      ASN1_SCK *asn1,
167  *                      guint    *tag
168  *                  )
169  * DESCRIPTION: Decodes a tag number.
170  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
171  */
172 int
173 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
174 {
175     *tag = 0;
176     return asn1_tag_get(asn1, tag);
177 }
178
179 /*
180  * NAME:        asn1_id_decode
181  * SYNOPSIS:    int asn1_id_decode
182  *                  (
183  *                      ASN1_SCK *asn1,
184  *                      guint    *cls,
185  *                      guint    *con,
186  *                      guint    *tag
187  *                  )
188  * DESCRIPTION: Decodes an identifier.
189  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
190  */
191 int
192 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
193 {
194     int    ret;
195     guchar ch;
196
197     *tag = 0;
198     ret = asn1_octet_decode (asn1, &ch);
199     if (ret != ASN1_ERR_NOERROR)
200         return ret;
201     *cls = (ch & 0xC0) >> 6;
202     *con = (ch & 0x20) >> 5;
203     *tag = (ch & 0x1F);
204     if (*tag == 0x1F) {
205         ret = asn1_tag_decode (asn1, tag);
206         if (ret != ASN1_ERR_NOERROR)
207             return ret;
208     }
209     return ASN1_ERR_NOERROR;
210 }
211
212 /*
213  * NAME:        asn1_id_decode1
214  * SYNOPSIS:    int asn1_id_decode1
215  *                  (
216  *                      ASN1_SCK *asn1,
217  *                      guint    *tag
218  *                  )
219  * DESCRIPTION: Decodes an identifier.
220  *              Like asn1_id_decode() except that the Class and Constructor
221  *              bits are returned in the tag.
222  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
223  */
224 int
225 asn1_id_decode1(ASN1_SCK *asn1, guint *tag)
226 {
227     int    ret;
228     guchar ch;
229
230     *tag = 0;
231     ret = asn1_octet_decode (asn1, &ch);
232     if (ret != ASN1_ERR_NOERROR)
233         return ret;
234
235     *tag = ch;
236     if ((*tag & 0x1F) == 0x1F) { /* high-tag-number format */
237         *tag = ch >> 5; /* leave just the Class and Constructor bits */
238         ret = asn1_tag_get (asn1, tag);
239         if (ret != ASN1_ERR_NOERROR)
240             return ret;
241     }
242     return ASN1_ERR_NOERROR;
243 }
244
245 /*
246  * NAME:        asn1_length_decode
247  * SYNOPSIS:    int asn1_length_decode
248  *                  (
249  *                      ASN1_SCK *asn1,
250  *                      gboolean *def,
251  *                      guint    *len
252  *                  )
253  * DESCRIPTION: Decodes an ASN1 length.
254  *              Parameters:
255  *              asn1: pointer to ASN1 socket.
256  *              def: Boolean - TRUE if length definite, FALSE if not
257  *              len: length, if length is definite
258  * DESCRIPTION: Decodes a definite or indefinite length.
259  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
260  */
261 int
262 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
263 {
264     int    ret;
265     guchar ch, cnt;
266
267     ret = asn1_octet_decode (asn1, &ch);
268     if (ret != ASN1_ERR_NOERROR)
269         return ret;
270     if (ch == 0x80)
271         *def = FALSE;           /* indefinite length */
272     else {
273         *def = TRUE;            /* definite length */
274         if (ch < 0x80)
275             *len = ch;
276         else {
277             cnt = (guchar) (ch & 0x7F);
278             *len = 0;
279             while (cnt > 0) {
280                 ret = asn1_octet_decode (asn1, &ch);
281                 if (ret != ASN1_ERR_NOERROR)
282                     return ret;
283                 *len <<= 8;
284                 *len |= ch;
285                 cnt--;
286             }
287         }
288     }
289     return ASN1_ERR_NOERROR;
290 }
291
292 /*
293  * NAME:        asn1_header_decode                                [API]
294  * SYNOPSIS:    int asn1_header_decode
295  *                  (
296  *                      ASN1_SCK *asn1,
297  *                      guint    *cls,
298  *                      guint    *con,
299  *                      guint    *tag
300  *                      gboolean *defp,
301  *                      guint    *lenp
302  *                  )
303  * DESCRIPTION: Decodes an ASN1 header.
304  *              Parameters:
305  *              asn1: pointer to ASN1 socket.
306  *              cls:  Class (see asn1.h)
307  *              con:  Primitive, Constructed (ASN1_PRI, ASN1_CON)
308  *              tag:  Tag (see asn1.h)
309  *              defp: Boolean - TRUE if length definite, FALSE if not
310  *              lenp: length, if length is definite
311  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
312  */
313 int
314 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
315                         gboolean *defp, guint *lenp)
316 {
317     int   ret;
318     guint def, len = 0;
319
320     ret = asn1_id_decode (asn1, cls, con, tag);
321     if (ret != ASN1_ERR_NOERROR)
322         return ret;
323     ret = asn1_length_decode (asn1, &def, &len);
324     if (ret != ASN1_ERR_NOERROR)
325         return ret;
326     *defp = def;
327     *lenp = len;
328     return ASN1_ERR_NOERROR;
329 }
330
331
332 /*
333  * NAME:        asn1_eoc                                   [API]
334  * SYNOPSIS:    gboolean asn1_eoc
335  *                  (
336  *                      ASN1_SCK *asn1,
337  *                      int       eoc
338  *                  )
339  * DESCRIPTION: Checks if decoding is at End Of Contents.
340  *              Parameters:
341  *              asn1: pointer to ASN1 socket.
342  *              eoc: offset of end of encoding, or -1 if indefinite.
343  * RETURNS:     gboolean success
344  */
345 gboolean
346 asn1_eoc ( ASN1_SCK *asn1, int eoc)
347 {
348     if (eoc == -1)
349         return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
350                 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
351     else
352         return (asn1->offset >= eoc);
353 }
354
355 /*
356  * NAME:        asn1_eoc_decode                                [API]
357  * SYNOPSIS:    int asn1_eoc_decode
358  *                  (
359  *                      ASN1_SCK  *asn1,
360  *                      int       eoc
361  *                  )
362  * DESCRIPTION: Decodes End Of Contents.
363  *              Parameters:
364  *              asn1: pointer to ASN1 socket.
365  *              eoc: offset of end of encoding, or -1 if indefinite.
366  *              If eoc is -1 it decodes an ASN1 End Of
367  *              Contents (0x00 0x00), so it has to be an
368  *              indefinite length encoding. If eoc is a non-negative
369  *              integer, it probably was filled by asn1_header_decode,
370  *              and should refer to the octet after the last of the encoding.
371  *              It is checked if this offset refers to the octet to be
372  *              decoded. This only takes place in decoding a
373  *              definite length encoding.
374  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
375  */
376 int
377 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
378 {
379     int    ret;
380     guchar ch;
381
382     if (eoc == -1) {
383         ret = asn1_octet_decode (asn1, &ch);
384         if (ret != ASN1_ERR_NOERROR)
385             return ret;
386       if (ch != 0x00)
387         return ASN1_ERR_EOC_MISMATCH;
388       ret = asn1_octet_decode (asn1, &ch);
389       if (ret != ASN1_ERR_NOERROR)
390         return ret;
391       if (ch != 0x00)
392         return ASN1_ERR_EOC_MISMATCH;
393       return ASN1_ERR_NOERROR;
394   } else {
395       if (asn1->offset != eoc)
396         return ASN1_ERR_LENGTH_MISMATCH;
397       return ASN1_ERR_NOERROR;
398     }
399 }
400
401 /*
402  * NAME:        asn1_null_decode                                [API]
403  * SYNOPSIS:    int asn1_null_decode
404  *                  (
405  *                      ASN1_SCK *asn1,
406  *                      int      enc_len
407  *                  )
408  * DESCRIPTION: Decodes Null.
409  *              Parameters:
410  *              asn1:    pointer to ASN1 socket.
411  *              enc_len: length of encoding of value.
412  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
413  */
414 int
415 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
416 {
417     int start_off = asn1->offset;
418
419     asn1->offset += enc_len;
420     /*
421      * Check for integer overflows.  
422      * XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate
423      *       error from the ones available.  Should we make a new one?
424      */
425     if (asn1->offset < 0 || asn1->offset < start_off)
426         return ASN1_ERR_LENGTH_MISMATCH;
427
428     return ASN1_ERR_NOERROR;
429 }
430
431 /*
432  * NAME:        asn1_bool_decode                                [API]
433  * SYNOPSIS:    int asn1_bool_decode
434  *                  (
435  *                      ASN1_SCK *asn1,
436  *                      int      enc_len,
437  *                      gboolean *boolean
438  *                  )
439  * DESCRIPTION: Decodes Boolean.
440  *              Parameters:
441  *              asn1:    pointer to ASN1 socket.
442  *              enc_len: length of encoding of value.
443  *              bool:    False, True (0, !0).
444  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
445  */
446 int
447 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *boolean)
448 {
449     int    ret;
450     guchar ch;
451
452     if (enc_len != 1)
453       return ASN1_ERR_LENGTH_MISMATCH;
454     ret = asn1_octet_decode (asn1, &ch);
455     if (ret != ASN1_ERR_NOERROR)
456         return ret;
457     *boolean = ch ? TRUE : FALSE;
458     return ASN1_ERR_NOERROR;
459 }
460
461 /*
462  * NAME:        asn1_int32_value_decode                                [API]
463  * SYNOPSIS:    int asn1_int32_value_decode
464  *                  (
465  *                      ASN1_SCK *asn1,
466  *                      int      enc_len,
467  *                      gint32   *integer
468  *                  )
469  * DESCRIPTION: Decodes value portion of Integer (which must be no more
470  *              than 32 bits).
471  *              Parameters:
472  *              asn1:    pointer to ASN1 socket.
473  *              enc_len: length of encoding of value.
474  *              integer: Integer.
475  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
476  */
477 int
478 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
479 {
480     int          ret;
481     int          eoc;
482     guchar       ch;
483     guint        len;
484
485     eoc = asn1->offset + enc_len;
486     ret = asn1_octet_decode (asn1, &ch);
487     if (ret != ASN1_ERR_NOERROR)
488         return ret;
489     *integer = (gint) ch;
490     len = 1;
491     while (asn1->offset < eoc) {
492         if (++len > sizeof (gint32))
493             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
494         ret = asn1_octet_decode (asn1, &ch);
495         if (ret != ASN1_ERR_NOERROR)
496             return ret;
497         *integer <<= 8;
498         *integer |= ch;
499     }
500     return ASN1_ERR_NOERROR;
501 }
502
503 /*
504  * NAME:        asn1_int32_decode                                [API]
505  * SYNOPSIS:    int asn1_int32_decode
506  *                  (
507  *                      ASN1_SCK *asn1,
508  *                      gint32   *integer,
509  *                      guint    *nbytes,
510  *                  )
511  * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
512  *              Parameters:
513  *              asn1:    pointer to ASN1 socket.
514  *              integer: Integer.
515  *              nbytes:  number of bytes used to encode it.
516  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
517  */
518 int
519 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
520 {
521     int          ret;
522     int          start;
523     guint        cls;
524     guint        con;
525     guint        tag;
526     gboolean     def;
527     guint        enc_len;
528
529     start = asn1->offset;
530     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
531     if (ret != ASN1_ERR_NOERROR)
532         goto done;
533     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
534         ret = ASN1_ERR_WRONG_TYPE;
535         goto done;
536     }
537     if (!def) {
538         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
539         goto done;
540     }
541     ret = asn1_int32_value_decode (asn1, enc_len, integer);
542
543 done:
544     *nbytes = asn1->offset - start;
545     return ret;
546 }
547
548 /*
549  * NAME:        asn1_uint32_value_decode                             [API]
550  * SYNOPSIS:    int asn1_uint32_value_decode
551  *                  (
552  *                      ASN1_SCK *asn1,
553  *                      int      enc_len,
554  *                      guint32  *integer
555  *                  )
556  * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
557  *              more than 32 bits).
558  *              Parameters:
559  *              asn1:    pointer to ASN1 socket.
560  *              enc_len: length of encoding of value.
561  *              integer: Integer.
562  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
563  */
564 int
565 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint32 *integer)
566 {
567     int          ret;
568     int          eoc;
569     guchar       ch;
570     guint        len;
571
572     eoc = asn1->offset + enc_len;
573     ret = asn1_octet_decode (asn1, &ch);
574     if (ret != ASN1_ERR_NOERROR)
575         return ret;
576     *integer = ch;
577     if (ch == 0)
578         len = 0;
579     else
580         len = 1;
581     while (asn1->offset < eoc) {
582         if (++len > sizeof (guint32))
583             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
584         ret = asn1_octet_decode (asn1, &ch);
585         if (ret != ASN1_ERR_NOERROR)
586             return ret;
587         *integer <<= 8;
588         *integer |= ch;
589     }
590     return ASN1_ERR_NOERROR;
591 }
592
593 /*
594  * NAME:        asn1_uint32_decode                             [API]
595  * SYNOPSIS:    int asn1_uint32_decode
596  *                  (
597  *                      ASN1_SCK *asn1,
598  *                      guint32  *integer,
599  *                      guint    *nbytes,
600  *                  )
601  * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
602  *              Parameters:
603  *              asn1:    pointer to ASN1 socket.
604  *              integer: Integer.
605  *              nbytes:  number of bytes used to encode it.
606  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
607  */
608 int
609 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
610 {
611     int          ret;
612     int          start;
613     guint        cls;
614     guint        con;
615     guint        tag;
616     gboolean     def;
617     guint        enc_len;
618
619     start = asn1->offset;
620     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
621     if (ret != ASN1_ERR_NOERROR)
622         goto done;
623     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
624         ret = ASN1_ERR_WRONG_TYPE;
625         goto done;
626     }
627     if (!def) {
628         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
629         goto done;
630     }
631     ret = asn1_uint32_value_decode (asn1, enc_len, integer);
632
633 done:
634     *nbytes = asn1->offset - start;
635     return ret;
636 }
637
638 /*
639  * NAME:        asn1_bits_decode                                [API]
640  * SYNOPSIS:    int asn1_bits_decode
641  *                  (
642  *                      ASN1_SCK  *asn1,
643  *                      int        eoc,
644  *                      guchar    *bits,
645  *                      guint      size,
646  *                      guint      len,
647  *                      guchar     unused
648  *                  )
649  * DESCRIPTION: Decodes Bit String.
650  *              Parameters:
651  *              asn1:    pointer to ASN1 socket.
652  *              enc_len: length of value.
653  *              bits:    pointer to variable we set to point to strring
654  *              len:     Size of Bit String in characters.
655  *              unused:  Number of unused bits in last character.
656  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
657  */
658 int
659 asn1_bits_decode ( ASN1_SCK *asn1, int enc_len, guchar **bits,
660                      guint *len, guchar *unused)
661 {
662     int ret;
663     int eoc;
664     guchar *ptr;
665
666     eoc = asn1->offset + enc_len;
667     *bits = NULL;
668     ret = asn1_octet_decode (asn1, unused);
669     if (ret != ASN1_ERR_NOERROR)
670         return ret;
671     *len = 0;
672
673     /*
674      * First, make sure the entire string is in the tvbuff, and throw
675      * an exception if it isn't.  If the length is bogus, this should
676      * keep us from trying to allocate an immensely large buffer.
677      * (It won't help if the length is *valid* but immensely large,
678      * but that's another matter; in any case, that would happen only
679      * if we had an immensely large tvbuff....)
680      */
681     if (enc_len != 0) {
682         tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
683         *bits = g_malloc (enc_len);
684     } else {
685         /*
686          * If the length is 0, we allocate a 1-byte buffer, as
687          * "g_malloc()" returns NULL if passed 0 as an argument,
688          * and our caller expects us to return a pointer to a
689          * buffer.
690          */
691         *bits = g_malloc (1);
692     }
693
694     ptr = *bits;
695     while (asn1->offset < eoc) {
696         ret = asn1_octet_decode (asn1, (guchar *)ptr++);
697         if (ret != ASN1_ERR_NOERROR) {
698             g_free(*bits);
699             *bits = NULL;
700             return ret;
701         }
702     }
703     *len = ptr - *bits;
704     return ASN1_ERR_NOERROR;
705 }
706
707 /*
708  * NAME:        asn1_string_value_decode                       [API]
709  * SYNOPSIS:    int asn1_string_value_decode
710  *                  (
711  *                      ASN1_SCK *asn1,
712  *                      int      enc_len,
713  *                      guchar   **octets
714  *                  )
715  * DESCRIPTION: Decodes value portion of string (Octet String, various
716  *              character string types)
717  *              Parameters:
718  *              asn1:    pointer to ASN1 socket.
719  *              enc_len: length of encoding of value.
720  *              octets:  pointer to variable we set to point to string,
721  *                       which is '\0' terminated for ease of use as C-string
722  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
723  */
724 int
725 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
726 {
727     int          ret;
728     int          eoc;
729     guchar       *ptr;
730
731     /*
732      * First, make sure the entire string is in the tvbuff, and throw
733      * an exception if it isn't.  If the length is bogus, this should
734      * keep us from trying to allocate an immensely large buffer.
735      * (It won't help if the length is *valid* but immensely large,
736      * but that's another matter; in any case, that would happen only
737      * if we had an immensely large tvbuff....)
738      */
739     if (enc_len != 0)
740         tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
741     *octets = g_malloc (enc_len+1);
742
743     eoc = asn1->offset + enc_len;
744     ptr = *octets;
745     while (asn1->offset < eoc) {
746         ret = asn1_octet_decode (asn1, (guchar *)ptr++);
747         if (ret != ASN1_ERR_NOERROR) {
748             g_free(*octets);
749             *octets = NULL;
750             return ret;
751         }
752     }
753     *(guchar *)ptr = '\0';
754     return ASN1_ERR_NOERROR;
755 }
756
757 /*
758  * NAME:        asn1_string_decode                             [API]
759  * SYNOPSIS:    int asn1_string_decode
760  *                  (
761  *                      ASN1_SCK  *asn1,
762  *                      guchar    **octets,
763  *                      guint     *str_len,
764  *                      guint     *nbytes,
765  *                      guint     expected_tag
766  *                  )
767  * DESCRIPTION: Decodes string (Octet String, various character string
768  *              types)
769  *              Parameters:
770  *              asn1:         pointer to ASN1 socket.
771  *              octets:       pointer to variable we set to point to string.
772  *              str_len:      length of octet_string.
773  *              nbytes:       number of bytes used to encode.
774  *              expected_tag: tag expected for this type of string.
775  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
776  */
777 int
778 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
779                         guint *nbytes, guint expected_tag)
780 {
781     int          ret;
782     int          start;
783     int          enc_len;
784     guint        cls;
785     guint        con;
786     guint        tag;
787     gboolean     def;
788
789     start = asn1->offset;
790     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
791     if (ret != ASN1_ERR_NOERROR)
792         goto done;
793     if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
794         /* XXX - handle the constructed encoding? */
795         ret = ASN1_ERR_WRONG_TYPE;
796         goto done;
797     }
798     if (!def) {
799         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
800         goto done;
801     }
802
803     ret = asn1_string_value_decode (asn1, enc_len, octets);
804     *str_len = enc_len;
805
806 done:
807     *nbytes = asn1->offset - start;
808     return ret;
809 }
810
811 /*
812  * NAME:        asn1_octet_string_decode                             [API]
813  * SYNOPSIS:    int asn1_octet_string_decode
814  *                  (
815  *                      ASN1_SCK  *asn1,
816  *                      guchar    **octets,
817  *                      guint     *str_len,
818  *                      guint     *nbytes,
819  *                  )
820  * DESCRIPTION: Decodes Octet String.
821  *              Parameters:
822  *              asn1:    pointer to ASN1 socket.
823  *              octets:  pointer to variable we set to point to string.
824  *              str_len: length of octet_string.
825  *              nbytes:  number of bytes used to encode.
826  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
827  */
828 int
829 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
830                         guint *nbytes)
831 {
832     return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
833 }
834
835 /*
836  * NAME:        asn1_subid_decode
837  * SYNOPSIS:    int asn1_subid_decode
838  *                  (
839  *                      ASN1_SCK *asn1,
840  *                      subid_t  *subid
841  *                  )
842  * DESCRIPTION: Decodes Sub Identifier.
843  *              Parameters:
844  *              asn1:  pointer to ASN1 socket.
845  *              subid: Sub Identifier.
846  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
847  */
848 int
849 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
850 {
851     int    ret;
852     guchar ch;
853
854     *subid = 0;
855     do {
856         ret = asn1_octet_decode(asn1, &ch);
857         if (ret != ASN1_ERR_NOERROR)
858             return ret;
859         *subid <<= 7;
860         *subid |= ch & 0x7F;
861     } while ((ch & 0x80) == 0x80);
862     return ASN1_ERR_NOERROR;
863 }
864
865 /*
866  * NAME:        asn1_oid_value_decode                                [API]
867  * SYNOPSIS:    int asn1_oid_value_decode
868  *                  (
869  *                      ASN1_SCK *asn1,
870  *                      int      enc_len,
871  *                      subid_t  **oid,
872  *                      guint    *len
873  *                  )
874  * DESCRIPTION: Decodes value portion of Object Identifier.
875  *              Parameters:
876  *              asn1:    pointer to ASN1 socket.
877  *              enc_len: length of encoding of value.
878  *              oid:     pointer to variable we set to Object Identifier.
879  *              len:     Length of Object Identifier in gulongs.
880  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
881  */
882 int
883 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
884 {
885     int          ret;
886     int          eoc;
887     subid_t      subid;
888     guint        size;
889     subid_t      *optr;
890
891     /*
892      * First, make sure the entire string is in the tvbuff, and throw
893      * an exception if it isn't.  If the length is bogus, this should
894      * keep us from trying to allocate an immensely large buffer.
895      * (It won't help if the length is *valid* but immensely large,
896      * but that's another matter; in any case, that would happen only
897      * if we had an immensely large tvbuff....)
898      */
899     if (enc_len < 1) {
900         *oid = NULL;
901         return ASN1_ERR_LENGTH_MISMATCH;
902     }
903     tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
904
905     eoc = asn1->offset + enc_len;
906
907     size = enc_len + 1;
908     *oid = g_malloc(size * sizeof(gulong));
909     optr = *oid;
910
911     ret = asn1_subid_decode (asn1, &subid);
912     if (ret != ASN1_ERR_NOERROR) {
913         g_free(*oid);
914         *oid = NULL;
915         return ret;
916     }
917     if (subid < 40) {
918         optr[0] = 0;
919         optr[1] = subid;
920     } else if (subid < 80) {
921         optr[0] = 1;
922         optr[1] = subid - 40;
923     } else {
924         optr[0] = 2;
925         optr[1] = subid - 80;
926     }
927     *len = 2;
928     optr += 2;
929     while (asn1->offset < eoc) {
930         if (++(*len) > size) {
931             g_free(*oid);
932             *oid = NULL;
933             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
934         }
935         ret = asn1_subid_decode (asn1, optr++);
936         if (ret != ASN1_ERR_NOERROR) {
937             g_free(*oid);
938             *oid = NULL;
939             return ret;
940         }
941     }
942     return ASN1_ERR_NOERROR;
943 }
944
945 /*
946  * NAME:        asn1_oid_decode                                [API]
947  * SYNOPSIS:    int asn1_oid_decode
948  *                  (
949  *                      ASN1_SCK *asn1,
950  *                      subid_t  **oid,
951  *                      guint    *len,
952  *                      guint    *nbytes
953  *                  )
954  * DESCRIPTION: Decodes Object Identifier.
955  *              Parameters:
956  *              asn1:   pointer to ASN1 socket.
957  *              oid:    pointer to variable we set to Object Identifier.
958  *              len:    Length of Object Identifier in gulongs.
959  *              nbytes: number of bytes used to encode.
960  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
961  */
962 int
963 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
964 {
965     int          ret;
966     int          start;
967     guint        cls;
968     guint        con;
969     guint        tag;
970     gboolean     def;
971     guint        enc_len;
972
973     start = asn1->offset;
974     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
975     if (ret != ASN1_ERR_NOERROR)
976         goto done;
977     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
978         ret = ASN1_ERR_WRONG_TYPE;
979         goto done;
980     }
981     if (!def) {
982         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
983         goto done;
984     }
985
986     ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
987
988 done:
989     *nbytes = asn1->offset - start;
990     return ret;
991 }
992
993 /*
994  * NAME:        asn1_sequence_decode                             [API]
995  * SYNOPSIS:    int asn1_sequence_decode
996  *                  (
997  *                      ASN1_SCK  *asn1,
998  *                      guint     *seq_len,
999  *                      guint     *nbytes
1000  *                  )
1001  * DESCRIPTION: Decodes header for SEQUENCE.
1002  *              Parameters:
1003  *              asn1:    pointer to ASN1 socket.
1004  *              seq_len: length of sequence.
1005  *              nbytes:  number of bytes used to encode header.
1006  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
1007  */
1008 int
1009 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
1010 {
1011     int          ret;
1012     int          start;
1013     guint        cls;
1014     guint        con;
1015     guint        tag;
1016     gboolean     def;
1017
1018     start = asn1->offset;
1019     ret = asn1_header_decode(asn1, &cls, &con, &tag,
1020             &def, seq_len);
1021     if (ret != ASN1_ERR_NOERROR)
1022         goto done;
1023     if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
1024         ret = ASN1_ERR_WRONG_TYPE;
1025         goto done;
1026     }
1027     if (!def) {
1028         /* XXX - might some sequences have an indefinite length? */
1029         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
1030         goto done;
1031     }
1032     ret = ASN1_ERR_NOERROR;
1033
1034 done:
1035     *nbytes = asn1->offset - start;
1036     return ret;
1037 }
1038
1039 /*
1040  * NAME:        asn1_err_to_str                             [API]
1041  * SYNOPSIS:    const char *asn1_err_to_str
1042  *                  (
1043  *                      int     err
1044  *                  )
1045  * DESCRIPTION: Returns the string corresponding to an ASN.1 library error.
1046  *              Parameters:
1047  *              err: the error code
1048  * RETURNS:     string for the error
1049  */
1050 const char *
1051 asn1_err_to_str(int err)
1052 {
1053     const char   *errstr;
1054     char         errstrbuf[14+1+1+11+1+1];      /* "Unknown error (%d)\0" */
1055
1056     switch (err) {
1057
1058     case ASN1_ERR_EOC_MISMATCH:
1059         errstr = "EOC mismatch";
1060         break;
1061
1062     case ASN1_ERR_WRONG_TYPE:
1063         errstr = "Wrong type for that item";
1064         break;
1065
1066     case ASN1_ERR_LENGTH_NOT_DEFINITE:
1067         errstr = "Length was indefinite";
1068         break;
1069
1070     case ASN1_ERR_LENGTH_MISMATCH:
1071         errstr = "Length mismatch";
1072         break;
1073
1074     case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
1075         errstr = "Wrong length for that item's type";
1076         break;
1077
1078     default:
1079         g_snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);
1080         errstr = errstrbuf;
1081         break;
1082     }
1083     return errstr;
1084 }