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