From Andreas Sikkema:
[metze/wireshark/wip.git] / asn1.c
1 /* asn1.c
2  * Routines for ASN.1 BER dissection
3  *
4  * $Id: asn1.c,v 1.21 2003/08/29 19:13:28 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     eoc = asn1->offset + enc_len;
611     *bits = NULL;
612     ret = asn1_octet_decode (asn1, unused);
613     if (ret != ASN1_ERR_NOERROR)
614         return ret;
615     *len = 0;
616
617     /*
618      * First, make sure the entire string is in the tvbuff, and throw
619      * an exception if it isn't.  If the length is bogus, this should
620      * keep us from trying to allocate an immensely large buffer.
621      * (It won't help if the length is *valid* but immensely large,
622      * but that's another matter; in any case, that would happen only
623      * if we had an immensely large tvbuff....)
624      */
625     if (enc_len != 0) {
626         tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
627         *bits = g_malloc (enc_len);
628     } else {
629         /*
630          * If the length is 0, we allocate a 1-byte buffer, as
631          * "g_malloc()" returns NULL if passed 0 as an argument,
632          * and our caller expects us to return a pointer to a
633          * buffer.
634          */
635         *bits = g_malloc (1);
636     }
637
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  *                       which is '\0' terminated for ease of use as C-string
666  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
667  */
668 int
669 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
670 {
671     int          ret;
672     int          eoc;
673     guchar       *ptr;
674
675     /*
676      * First, make sure the entire string is in the tvbuff, and throw
677      * an exception if it isn't.  If the length is bogus, this should
678      * keep us from trying to allocate an immensely large buffer.
679      * (It won't help if the length is *valid* but immensely large,
680      * but that's another matter; in any case, that would happen only
681      * if we had an immensely large tvbuff....)
682      */
683     if (enc_len != 0)
684         tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
685     *octets = g_malloc (enc_len+1);
686
687     eoc = asn1->offset + enc_len;
688     ptr = *octets;
689     while (asn1->offset < eoc) {
690         ret = asn1_octet_decode (asn1, (guchar *)ptr++);
691         if (ret != ASN1_ERR_NOERROR) {
692             g_free(*octets);
693             *octets = NULL;
694             return ret;
695         }
696     }
697     *(guchar *)ptr = '\0';
698     return ASN1_ERR_NOERROR;
699 }
700
701 /*
702  * NAME:        asn1_string_decode                             [API]
703  * SYNOPSIS:    int asn1_string_decode
704  *                  (
705  *                      ASN1_SCK  *asn1,
706  *                      guchar    **octets,
707  *                      guint     *str_len,
708  *                      guint     *nbytes,
709  *                      guint     expected_tag
710  *                  )
711  * DESCRIPTION: Decodes string (Octet String, various character string
712  *              types)
713  *              Parameters:
714  *              asn1:         pointer to ASN1 socket.
715  *              octets:       pointer to variable we set to point to string.
716  *              str_len:      length of octet_string.
717  *              nbytes:       number of bytes used to encode.
718  *              expected_tag: tag expected for this type of string.
719  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
720  */
721 int
722 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
723                         guint *nbytes, guint expected_tag)
724 {
725     int          ret;
726     int          start;
727     int          enc_len;
728     guint        cls;
729     guint        con;
730     guint        tag;
731     gboolean     def;
732
733     start = asn1->offset;
734     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
735     if (ret != ASN1_ERR_NOERROR)
736         goto done;
737     if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
738         /* XXX - handle the constructed encoding? */
739         ret = ASN1_ERR_WRONG_TYPE;
740         goto done;
741     }
742     if (!def) {
743         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
744         goto done;
745     }
746
747     ret = asn1_string_value_decode (asn1, enc_len, octets);
748     *str_len = enc_len;
749
750 done:
751     *nbytes = asn1->offset - start;
752     return ret;
753 }
754
755 /*
756  * NAME:        asn1_octet_string_decode                             [API]
757  * SYNOPSIS:    int asn1_octet_string_decode
758  *                  (
759  *                      ASN1_SCK  *asn1,
760  *                      guchar    **octets,
761  *                      guint     *str_len,
762  *                      guint     *nbytes,
763  *                  )
764  * DESCRIPTION: Decodes Octet String.
765  *              Parameters:
766  *              asn1:    pointer to ASN1 socket.
767  *              octets:  pointer to variable we set to point to string.
768  *              str_len: length of octet_string.
769  *              nbytes:  number of bytes used to encode.
770  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
771  */
772 int
773 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
774                         guint *nbytes)
775 {
776     return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
777 }
778
779 /*
780  * NAME:        asn1_subid_decode
781  * SYNOPSIS:    int asn1_subid_decode
782  *                  (
783  *                      ASN1_SCK *asn1,
784  *                      subid_t  *subid
785  *                  )
786  * DESCRIPTION: Decodes Sub Identifier.
787  *              Parameters:
788  *              asn1:  pointer to ASN1 socket.
789  *              subid: Sub Identifier.
790  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
791  */
792 int
793 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
794 {
795     int    ret;
796     guchar ch;
797
798     *subid = 0;
799     do {
800         ret = asn1_octet_decode(asn1, &ch);
801         if (ret != ASN1_ERR_NOERROR)
802             return ret;
803         *subid <<= 7;
804         *subid |= ch & 0x7F;
805     } while ((ch & 0x80) == 0x80);
806     return ASN1_ERR_NOERROR;
807 }
808
809 /*
810  * NAME:        asn1_oid_value_decode                                [API]
811  * SYNOPSIS:    int asn1_oid_value_decode
812  *                  (
813  *                      ASN1_SCK *asn1,
814  *                      int      enc_len,
815  *                      subid_t  **oid,
816  *                      guint    *len
817  *                  )
818  * DESCRIPTION: Decodes value portion of Object Identifier.
819  *              Parameters:
820  *              asn1:    pointer to ASN1 socket.
821  *              enc_len: length of encoding of value.
822  *              oid:     pointer to variable we set to Object Identifier.
823  *              len:     Length of Object Identifier in gulongs.
824  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
825  */
826 int
827 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
828 {
829     int          ret;
830     int          eoc;
831     subid_t      subid;
832     guint        size;
833     subid_t      *optr;
834
835     /*
836      * First, make sure the entire string is in the tvbuff, and throw
837      * an exception if it isn't.  If the length is bogus, this should
838      * keep us from trying to allocate an immensely large buffer.
839      * (It won't help if the length is *valid* but immensely large,
840      * but that's another matter; in any case, that would happen only
841      * if we had an immensely large tvbuff....)
842      */
843     if (enc_len != 0)
844         tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
845
846     eoc = asn1->offset + enc_len;
847
848     size = enc_len + 1;
849     *oid = g_malloc(size * sizeof(gulong));
850     optr = *oid;
851
852     ret = asn1_subid_decode (asn1, &subid);
853     if (ret != ASN1_ERR_NOERROR) {
854         g_free(*oid);
855         *oid = NULL;
856         return ret;
857     }
858     if (subid < 40) {
859         optr[0] = 0;
860         optr[1] = subid;
861     } else if (subid < 80) {
862         optr[0] = 1;
863         optr[1] = subid - 40;
864     } else {
865         optr[0] = 2;
866         optr[1] = subid - 80;
867     }
868     *len = 2;
869     optr += 2;
870     while (asn1->offset < eoc) {
871         if (++(*len) > size) {
872             g_free(*oid);
873             *oid = NULL;
874             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
875         }
876         ret = asn1_subid_decode (asn1, optr++);
877         if (ret != ASN1_ERR_NOERROR) {
878             g_free(*oid);
879             *oid = NULL;
880             return ret;
881         }
882     }
883     return ASN1_ERR_NOERROR;
884 }
885
886 /*
887  * NAME:        asn1_oid_decode                                [API]
888  * SYNOPSIS:    int asn1_oid_decode
889  *                  (
890  *                      ASN1_SCK *asn1,
891  *                      subid_t  **oid,
892  *                      guint    *len,
893  *                      guint    *nbytes
894  *                  )
895  * DESCRIPTION: Decodes Object Identifier.
896  *              Parameters:
897  *              asn1:   pointer to ASN1 socket.
898  *              oid:    pointer to variable we set to Object Identifier.
899  *              len:    Length of Object Identifier in gulongs.
900  *              nbytes: number of bytes used to encode.
901  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
902  */
903 int
904 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
905 {
906     int          ret;
907     int          start;
908     guint        cls;
909     guint        con;
910     guint        tag;
911     gboolean     def;
912     guint        enc_len;
913
914     start = asn1->offset;
915     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
916     if (ret != ASN1_ERR_NOERROR)
917         goto done;
918     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
919         ret = ASN1_ERR_WRONG_TYPE;
920         goto done;
921     }
922     if (!def) {
923         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
924         goto done;
925     }
926
927     ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
928
929 done:
930     *nbytes = asn1->offset - start;
931     return ret;
932 }
933
934 /*
935  * NAME:        asn1_sequence_decode                             [API]
936  * SYNOPSIS:    int asn1_sequence_decode
937  *                  (
938  *                      ASN1_SCK  *asn1,
939  *                      guint     *seq_len,
940  *                      guint     *nbytes
941  *                  )
942  * DESCRIPTION: Decodes header for SEQUENCE.
943  *              Parameters:
944  *              asn1:    pointer to ASN1 socket.
945  *              seq_len: length of sequence.
946  *              nbytes:  number of bytes used to encode header.
947  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
948  */
949 int
950 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
951 {
952     int          ret;
953     int          start;
954     guint        cls;
955     guint        con;
956     guint        tag;
957     gboolean     def;
958
959     start = asn1->offset;
960     ret = asn1_header_decode(asn1, &cls, &con, &tag,
961             &def, seq_len);
962     if (ret != ASN1_ERR_NOERROR)
963         goto done;
964     if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
965         ret = ASN1_ERR_WRONG_TYPE;
966         goto done;
967     }
968     if (!def) {
969         /* XXX - might some sequences have an indefinite length? */
970         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
971         goto done;
972     }
973     ret = ASN1_ERR_NOERROR;
974
975 done:
976     *nbytes = asn1->offset - start;
977     return ret;
978 }
979
980 /*
981  * NAME:        asn1_err_to_str                             [API]
982  * SYNOPSIS:    char *asn1_err_to_str
983  *                  (
984  *                      int     err
985  *                  )
986  * DESCRIPTION: Returns the string corresponding to an ASN.1 library error.
987  *              Parameters:
988  *              err: the error code
989  * RETURNS:     string for the error
990  */
991 char *
992 asn1_err_to_str(int err)
993 {
994     char         *errstr;
995     char         errstrbuf[14+1+1+11+1+1];      /* "Unknown error (%d)\0" */
996
997     switch (err) {
998
999     case ASN1_ERR_EOC_MISMATCH:
1000         errstr = "EOC mismatch";
1001         break;
1002
1003     case ASN1_ERR_WRONG_TYPE:
1004         errstr = "Wrong type for that item";
1005         break;
1006
1007     case ASN1_ERR_LENGTH_NOT_DEFINITE:
1008         errstr = "Length was indefinite";
1009         break;
1010
1011     case ASN1_ERR_LENGTH_MISMATCH:
1012         errstr = "Length mismatch";
1013         break;
1014
1015     case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
1016         errstr = "Wrong length for that item's type";
1017         break;
1018
1019     default:
1020         snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);
1021         errstr = errstrbuf;
1022         break;
1023     }
1024     return errstr;
1025 }