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