2 * Routines for ASN.1 BER dissection
4 * $Id: asn1.c,v 1.12 2002/03/05 09:18:58 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.
65 #ifdef HAVE_SYS_TYPES_H
66 # include <sys/types.h>
77 #ifdef NEED_SNPRINTF_H
78 # include "snprintf.h"
81 #include <epan/tvbuff.h>
85 * NAME: asn1_open [API]
86 * SYNOPSIS: void asn1_open
92 * DESCRIPTION: Opens an ASN1 socket.
94 * asn1: pointer to ASN1 socket.
95 * tvb: Tvbuff for encoding.
96 * offset: Current offset in tvbuff.
97 * Encoding starts at the end of the buffer, and
98 * proceeds to the beginning.
103 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
106 asn1->offset = offset;
110 * NAME: asn1_close [API]
111 * SYNOPSIS: void asn1_close
116 * DESCRIPTION: Closes an ASN1 socket.
118 * asn1: pointer to ASN1 socket.
119 * offset: pointer to variable into which current offset is
125 asn1_close(ASN1_SCK *asn1, int *offset)
127 *offset = asn1->offset;
131 * NAME: asn1_octet_decode
132 * SYNOPSIS: int asn1_octet_decode
137 * DESCRIPTION: Decodes an octet.
138 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
141 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
143 *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
145 return ASN1_ERR_NOERROR;
149 * NAME: asn1_tag_decode
150 * SYNOPSIS: int asn1_tag_decode
155 * DESCRIPTION: Decodes a tag.
156 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
159 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
166 ret = asn1_octet_decode (asn1, &ch);
167 if (ret != ASN1_ERR_NOERROR)
171 } while ((ch & 0x80) == 0x80);
172 return ASN1_ERR_NOERROR;
176 * NAME: asn1_id_decode
177 * SYNOPSIS: int asn1_id_decode
184 * DESCRIPTION: Decodes an identifier.
185 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
188 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
193 ret = asn1_octet_decode (asn1, &ch);
194 if (ret != ASN1_ERR_NOERROR)
196 *cls = (ch & 0xC0) >> 6;
197 *con = (ch & 0x20) >> 5;
200 ret = asn1_tag_decode (asn1, tag);
201 if (ret != ASN1_ERR_NOERROR)
204 return ASN1_ERR_NOERROR;
208 * NAME: asn1_length_decode
209 * SYNOPSIS: int asn1_length_decode
215 * DESCRIPTION: Decodes an ASN1 length.
217 * asn1: pointer to ASN1 socket.
218 * def: Boolean - TRUE if length definite, FALSE if not
219 * len: length, if length is definite
220 * DESCRIPTION: Decodes a definite or indefinite length.
221 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
224 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
229 ret = asn1_octet_decode (asn1, &ch);
230 if (ret != ASN1_ERR_NOERROR)
233 *def = FALSE; /* indefinite length */
235 *def = TRUE; /* definite length */
239 cnt = (guchar) (ch & 0x7F);
242 ret = asn1_octet_decode (asn1, &ch);
243 if (ret != ASN1_ERR_NOERROR)
251 return ASN1_ERR_NOERROR;
255 * NAME: asn1_header_decode [API]
256 * SYNOPSIS: int asn1_header_decode
265 * DESCRIPTION: Decodes an ASN1 header.
267 * asn1: pointer to ASN1 socket.
268 * cls: Class (see asn1.h)
269 * con: Primitive, Constructed (ASN1_PRI, ASN1_CON)
270 * tag: Tag (see asn1.h)
271 * defp: Boolean - TRUE if length definite, FALSE if not
272 * lenp: length, if length is definite
273 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
276 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
277 gboolean *defp, guint *lenp)
282 ret = asn1_id_decode (asn1, cls, con, tag);
283 if (ret != ASN1_ERR_NOERROR)
285 ret = asn1_length_decode (asn1, &def, &len);
286 if (ret != ASN1_ERR_NOERROR)
290 return ASN1_ERR_NOERROR;
295 * NAME: asn1_eoc [API]
296 * SYNOPSIS: gboolean asn1_eoc
301 * DESCRIPTION: Checks if decoding is at End Of Contents.
303 * asn1: pointer to ASN1 socket.
304 * eoc: offset of end of encoding, or -1 if indefinite.
305 * RETURNS: gboolean success
308 asn1_eoc ( ASN1_SCK *asn1, int eoc)
311 return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
312 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
314 return (asn1->offset >= eoc);
318 * NAME: asn1_eoc_decode [API]
319 * SYNOPSIS: int asn1_eoc_decode
324 * DESCRIPTION: Decodes End Of Contents.
326 * asn1: pointer to ASN1 socket.
327 * eoc: offset of end of encoding, or -1 if indefinite.
328 * If eoc is -1 it decodes an ASN1 End Of
329 * Contents (0x00 0x00), so it has to be an
330 * indefinite length encoding. If eoc is a non-negative
331 * integer, it probably was filled by asn1_header_decode,
332 * and should refer to the octet after the last of the encoding.
333 * It is checked if this offset refers to the octet to be
334 * decoded. This only takes place in decoding a
335 * definite length encoding.
336 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
339 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
345 ret = asn1_octet_decode (asn1, &ch);
346 if (ret != ASN1_ERR_NOERROR)
349 return ASN1_ERR_EOC_MISMATCH;
350 ret = asn1_octet_decode (asn1, &ch);
351 if (ret != ASN1_ERR_NOERROR)
354 return ASN1_ERR_EOC_MISMATCH;
355 return ASN1_ERR_NOERROR;
357 if (asn1->offset != eoc)
358 return ASN1_ERR_LENGTH_MISMATCH;
359 return ASN1_ERR_NOERROR;
364 * NAME: asn1_null_decode [API]
365 * SYNOPSIS: int asn1_null_decode
370 * DESCRIPTION: Decodes Null.
372 * asn1: pointer to ASN1 socket.
373 * enc_len: length of encoding of value.
374 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
377 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
379 asn1->offset += enc_len;
380 return ASN1_ERR_NOERROR;
384 * NAME: asn1_bool_decode [API]
385 * SYNOPSIS: int asn1_bool_decode
391 * DESCRIPTION: Decodes Boolean.
393 * asn1: pointer to ASN1 socket.
394 * enc_len: length of encoding of value.
395 * bool: False, True (0, !0).
396 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
399 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *bool)
405 return ASN1_ERR_LENGTH_MISMATCH;
406 ret = asn1_octet_decode (asn1, &ch);
407 if (ret != ASN1_ERR_NOERROR)
409 *bool = ch ? TRUE : FALSE;
410 return ASN1_ERR_NOERROR;
414 * NAME: asn1_int32_value_decode [API]
415 * SYNOPSIS: int asn1_int32_value_decode
421 * DESCRIPTION: Decodes value portion of Integer (which must be no more
424 * asn1: pointer to ASN1 socket.
425 * enc_len: length of encoding of value.
427 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
430 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
437 eoc = asn1->offset + enc_len;
438 ret = asn1_octet_decode (asn1, &ch);
439 if (ret != ASN1_ERR_NOERROR)
441 *integer = (gint) ch;
443 while (asn1->offset < eoc) {
444 if (++len > sizeof (gint32))
445 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
446 ret = asn1_octet_decode (asn1, &ch);
447 if (ret != ASN1_ERR_NOERROR)
452 return ASN1_ERR_NOERROR;
456 * NAME: asn1_int32_decode [API]
457 * SYNOPSIS: int asn1_int32_decode
463 * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
465 * asn1: pointer to ASN1 socket.
467 * nbytes: number of bytes used to encode it.
468 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
471 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
481 start = asn1->offset;
482 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
483 if (ret != ASN1_ERR_NOERROR)
485 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
486 ret = ASN1_ERR_WRONG_TYPE;
490 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
493 ret = asn1_int32_value_decode (asn1, enc_len, integer);
496 *nbytes = asn1->offset - start;
501 * NAME: asn1_uint32_value_decode [API]
502 * SYNOPSIS: int asn1_uint32_value_decode
508 * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
509 * more than 32 bits).
511 * asn1: pointer to ASN1 socket.
512 * enc_len: length of encoding of value.
514 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
517 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint *integer)
524 eoc = asn1->offset + enc_len;
525 ret = asn1_octet_decode (asn1, &ch);
526 if (ret != ASN1_ERR_NOERROR)
533 while (asn1->offset < eoc) {
534 if (++len > sizeof (guint32))
535 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
536 ret = asn1_octet_decode (asn1, &ch);
537 if (ret != ASN1_ERR_NOERROR)
542 return ASN1_ERR_NOERROR;
546 * NAME: asn1_uint32_decode [API]
547 * SYNOPSIS: int asn1_uint32_decode
553 * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
555 * asn1: pointer to ASN1 socket.
557 * nbytes: number of bytes used to encode it.
558 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
561 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
571 start = asn1->offset;
572 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
573 if (ret != ASN1_ERR_NOERROR)
575 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
576 ret = ASN1_ERR_WRONG_TYPE;
580 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
583 ret = asn1_uint32_value_decode (asn1, enc_len, integer);
586 *nbytes = asn1->offset - start;
591 * NAME: asn1_bits_decode [API]
592 * SYNOPSIS: int asn1_bits_decode
601 * DESCRIPTION: Decodes Bit String.
603 * asn1: pointer to ASN1 socket.
604 * eoc: offset of end of encoding, or -1 if indefinite.
605 * bits: pointer to begin of Bit String.
606 * size: Size of Bit String in characters.
607 * len: Length of Bit String in characters.
608 * unused: Number of unused bits in last character.
609 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
612 asn1_bits_decode ( ASN1_SCK *asn1, int eoc, guchar **bits,
613 guint *len, guchar *unused)
619 ret = asn1_octet_decode (asn1, unused);
620 if (ret != ASN1_ERR_NOERROR)
623 *bits = g_malloc(eoc - asn1->offset);
624 while (asn1->offset < eoc) {
625 ret = asn1_octet_decode (asn1, (guchar *)bits++);
626 if (ret != ASN1_ERR_NOERROR) {
632 return ASN1_ERR_NOERROR;
636 * NAME: asn1_string_value_decode [API]
637 * SYNOPSIS: int asn1_string_value_decode
643 * DESCRIPTION: Decodes value portion of string (Octet String, various
644 * character string types)
646 * asn1: pointer to ASN1 socket.
647 * enc_len: length of encoding of value.
648 * octets: pointer to variable we set to point to string.
649 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
652 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
658 eoc = asn1->offset + enc_len;
661 * Check for an overflow, and clamp "eoc" at the maximum if we
664 if (eoc < asn1->offset || eoc < 0)
668 * First, make sure the entire string is in the tvbuff, and throw
669 * an exception if it isn't. If the length is bogus, this should
670 * keep us from trying to allocate an immensely large buffer.
671 * (It won't help if the length is *valid* but immensely large,
672 * but that's another matter.)
674 * We do that by attempting to fetch the last byte (if the length
678 tvb_get_guint8(asn1->tvb, eoc - 1);
679 *octets = g_malloc (enc_len);
682 * If the length is 0, we allocate a 1-byte buffer, as
683 * "g_malloc()" returns NULL if passed 0 as an argument,
684 * and our caller expects us to return a pointer to a
687 *octets = g_malloc (1);
690 while (asn1->offset < eoc) {
691 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
692 if (ret != ASN1_ERR_NOERROR) {
698 return ASN1_ERR_NOERROR;
702 * NAME: asn1_string_decode [API]
703 * SYNOPSIS: int asn1_string_decode
711 * DESCRIPTION: Decodes string (Octet String, various character string
714 * asn1: pointer to ASN1 socket.
715 * octets: pointer to variable we set to point to string.
716 * str_len: length of octet_string.
717 * nbytes: number of bytes used to encode.
718 * expected_tag: tag expected for this type of string.
719 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
722 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
723 guint *nbytes, guint expected_tag)
733 start = asn1->offset;
734 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
735 if (ret != ASN1_ERR_NOERROR)
737 if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
738 /* XXX - handle the constructed encoding? */
739 ret = ASN1_ERR_WRONG_TYPE;
743 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
747 ret = asn1_string_value_decode (asn1, enc_len, octets);
751 *nbytes = asn1->offset - start;
756 * NAME: asn1_octet_string_decode [API]
757 * SYNOPSIS: int asn1_octet_string_decode
764 * DESCRIPTION: Decodes Octet String.
766 * asn1: pointer to ASN1 socket.
767 * octets: pointer to variable we set to point to string.
768 * str_len: length of octet_string.
769 * nbytes: number of bytes used to encode.
770 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
773 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
776 return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
780 * NAME: asn1_subid_decode
781 * SYNOPSIS: int asn1_subid_decode
786 * DESCRIPTION: Decodes Sub Identifier.
788 * asn1: pointer to ASN1 socket.
789 * subid: Sub Identifier.
790 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
793 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
800 ret = asn1_octet_decode(asn1, &ch);
801 if (ret != ASN1_ERR_NOERROR)
805 } while ((ch & 0x80) == 0x80);
806 return ASN1_ERR_NOERROR;
810 * NAME: asn1_oid_value_decode [API]
811 * SYNOPSIS: int asn1_oid_value_decode
818 * DESCRIPTION: Decodes value portion of Object Identifier.
820 * asn1: pointer to ASN1 socket.
821 * enc_len: length of encoding of value.
822 * oid: pointer to variable we set to Object Identifier.
823 * len: Length of Object Identifier in gulongs.
824 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
827 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
835 eoc = asn1->offset + enc_len;
838 * Check for an overflow, and clamp "eoc" at the maximum if we
841 if (eoc < asn1->offset || eoc < 0)
845 * First, make sure the entire string is in the tvbuff, and throw
846 * an exception if it isn't. If the length is bogus, this should
847 * keep us from trying to allocate an immensely large buffer.
848 * (It won't help if the length is *valid* but immensely large,
849 * but that's another matter.)
851 * We do that by attempting to fetch the last byte (if the length
855 tvb_get_guint8(asn1->tvb, eoc - 1);
858 *oid = g_malloc(size * sizeof(gulong));
861 ret = asn1_subid_decode (asn1, &subid);
862 if (ret != ASN1_ERR_NOERROR) {
870 } else if (subid < 80) {
872 optr[1] = subid - 40;
875 optr[1] = subid - 80;
879 while (asn1->offset < eoc) {
880 if (++(*len) > size) {
883 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
885 ret = asn1_subid_decode (asn1, optr++);
886 if (ret != ASN1_ERR_NOERROR) {
892 return ASN1_ERR_NOERROR;
896 * NAME: asn1_oid_decode [API]
897 * SYNOPSIS: int asn1_oid_decode
904 * DESCRIPTION: Decodes Object Identifier.
906 * asn1: pointer to ASN1 socket.
907 * oid: pointer to variable we set to Object Identifier.
908 * len: Length of Object Identifier in gulongs.
909 * nbytes: number of bytes used to encode.
910 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
913 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
923 start = asn1->offset;
924 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
925 if (ret != ASN1_ERR_NOERROR)
927 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
928 ret = ASN1_ERR_WRONG_TYPE;
932 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
936 ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
939 *nbytes = asn1->offset - start;
944 * NAME: asn1_sequence_decode [API]
945 * SYNOPSIS: int asn1_sequence_decode
951 * DESCRIPTION: Decodes header for SEQUENCE.
953 * asn1: pointer to ASN1 socket.
954 * seq_len: length of sequence.
955 * nbytes: number of bytes used to encode header.
956 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
959 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
968 start = asn1->offset;
969 ret = asn1_header_decode(asn1, &cls, &con, &tag,
971 if (ret != ASN1_ERR_NOERROR)
973 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
974 ret = ASN1_ERR_WRONG_TYPE;
978 /* XXX - might some sequences have an indefinite length? */
979 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
982 ret = ASN1_ERR_NOERROR;
985 *nbytes = asn1->offset - start;
990 * NAME: asn1_err_to_str [API]
991 * SYNOPSIS: char *asn1_err_to_str
995 * DESCRIPTION: Returns the string corresponding to an ASN.1 library error.
997 * err: the error code
998 * RETURNS: string for the error
1001 asn1_err_to_str(int err)
1004 char errstrbuf[14+1+1+11+1+1]; /* "Unknown error (%d)\0" */
1008 case ASN1_ERR_EOC_MISMATCH:
1009 errstr = "EOC mismatch";
1012 case ASN1_ERR_WRONG_TYPE:
1013 errstr = "Wrong type for that item";
1016 case ASN1_ERR_LENGTH_NOT_DEFINITE:
1017 errstr = "Length was indefinite";
1020 case ASN1_ERR_LENGTH_MISMATCH:
1021 errstr = "Length mismatch";
1024 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
1025 errstr = "Wrong length for that item's type";
1029 snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);