Rename "asn1_octet_string_value_decode()" to
[obnox/wireshark/wip.git] / asn1.c
1 /* asn1.c
2  * Routines for ASN.1 BER dissection
3  *
4  * $Id: asn1.c,v 1.6 2000/12/24 09:10:11 guy 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_string_value_decode                       [API]
635  * SYNOPSIS:    int asn1_string_value_decode
636  *                  (
637  *                      ASN1_SCK *asn1,
638  *                      int      enc_len,
639  *                      guchar   **octets
640  *                  )
641  * DESCRIPTION: Decodes value portion of string (Octet String, various
642  *              character string types)
643  *              Parameters:
644  *              asn1:    pointer to ASN1 socket.
645  *              enc_len: length of encoding of value.
646  *              octets:  pointer to variable we set to point to string.
647  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
648  */
649 int
650 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
651 {
652     int          ret;
653     const guchar *eoc;
654     guchar       *ptr;
655
656     eoc = asn1->pointer + enc_len;
657     *octets = g_malloc (enc_len);
658     ptr = *octets;
659     while (asn1->pointer < eoc) {
660         ret = asn1_octet_decode (asn1, (guchar *)ptr++);
661         if (ret != ASN1_ERR_NOERROR) {
662             g_free(*octets);
663             *octets = NULL;
664             return ret;
665         }
666     }
667     return ASN1_ERR_NOERROR;
668 }
669
670 /*
671  * NAME:        asn1_string_decode                             [API]
672  * SYNOPSIS:    int asn1_string_decode
673  *                  (
674  *                      ASN1_SCK  *asn1,
675  *                      guchar    **octets,
676  *                      guint     *str_len,
677  *                      guint     *nbytes,
678  *                      guint     expected_tag
679  *                  )
680  * DESCRIPTION: Decodes string (Octet String, various character string
681  *              types)
682  *              Parameters:
683  *              asn1:         pointer to ASN1 socket.
684  *              octets:       pointer to variable we set to point to string.
685  *              str_len:      length of octet_string.
686  *              nbytes:       number of bytes used to encode.
687  *              expected_tag: tag expected for this type of string.
688  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
689  */
690 int
691 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
692                         guint *nbytes, guint expected_tag)
693 {
694     int          ret;
695     const guchar *start;
696     int          enc_len;
697     guint        cls;
698     guint        con;
699     guint        tag;
700     gboolean     def;
701
702     start = asn1->pointer;
703     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
704     if (ret != ASN1_ERR_NOERROR)
705         goto done;
706     if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
707         /* XXX - handle the constructed encoding? */
708         ret = ASN1_ERR_WRONG_TYPE;
709         goto done;
710     }
711     if (!def) {
712         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
713         goto done;
714     }
715
716     ret = asn1_string_value_decode (asn1, enc_len, octets);
717     *str_len = enc_len;
718
719 done:
720     *nbytes = asn1->pointer - start;
721     return ret;
722 }
723
724 /*
725  * NAME:        asn1_octet_string_decode                             [API]
726  * SYNOPSIS:    int asn1_octet_string_decode
727  *                  (
728  *                      ASN1_SCK  *asn1,
729  *                      guchar    **octets,
730  *                      guint     *str_len,
731  *                      guint     *nbytes,
732  *                  )
733  * DESCRIPTION: Decodes Octet String.
734  *              Parameters:
735  *              asn1:    pointer to ASN1 socket.
736  *              octets:  pointer to variable we set to point to string.
737  *              str_len: length of octet_string.
738  *              nbytes:  number of bytes used to encode.
739  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
740  */
741 int
742 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
743                         guint *nbytes)
744 {
745     return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
746 }
747
748 /*
749  * NAME:        asn1_subid_decode
750  * SYNOPSIS:    int asn1_subid_decode
751  *                  (
752  *                      ASN1_SCK *asn1,
753  *                      subid_t  *subid
754  *                  )
755  * DESCRIPTION: Decodes Sub Identifier.
756  *              Parameters:
757  *              asn1:  pointer to ASN1 socket.
758  *              subid: Sub Identifier.
759  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
760  */
761 int
762 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
763 {
764     int    ret;
765     guchar ch;
766
767     *subid = 0;
768     do {
769         ret = asn1_octet_decode(asn1, &ch);
770         if (ret != ASN1_ERR_NOERROR)
771             return ret;
772         *subid <<= 7;
773         *subid |= ch & 0x7F;
774     } while ((ch & 0x80) == 0x80);
775     return ASN1_ERR_NOERROR;
776 }
777
778 /*
779  * NAME:        asn1_oid_value_decode                                [API]
780  * SYNOPSIS:    int asn1_oid_value_decode
781  *                  (
782  *                      ASN1_SCK *asn1,
783  *                      int      enc_len,
784  *                      subid_t  **oid,
785  *                      guint    *len
786  *                  )
787  * DESCRIPTION: Decodes value portion of Object Identifier.
788  *              Parameters:
789  *              asn1:    pointer to ASN1 socket.
790  *              enc_len: length of encoding of value.
791  *              oid:     pointer to variable we set to Object Identifier.
792  *              len:     Length of Object Identifier in gulongs.
793  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
794  */
795 int
796 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
797 {
798     int          ret;
799     const guchar *eoc;
800     subid_t      subid;
801     guint        size;
802     subid_t      *optr;
803
804     eoc = asn1->pointer + enc_len;
805     size = enc_len + 1;
806     *oid = g_malloc(size * sizeof(gulong));
807     optr = *oid;
808  
809     ret = asn1_subid_decode (asn1, &subid);
810     if (ret != ASN1_ERR_NOERROR) {
811         g_free(*oid);
812         *oid = NULL;
813         return ret;
814     }
815     if (subid < 40) {
816         optr[0] = 0;
817         optr[1] = subid;
818     } else if (subid < 80) {
819         optr[0] = 1;
820         optr[1] = subid - 40;
821     } else {
822         optr[0] = 2;
823         optr[1] = subid - 80;
824     }
825     *len = 2;
826     optr += 2;
827     while (asn1->pointer < eoc) {
828         if (++(*len) > size) {
829             g_free(*oid);
830             *oid = NULL;
831             return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
832         }
833         ret = asn1_subid_decode (asn1, optr++);
834         if (ret != ASN1_ERR_NOERROR) {
835             g_free(*oid);
836             *oid = NULL;
837             return ret;
838         }
839     }
840     return ASN1_ERR_NOERROR;
841 }
842
843 /*
844  * NAME:        asn1_oid_decode                                [API]
845  * SYNOPSIS:    int asn1_oid_decode
846  *                  (
847  *                      ASN1_SCK *asn1,
848  *                      subid_t  **oid,
849  *                      guint    *len,
850  *                      guint    *nbytes
851  *                  )
852  * DESCRIPTION: Decodes Object Identifier.
853  *              Parameters:
854  *              asn1:   pointer to ASN1 socket.
855  *              oid:    pointer to variable we set to Object Identifier.
856  *              len:    Length of Object Identifier in gulongs.
857  *              nbytes: number of bytes used to encode.
858  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
859  */
860 int
861 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
862 {
863     int          ret;
864     const guchar *start;
865     guint        cls;
866     guint        con;
867     guint        tag;
868     gboolean     def;
869     guint        enc_len;
870
871     start = asn1->pointer;
872     ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
873     if (ret != ASN1_ERR_NOERROR)
874         goto done;
875     if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
876         ret = ASN1_ERR_WRONG_TYPE;
877         goto done;
878     }
879     if (!def) {
880         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
881         goto done;
882     }
883
884     ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
885
886 done:
887     *nbytes = asn1->pointer - start;
888     return ret;
889 }
890
891 /*
892  * NAME:        asn1_sequence_decode                             [API]
893  * SYNOPSIS:    int asn1_sequence_decode
894  *                  (
895  *                      ASN1_SCK  *asn1,
896  *                      guint     *seq_len,
897  *                      guint     *nbytes
898  *                  )
899  * DESCRIPTION: Decodes header for SEQUENCE.
900  *              Parameters:
901  *              asn1:    pointer to ASN1 socket.
902  *              seq_len: length of sequence.
903  *              nbytes:  number of bytes used to encode header.
904  * RETURNS:     ASN1_ERR value (ASN1_ERR_NOERROR on success)
905  */
906 int
907 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
908 {
909     int          ret;
910     const guchar *start;
911     guint        cls;
912     guint        con;
913     guint        tag;
914     gboolean     def;
915
916     start = asn1->pointer;
917     ret = asn1_header_decode(asn1, &cls, &con, &tag,
918             &def, seq_len);
919     if (ret != ASN1_ERR_NOERROR)
920         goto done;
921     if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
922         ret = ASN1_ERR_WRONG_TYPE;
923         goto done;
924     }
925     if (!def) {
926         /* XXX - might some sequences have an indefinite length? */
927         ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
928         goto done;
929     }
930     ret = ASN1_ERR_NOERROR;
931
932 done:
933     *nbytes = asn1->pointer - start;
934     return ret;
935 }