aboutsummaryrefslogtreecommitdiffstats
path: root/asn1.c
diff options
context:
space:
mode:
authorLars Roland <Lars.Roland@gmx.net>2005-02-09 23:38:00 +0000
committerLars Roland <Lars.Roland@gmx.net>2005-02-09 23:38:00 +0000
commitec9ca01616d179043c0e84d5e5799cfec8ad63ba (patch)
tree6b8d6526fe00a336c75b9118009deb4c690984ad /asn1.c
parent125bb2d27803ba28210643ff404072ab0af31f33 (diff)
Move the following files from /trunk to /trunk/epan:
asn1.[ch] follow.[ch] ptvcursor.[ch] reassemble.[ch] xmlstub.[ch] fix #include statements accordingly. svn path=/trunk/; revision=13366
Diffstat (limited to 'asn1.c')
-rw-r--r--asn1.c1085
1 files changed, 0 insertions, 1085 deletions
diff --git a/asn1.c b/asn1.c
deleted file mode 100644
index 8edd59bcb8..0000000000
--- a/asn1.c
+++ /dev/null
@@ -1,1085 +0,0 @@
-/* asn1.c
- * Routines for ASN.1 BER dissection
- *
- * $Id$
- *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
- *
- * 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>
-
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
-#include <epan/tvbuff.h>
-#include "asn1.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;
-
- 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 != 0)
- 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: 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
- */
-char *
-asn1_err_to_str(int err)
-{
- 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:
- snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);
- errstr = errstrbuf;
- break;
- }
- return errstr;
-}