2 * Routines for ASN.1 BER dissection
4 * $Id: asn1.c,v 1.8 2002/01/21 07:36:31 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
9 * Based on "g_asn1.c" from:
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
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.
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.
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.
34 * SYSTEM NAME: ASN1 Basic Encoding
35 * ORIGINAL AUTHOR(S): Dirk Wisse
37 * CREATION DATE: 1990/11/22
39 * DESCRIPTION: ASN1 Basic Encoding Rules.
41 * To decode this we must do:
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);
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.
63 #ifdef HAVE_SYS_TYPES_H
64 # include <sys/types.h>
72 #include <epan/tvbuff.h>
76 * NAME: asn1_open [API]
77 * SYNOPSIS: void asn1_open
83 * DESCRIPTION: Opens an ASN1 socket.
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.
94 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
97 asn1->offset = offset;
101 * NAME: asn1_close [API]
102 * SYNOPSIS: void asn1_close
107 * DESCRIPTION: Closes an ASN1 socket.
109 * asn1: pointer to ASN1 socket.
110 * offset: pointer to variable into which current offset is
116 asn1_close(ASN1_SCK *asn1, int *offset)
118 *offset = asn1->offset;
122 * NAME: asn1_octet_decode
123 * SYNOPSIS: int asn1_octet_decode
128 * DESCRIPTION: Decodes an octet.
129 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
132 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
134 *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
136 return ASN1_ERR_NOERROR;
140 * NAME: asn1_tag_decode
141 * SYNOPSIS: int asn1_tag_decode
146 * DESCRIPTION: Decodes a tag.
147 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
150 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
157 ret = asn1_octet_decode (asn1, &ch);
158 if (ret != ASN1_ERR_NOERROR)
162 } while ((ch & 0x80) == 0x80);
163 return ASN1_ERR_NOERROR;
167 * NAME: asn1_id_decode
168 * SYNOPSIS: int asn1_id_decode
175 * DESCRIPTION: Decodes an identifier.
176 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
179 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
184 ret = asn1_octet_decode (asn1, &ch);
185 if (ret != ASN1_ERR_NOERROR)
187 *cls = (ch & 0xC0) >> 6;
188 *con = (ch & 0x20) >> 5;
191 ret = asn1_tag_decode (asn1, tag);
192 if (ret != ASN1_ERR_NOERROR)
195 return ASN1_ERR_NOERROR;
199 * NAME: asn1_length_decode
200 * SYNOPSIS: int asn1_length_decode
206 * DESCRIPTION: Decodes an ASN1 length.
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)
215 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
220 ret = asn1_octet_decode (asn1, &ch);
221 if (ret != ASN1_ERR_NOERROR)
224 *def = FALSE; /* indefinite length */
226 *def = TRUE; /* definite length */
230 cnt = (guchar) (ch & 0x7F);
233 ret = asn1_octet_decode (asn1, &ch);
234 if (ret != ASN1_ERR_NOERROR)
242 return ASN1_ERR_NOERROR;
246 * NAME: asn1_header_decode [API]
247 * SYNOPSIS: int asn1_header_decode
256 * DESCRIPTION: Decodes an ASN1 header.
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)
267 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
268 gboolean *defp, guint *lenp)
273 ret = asn1_id_decode (asn1, cls, con, tag);
274 if (ret != ASN1_ERR_NOERROR)
276 ret = asn1_length_decode (asn1, &def, &len);
277 if (ret != ASN1_ERR_NOERROR)
281 return ASN1_ERR_NOERROR;
286 * NAME: asn1_eoc [API]
287 * SYNOPSIS: gboolean asn1_eoc
292 * DESCRIPTION: Checks if decoding is at End Of Contents.
294 * asn1: pointer to ASN1 socket.
295 * eoc: offset of end of encoding, or -1 if indefinite.
296 * RETURNS: gboolean success
299 asn1_eoc ( ASN1_SCK *asn1, int eoc)
302 return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
303 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
305 return (asn1->offset >= eoc);
309 * NAME: asn1_eoc_decode [API]
310 * SYNOPSIS: int asn1_eoc_decode
315 * DESCRIPTION: Decodes End Of Contents.
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)
330 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
336 ret = asn1_octet_decode (asn1, &ch);
337 if (ret != ASN1_ERR_NOERROR)
340 return ASN1_ERR_EOC_MISMATCH;
341 ret = asn1_octet_decode (asn1, &ch);
342 if (ret != ASN1_ERR_NOERROR)
345 return ASN1_ERR_EOC_MISMATCH;
346 return ASN1_ERR_NOERROR;
348 if (asn1->offset != eoc)
349 return ASN1_ERR_LENGTH_MISMATCH;
350 return ASN1_ERR_NOERROR;
355 * NAME: asn1_null_decode [API]
356 * SYNOPSIS: int asn1_null_decode
361 * DESCRIPTION: Decodes Null.
363 * asn1: pointer to ASN1 socket.
364 * enc_len: length of encoding of value.
365 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
368 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
370 asn1->offset += enc_len;
371 return ASN1_ERR_NOERROR;
375 * NAME: asn1_bool_decode [API]
376 * SYNOPSIS: int asn1_bool_decode
382 * DESCRIPTION: Decodes Boolean.
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)
390 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *bool)
396 return ASN1_ERR_LENGTH_MISMATCH;
397 ret = asn1_octet_decode (asn1, &ch);
398 if (ret != ASN1_ERR_NOERROR)
400 *bool = ch ? TRUE : FALSE;
401 return ASN1_ERR_NOERROR;
405 * NAME: asn1_int32_value_decode [API]
406 * SYNOPSIS: int asn1_int32_value_decode
412 * DESCRIPTION: Decodes value portion of Integer (which must be no more
415 * asn1: pointer to ASN1 socket.
416 * enc_len: length of encoding of value.
418 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
421 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
428 eoc = asn1->offset + enc_len;
429 ret = asn1_octet_decode (asn1, &ch);
430 if (ret != ASN1_ERR_NOERROR)
432 *integer = (gint) ch;
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)
443 return ASN1_ERR_NOERROR;
447 * NAME: asn1_int32_decode [API]
448 * SYNOPSIS: int asn1_int32_decode
454 * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
456 * asn1: pointer to ASN1 socket.
458 * nbytes: number of bytes used to encode it.
459 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
462 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
472 start = asn1->offset;
473 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
474 if (ret != ASN1_ERR_NOERROR)
476 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
477 ret = ASN1_ERR_WRONG_TYPE;
481 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
484 ret = asn1_int32_value_decode (asn1, enc_len, integer);
487 *nbytes = asn1->offset - start;
492 * NAME: asn1_uint32_value_decode [API]
493 * SYNOPSIS: int asn1_uint32_value_decode
499 * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
500 * more than 32 bits).
502 * asn1: pointer to ASN1 socket.
503 * enc_len: length of encoding of value.
505 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
508 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint *integer)
515 eoc = asn1->offset + enc_len;
516 ret = asn1_octet_decode (asn1, &ch);
517 if (ret != ASN1_ERR_NOERROR)
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)
533 return ASN1_ERR_NOERROR;
537 * NAME: asn1_uint32_decode [API]
538 * SYNOPSIS: int asn1_uint32_decode
544 * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
546 * asn1: pointer to ASN1 socket.
548 * nbytes: number of bytes used to encode it.
549 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
552 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
562 start = asn1->offset;
563 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
564 if (ret != ASN1_ERR_NOERROR)
566 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
567 ret = ASN1_ERR_WRONG_TYPE;
571 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
574 ret = asn1_uint32_value_decode (asn1, enc_len, integer);
577 *nbytes = asn1->offset - start;
582 * NAME: asn1_bits_decode [API]
583 * SYNOPSIS: int asn1_bits_decode
592 * DESCRIPTION: Decodes Bit String.
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)
603 asn1_bits_decode ( ASN1_SCK *asn1, int eoc, guchar **bits,
604 guint *len, guchar *unused)
610 ret = asn1_octet_decode (asn1, unused);
611 if (ret != ASN1_ERR_NOERROR)
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) {
623 return ASN1_ERR_NOERROR;
627 * NAME: asn1_string_value_decode [API]
628 * SYNOPSIS: int asn1_string_value_decode
634 * DESCRIPTION: Decodes value portion of string (Octet String, various
635 * character string types)
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)
643 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
649 eoc = asn1->offset + enc_len;
650 *octets = g_malloc (enc_len);
652 while (asn1->offset < eoc) {
653 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
654 if (ret != ASN1_ERR_NOERROR) {
660 return ASN1_ERR_NOERROR;
664 * NAME: asn1_string_decode [API]
665 * SYNOPSIS: int asn1_string_decode
673 * DESCRIPTION: Decodes string (Octet String, various character string
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)
684 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
685 guint *nbytes, guint expected_tag)
695 start = asn1->offset;
696 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
697 if (ret != ASN1_ERR_NOERROR)
699 if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
700 /* XXX - handle the constructed encoding? */
701 ret = ASN1_ERR_WRONG_TYPE;
705 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
709 ret = asn1_string_value_decode (asn1, enc_len, octets);
713 *nbytes = asn1->offset - start;
718 * NAME: asn1_octet_string_decode [API]
719 * SYNOPSIS: int asn1_octet_string_decode
726 * DESCRIPTION: Decodes Octet String.
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)
735 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
738 return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
742 * NAME: asn1_subid_decode
743 * SYNOPSIS: int asn1_subid_decode
748 * DESCRIPTION: Decodes Sub Identifier.
750 * asn1: pointer to ASN1 socket.
751 * subid: Sub Identifier.
752 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
755 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
762 ret = asn1_octet_decode(asn1, &ch);
763 if (ret != ASN1_ERR_NOERROR)
767 } while ((ch & 0x80) == 0x80);
768 return ASN1_ERR_NOERROR;
772 * NAME: asn1_oid_value_decode [API]
773 * SYNOPSIS: int asn1_oid_value_decode
780 * DESCRIPTION: Decodes value portion of Object Identifier.
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)
789 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
797 eoc = asn1->offset + enc_len;
799 *oid = g_malloc(size * sizeof(gulong));
802 ret = asn1_subid_decode (asn1, &subid);
803 if (ret != ASN1_ERR_NOERROR) {
811 } else if (subid < 80) {
813 optr[1] = subid - 40;
816 optr[1] = subid - 80;
820 while (asn1->offset < eoc) {
821 if (++(*len) > size) {
824 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
826 ret = asn1_subid_decode (asn1, optr++);
827 if (ret != ASN1_ERR_NOERROR) {
833 return ASN1_ERR_NOERROR;
837 * NAME: asn1_oid_decode [API]
838 * SYNOPSIS: int asn1_oid_decode
845 * DESCRIPTION: Decodes Object Identifier.
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)
854 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
864 start = asn1->offset;
865 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
866 if (ret != ASN1_ERR_NOERROR)
868 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
869 ret = ASN1_ERR_WRONG_TYPE;
873 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
877 ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
880 *nbytes = asn1->offset - start;
885 * NAME: asn1_sequence_decode [API]
886 * SYNOPSIS: int asn1_sequence_decode
892 * DESCRIPTION: Decodes header for SEQUENCE.
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)
900 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
909 start = asn1->offset;
910 ret = asn1_header_decode(asn1, &cls, &con, &tag,
912 if (ret != ASN1_ERR_NOERROR)
914 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
915 ret = ASN1_ERR_WRONG_TYPE;
919 /* XXX - might some sequences have an indefinite length? */
920 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
923 ret = ASN1_ERR_NOERROR;
926 *nbytes = asn1->offset - start;