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