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