diff options
author | Tomas Kukosa <tomas.kukosa@siemens.com> | 2007-01-10 07:09:30 +0000 |
---|---|---|
committer | Tomas Kukosa <tomas.kukosa@siemens.com> | 2007-01-10 07:09:30 +0000 |
commit | a68f0224c32995115f35a5dccf1ff2d3da9b2162 (patch) | |
tree | efa2e3a1da83140e20d771b71e3efd064fecb97e /epan/asn1.c | |
parent | b3df1786244ced3cfed38fbf9b55f6c7e055cce2 (diff) |
move asn1.c/.h files into plugins/asn1 directory as just this plugin uses it now
svn path=/trunk/; revision=20372
Diffstat (limited to 'epan/asn1.c')
-rw-r--r-- | epan/asn1.c | 1085 |
1 files changed, 0 insertions, 1085 deletions
diff --git a/epan/asn1.c b/epan/asn1.c deleted file mode 100644 index 26c59c6ae6..0000000000 --- a/epan/asn1.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* asn1.c - * Routines for ASN.1 BER dissection - * - * $Id$ - * - * Wireshark - Network traffic analyzer - * By Gerald Combs <gerald@wireshark.org> - * - * Based on "g_asn1.c" from: - * - * GXSNMP -- An snmp mangament application - * Copyright (C) 1998 Gregory McLean & Jochen Friedrich - * Beholder RMON ethernet network monitor, Copyright (C) 1993 DNPAP group - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * MODULE INFORMATION - * ------------------ - * FILE NAME: g_asn1.c - * SYSTEM NAME: ASN1 Basic Encoding - * ORIGINAL AUTHOR(S): Dirk Wisse - * VERSION NUMBER: 1 - * CREATION DATE: 1990/11/22 - * - * DESCRIPTION: ASN1 Basic Encoding Rules. - * - * To decode this we must do: - * - * asn1_open (asn1, tvb, offset); - * asn1_header_decode (asn1, &end_of_seq, cls, con, tag, def, len); - * asn1_header_decode (asn1, &end_of_octs, cls, con, tag, def, len); - * asn1_octets_decode (asn1, end_of_octs, str, len); - * asn1_header_decode (asn1, &end_of_int, cls, con, tag); - * asn1_int_decode (asn1, end_of_int, &integer); - * asn1_eoc_decode (asn1, end_of_seq); - * asn1_close (asn1, &offset); - * - * For indefinite encoding end_of_seq and &end_of_seq in the - * example above should be replaced by NULL. - * For indefinite decoding nothing has to be changed. - * This can be very useful if you want to decode both - * definite and indefinite encodings. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> - -#include <limits.h> - -#include <glib.h> - -#include <epan/tvbuff.h> -#include <epan/asn1.h> -#include <epan/emem.h> - -/* - * NAME: asn1_open [API] - * SYNOPSIS: void asn1_open - * ( - * ASN1_SCK *asn1, - * tvbuff_t *tvb, - * int offset - * ) - * DESCRIPTION: Opens an ASN1 socket. - * Parameters: - * asn1: pointer to ASN1 socket. - * tvb: Tvbuff for encoding. - * offset: Current offset in tvbuff. - * Encoding starts at the end of the buffer, and - * proceeds to the beginning. - * RETURNS: void - */ - -void -asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset) -{ - asn1->tvb = tvb; - asn1->offset = offset; -} - -/* - * NAME: asn1_close [API] - * SYNOPSIS: void asn1_close - * ( - * ASN1_SCK *asn1, - * int *offset - * ) - * DESCRIPTION: Closes an ASN1 socket. - * Parameters: - * asn1: pointer to ASN1 socket. - * offset: pointer to variable into which current offset is - * to be put. - * RETURNS: void - */ - -void -asn1_close(ASN1_SCK *asn1, int *offset) -{ - *offset = asn1->offset; -} - -/* - * NAME: asn1_octet_decode - * SYNOPSIS: int asn1_octet_decode - * ( - * ASN1_SCK *asn1, - * guchar *ch - * ) - * DESCRIPTION: Decodes an octet. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_octet_decode(ASN1_SCK *asn1, guchar *ch) -{ - *ch = tvb_get_guint8(asn1->tvb, asn1->offset); - asn1->offset++; - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_tag_get - * SYNOPSIS: int asn1_tag_get - * ( - * ASN1_SCK *asn1, - * guint *tag - * ) - * DESCRIPTION: Decodes a tag number, combining it with existing tag bits. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -static int -asn1_tag_get(ASN1_SCK *asn1, guint *tag) -{ - int ret; - guchar ch; - - do { - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *tag <<= 7; - *tag |= ch & 0x7F; - } while ((ch & 0x80) == 0x80); - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_tag_decode - * SYNOPSIS: int asn1_tag_decode - * ( - * ASN1_SCK *asn1, - * guint *tag - * ) - * DESCRIPTION: Decodes a tag number. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_tag_decode(ASN1_SCK *asn1, guint *tag) -{ - *tag = 0; - return asn1_tag_get(asn1, tag); -} - -/* - * NAME: asn1_id_decode - * SYNOPSIS: int asn1_id_decode - * ( - * ASN1_SCK *asn1, - * guint *cls, - * guint *con, - * guint *tag - * ) - * DESCRIPTION: Decodes an identifier. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag) -{ - int ret; - guchar ch; - - *tag = 0; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *cls = (ch & 0xC0) >> 6; - *con = (ch & 0x20) >> 5; - *tag = (ch & 0x1F); - if (*tag == 0x1F) { - ret = asn1_tag_decode (asn1, tag); - if (ret != ASN1_ERR_NOERROR) - return ret; - } - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_id_decode1 - * SYNOPSIS: int asn1_id_decode1 - * ( - * ASN1_SCK *asn1, - * guint *tag - * ) - * DESCRIPTION: Decodes an identifier. - * Like asn1_id_decode() except that the Class and Constructor - * bits are returned in the tag. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_id_decode1(ASN1_SCK *asn1, guint *tag) -{ - int ret; - guchar ch; - - *tag = 0; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - - *tag = ch; - if ((*tag & 0x1F) == 0x1F) { /* high-tag-number format */ - *tag = ch >> 5; /* leave just the Class and Constructor bits */ - ret = asn1_tag_get (asn1, tag); - if (ret != ASN1_ERR_NOERROR) - return ret; - } - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_length_decode - * SYNOPSIS: int asn1_length_decode - * ( - * ASN1_SCK *asn1, - * gboolean *def, - * guint *len - * ) - * DESCRIPTION: Decodes an ASN1 length. - * Parameters: - * asn1: pointer to ASN1 socket. - * def: Boolean - TRUE if length definite, FALSE if not - * len: length, if length is definite - * DESCRIPTION: Decodes a definite or indefinite length. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len) -{ - int ret; - guchar ch, cnt; - - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - if (ch == 0x80) - *def = FALSE; /* indefinite length */ - else { - *def = TRUE; /* definite length */ - if (ch < 0x80) - *len = ch; - else { - cnt = (guchar) (ch & 0x7F); - *len = 0; - while (cnt > 0) { - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *len <<= 8; - *len |= ch; - cnt--; - } - } - } - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_header_decode [API] - * SYNOPSIS: int asn1_header_decode - * ( - * ASN1_SCK *asn1, - * guint *cls, - * guint *con, - * guint *tag - * gboolean *defp, - * guint *lenp - * ) - * DESCRIPTION: Decodes an ASN1 header. - * Parameters: - * asn1: pointer to ASN1 socket. - * cls: Class (see asn1.h) - * con: Primitive, Constructed (ASN1_PRI, ASN1_CON) - * tag: Tag (see asn1.h) - * defp: Boolean - TRUE if length definite, FALSE if not - * lenp: length, if length is definite - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag, - gboolean *defp, guint *lenp) -{ - int ret; - guint def, len = 0; - - ret = asn1_id_decode (asn1, cls, con, tag); - if (ret != ASN1_ERR_NOERROR) - return ret; - ret = asn1_length_decode (asn1, &def, &len); - if (ret != ASN1_ERR_NOERROR) - return ret; - *defp = def; - *lenp = len; - return ASN1_ERR_NOERROR; -} - - -/* - * NAME: asn1_eoc [API] - * SYNOPSIS: gboolean asn1_eoc - * ( - * ASN1_SCK *asn1, - * int eoc - * ) - * DESCRIPTION: Checks if decoding is at End Of Contents. - * Parameters: - * asn1: pointer to ASN1 socket. - * eoc: offset of end of encoding, or -1 if indefinite. - * RETURNS: gboolean success - */ -gboolean -asn1_eoc ( ASN1_SCK *asn1, int eoc) -{ - if (eoc == -1) - return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00 - && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00); - else - return (asn1->offset >= eoc); -} - -/* - * NAME: asn1_eoc_decode [API] - * SYNOPSIS: int asn1_eoc_decode - * ( - * ASN1_SCK *asn1, - * int eoc - * ) - * DESCRIPTION: Decodes End Of Contents. - * Parameters: - * asn1: pointer to ASN1 socket. - * eoc: offset of end of encoding, or -1 if indefinite. - * If eoc is -1 it decodes an ASN1 End Of - * Contents (0x00 0x00), so it has to be an - * indefinite length encoding. If eoc is a non-negative - * integer, it probably was filled by asn1_header_decode, - * and should refer to the octet after the last of the encoding. - * It is checked if this offset refers to the octet to be - * decoded. This only takes place in decoding a - * definite length encoding. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_eoc_decode (ASN1_SCK *asn1, int eoc) -{ - int ret; - guchar ch; - - if (eoc == -1) { - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - if (ch != 0x00) - return ASN1_ERR_EOC_MISMATCH; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - if (ch != 0x00) - return ASN1_ERR_EOC_MISMATCH; - return ASN1_ERR_NOERROR; - } else { - if (asn1->offset != eoc) - return ASN1_ERR_LENGTH_MISMATCH; - return ASN1_ERR_NOERROR; - } -} - -/* - * NAME: asn1_null_decode [API] - * SYNOPSIS: int asn1_null_decode - * ( - * ASN1_SCK *asn1, - * int enc_len - * ) - * DESCRIPTION: Decodes Null. - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of encoding of value. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_null_decode ( ASN1_SCK *asn1, int enc_len) -{ - int start_off = asn1->offset; - - asn1->offset += enc_len; - /* - * Check for integer overflows. - * XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate - * error from the ones available. Should we make a new one? - */ - if (asn1->offset < 0 || asn1->offset < start_off) - return ASN1_ERR_LENGTH_MISMATCH; - - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_bool_decode [API] - * SYNOPSIS: int asn1_bool_decode - * ( - * ASN1_SCK *asn1, - * int enc_len, - * gboolean *boolean - * ) - * DESCRIPTION: Decodes Boolean. - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of encoding of value. - * bool: False, True (0, !0). - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *boolean) -{ - int ret; - guchar ch; - - if (enc_len != 1) - return ASN1_ERR_LENGTH_MISMATCH; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *boolean = ch ? TRUE : FALSE; - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_int32_value_decode [API] - * SYNOPSIS: int asn1_int32_value_decode - * ( - * ASN1_SCK *asn1, - * int enc_len, - * gint32 *integer - * ) - * DESCRIPTION: Decodes value portion of Integer (which must be no more - * than 32 bits). - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of encoding of value. - * integer: Integer. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer) -{ - int ret; - int eoc; - guchar ch; - guint len; - - eoc = asn1->offset + enc_len; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *integer = (gint) ch; - len = 1; - while (asn1->offset < eoc) { - if (++len > sizeof (gint32)) - return ASN1_ERR_WRONG_LENGTH_FOR_TYPE; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *integer <<= 8; - *integer |= ch; - } - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_int32_decode [API] - * SYNOPSIS: int asn1_int32_decode - * ( - * ASN1_SCK *asn1, - * gint32 *integer, - * guint *nbytes, - * ) - * DESCRIPTION: Decodes Integer (which must be no more than 32 bits). - * Parameters: - * asn1: pointer to ASN1 socket. - * integer: Integer. - * nbytes: number of bytes used to encode it. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes) -{ - int ret; - int start; - guint cls; - guint con; - guint tag; - gboolean def; - guint enc_len; - - start = asn1->offset; - ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len); - if (ret != ASN1_ERR_NOERROR) - goto done; - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) { - ret = ASN1_ERR_WRONG_TYPE; - goto done; - } - if (!def) { - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - goto done; - } - ret = asn1_int32_value_decode (asn1, enc_len, integer); - -done: - *nbytes = asn1->offset - start; - return ret; -} - -/* - * NAME: asn1_uint32_value_decode [API] - * SYNOPSIS: int asn1_uint32_value_decode - * ( - * ASN1_SCK *asn1, - * int enc_len, - * guint32 *integer - * ) - * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no - * more than 32 bits). - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of encoding of value. - * integer: Integer. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint32 *integer) -{ - int ret; - int eoc; - guchar ch; - guint len; - - eoc = asn1->offset + enc_len; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *integer = ch; - if (ch == 0) - len = 0; - else - len = 1; - while (asn1->offset < eoc) { - if (++len > sizeof (guint32)) - return ASN1_ERR_WRONG_LENGTH_FOR_TYPE; - ret = asn1_octet_decode (asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *integer <<= 8; - *integer |= ch; - } - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_uint32_decode [API] - * SYNOPSIS: int asn1_uint32_decode - * ( - * ASN1_SCK *asn1, - * guint32 *integer, - * guint *nbytes, - * ) - * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits). - * Parameters: - * asn1: pointer to ASN1 socket. - * integer: Integer. - * nbytes: number of bytes used to encode it. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes) -{ - int ret; - int start; - guint cls; - guint con; - guint tag; - gboolean def; - guint enc_len; - - start = asn1->offset; - ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len); - if (ret != ASN1_ERR_NOERROR) - goto done; - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) { - ret = ASN1_ERR_WRONG_TYPE; - goto done; - } - if (!def) { - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - goto done; - } - ret = asn1_uint32_value_decode (asn1, enc_len, integer); - -done: - *nbytes = asn1->offset - start; - return ret; -} - -/* - * NAME: asn1_bits_decode [API] - * SYNOPSIS: int asn1_bits_decode - * ( - * ASN1_SCK *asn1, - * int eoc, - * guchar *bits, - * guint size, - * guint len, - * guchar unused - * ) - * DESCRIPTION: Decodes Bit String. - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of value. - * bits: pointer to variable we set to point to strring - * len: Size of Bit String in characters. - * unused: Number of unused bits in last character. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_bits_decode ( ASN1_SCK *asn1, int enc_len, guchar **bits, - guint *len, guchar *unused) -{ - int ret; - int eoc; - guchar *ptr; - - eoc = asn1->offset + enc_len; - *bits = NULL; - ret = asn1_octet_decode (asn1, unused); - if (ret != ASN1_ERR_NOERROR) - return ret; - *len = 0; - - /* - * First, make sure the entire string is in the tvbuff, and throw - * an exception if it isn't. If the length is bogus, this should - * keep us from trying to allocate an immensely large buffer. - * (It won't help if the length is *valid* but immensely large, - * but that's another matter; in any case, that would happen only - * if we had an immensely large tvbuff....) - */ - if (enc_len != 0) { - tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len); - *bits = g_malloc (enc_len); - } else { - /* - * If the length is 0, we allocate a 1-byte buffer, as - * "g_malloc()" returns NULL if passed 0 as an argument, - * and our caller expects us to return a pointer to a - * buffer. - */ - *bits = g_malloc (1); - } - - ptr = *bits; - while (asn1->offset < eoc) { - ret = asn1_octet_decode (asn1, (guchar *)ptr++); - if (ret != ASN1_ERR_NOERROR) { - g_free(*bits); - *bits = NULL; - return ret; - } - } - *len = ptr - *bits; - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_string_value_decode [API] - * SYNOPSIS: int asn1_string_value_decode - * ( - * ASN1_SCK *asn1, - * int enc_len, - * guchar **octets - * ) - * DESCRIPTION: Decodes value portion of string (Octet String, various - * character string types) - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of encoding of value. - * octets: pointer to variable we set to point to string, - * which is '\0' terminated for ease of use as C-string - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets) -{ - int ret; - int eoc; - guchar *ptr; - - /* - * First, make sure the entire string is in the tvbuff, and throw - * an exception if it isn't. If the length is bogus, this should - * keep us from trying to allocate an immensely large buffer. - * (It won't help if the length is *valid* but immensely large, - * but that's another matter; in any case, that would happen only - * if we had an immensely large tvbuff....) - */ - if (enc_len != 0) - tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len); - *octets = g_malloc (enc_len+1); - - eoc = asn1->offset + enc_len; - ptr = *octets; - while (asn1->offset < eoc) { - ret = asn1_octet_decode (asn1, (guchar *)ptr++); - if (ret != ASN1_ERR_NOERROR) { - g_free(*octets); - *octets = NULL; - return ret; - } - } - *(guchar *)ptr = '\0'; - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_string_decode [API] - * SYNOPSIS: int asn1_string_decode - * ( - * ASN1_SCK *asn1, - * guchar **octets, - * guint *str_len, - * guint *nbytes, - * guint expected_tag - * ) - * DESCRIPTION: Decodes string (Octet String, various character string - * types) - * Parameters: - * asn1: pointer to ASN1 socket. - * octets: pointer to variable we set to point to string. - * str_len: length of octet_string. - * nbytes: number of bytes used to encode. - * expected_tag: tag expected for this type of string. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len, - guint *nbytes, guint expected_tag) -{ - int ret; - int start; - int enc_len; - guint cls; - guint con; - guint tag; - gboolean def; - - start = asn1->offset; - ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len); - if (ret != ASN1_ERR_NOERROR) - goto done; - if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) { - /* XXX - handle the constructed encoding? */ - ret = ASN1_ERR_WRONG_TYPE; - goto done; - } - if (!def) { - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - goto done; - } - - ret = asn1_string_value_decode (asn1, enc_len, octets); - *str_len = enc_len; - -done: - *nbytes = asn1->offset - start; - return ret; -} - -/* - * NAME: asn1_octet_string_decode [API] - * SYNOPSIS: int asn1_octet_string_decode - * ( - * ASN1_SCK *asn1, - * guchar **octets, - * guint *str_len, - * guint *nbytes, - * ) - * DESCRIPTION: Decodes Octet String. - * Parameters: - * asn1: pointer to ASN1 socket. - * octets: pointer to variable we set to point to string. - * str_len: length of octet_string. - * nbytes: number of bytes used to encode. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len, - guint *nbytes) -{ - return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS); -} - -/* - * NAME: asn1_subid_decode - * SYNOPSIS: int asn1_subid_decode - * ( - * ASN1_SCK *asn1, - * subid_t *subid - * ) - * DESCRIPTION: Decodes Sub Identifier. - * Parameters: - * asn1: pointer to ASN1 socket. - * subid: Sub Identifier. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid) -{ - int ret; - guchar ch; - - *subid = 0; - do { - ret = asn1_octet_decode(asn1, &ch); - if (ret != ASN1_ERR_NOERROR) - return ret; - *subid <<= 7; - *subid |= ch & 0x7F; - } while ((ch & 0x80) == 0x80); - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_oid_value_decode [API] - * SYNOPSIS: int asn1_oid_value_decode - * ( - * ASN1_SCK *asn1, - * int enc_len, - * subid_t **oid, - * guint *len - * ) - * DESCRIPTION: Decodes value portion of Object Identifier. - * Parameters: - * asn1: pointer to ASN1 socket. - * enc_len: length of encoding of value. - * oid: pointer to variable we set to Object Identifier. - * len: Length of Object Identifier in gulongs. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len) -{ - int ret; - int eoc; - subid_t subid; - guint size; - subid_t *optr; - - /* - * First, make sure the entire string is in the tvbuff, and throw - * an exception if it isn't. If the length is bogus, this should - * keep us from trying to allocate an immensely large buffer. - * (It won't help if the length is *valid* but immensely large, - * but that's another matter; in any case, that would happen only - * if we had an immensely large tvbuff....) - */ - if (enc_len < 1) { - *oid = NULL; - return ASN1_ERR_LENGTH_MISMATCH; - } - tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len); - - eoc = asn1->offset + enc_len; - - size = enc_len + 1; - *oid = g_malloc(size * sizeof(gulong)); - optr = *oid; - - ret = asn1_subid_decode (asn1, &subid); - if (ret != ASN1_ERR_NOERROR) { - g_free(*oid); - *oid = NULL; - return ret; - } - if (subid < 40) { - optr[0] = 0; - optr[1] = subid; - } else if (subid < 80) { - optr[0] = 1; - optr[1] = subid - 40; - } else { - optr[0] = 2; - optr[1] = subid - 80; - } - *len = 2; - optr += 2; - while (asn1->offset < eoc) { - if (++(*len) > size) { - g_free(*oid); - *oid = NULL; - return ASN1_ERR_WRONG_LENGTH_FOR_TYPE; - } - ret = asn1_subid_decode (asn1, optr++); - if (ret != ASN1_ERR_NOERROR) { - g_free(*oid); - *oid = NULL; - return ret; - } - } - return ASN1_ERR_NOERROR; -} - -/* - * NAME: asn1_oid_decode [API] - * SYNOPSIS: int asn1_oid_decode - * ( - * ASN1_SCK *asn1, - * subid_t **oid, - * guint *len, - * guint *nbytes - * ) - * DESCRIPTION: Decodes Object Identifier. - * Parameters: - * asn1: pointer to ASN1 socket. - * oid: pointer to variable we set to Object Identifier. - * len: Length of Object Identifier in gulongs. - * nbytes: number of bytes used to encode. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes) -{ - int ret; - int start; - guint cls; - guint con; - guint tag; - gboolean def; - guint enc_len; - - start = asn1->offset; - ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len); - if (ret != ASN1_ERR_NOERROR) - goto done; - if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) { - ret = ASN1_ERR_WRONG_TYPE; - goto done; - } - if (!def) { - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - goto done; - } - - ret = asn1_oid_value_decode (asn1, enc_len, oid, len); - -done: - *nbytes = asn1->offset - start; - return ret; -} - -/* - * NAME: asn1_sequence_decode [API] - * SYNOPSIS: int asn1_sequence_decode - * ( - * ASN1_SCK *asn1, - * guint *seq_len, - * guint *nbytes - * ) - * DESCRIPTION: Decodes header for SEQUENCE. - * Parameters: - * asn1: pointer to ASN1 socket. - * seq_len: length of sequence. - * nbytes: number of bytes used to encode header. - * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success) - */ -int -asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes) -{ - int ret; - int start; - guint cls; - guint con; - guint tag; - gboolean def; - - start = asn1->offset; - ret = asn1_header_decode(asn1, &cls, &con, &tag, - &def, seq_len); - if (ret != ASN1_ERR_NOERROR) - goto done; - if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) { - ret = ASN1_ERR_WRONG_TYPE; - goto done; - } - if (!def) { - /* XXX - might some sequences have an indefinite length? */ - ret = ASN1_ERR_LENGTH_NOT_DEFINITE; - goto done; - } - ret = ASN1_ERR_NOERROR; - -done: - *nbytes = asn1->offset - start; - return ret; -} - -/* - * NAME: asn1_err_to_str [API] - * SYNOPSIS: const char *asn1_err_to_str - * ( - * int err - * ) - * DESCRIPTION: Returns the string corresponding to an ASN.1 library error. - * Parameters: - * err: the error code - * RETURNS: string for the error - */ -const char * -asn1_err_to_str(int err) -{ - const char *errstr; - char errstrbuf[14+1+1+11+1+1]; /* "Unknown error (%d)\0" */ - - switch (err) { - - case ASN1_ERR_EOC_MISMATCH: - errstr = "EOC mismatch"; - break; - - case ASN1_ERR_WRONG_TYPE: - errstr = "Wrong type for that item"; - break; - - case ASN1_ERR_LENGTH_NOT_DEFINITE: - errstr = "Length was indefinite"; - break; - - case ASN1_ERR_LENGTH_MISMATCH: - errstr = "Length mismatch"; - break; - - case ASN1_ERR_WRONG_LENGTH_FOR_TYPE: - errstr = "Wrong length for that item's type"; - break; - - default: - g_snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err); - errstr = ep_strdup(errstrbuf); - break; - } - return errstr; -} |