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