21124729 Move libtasn1 from Desktop to Userland consolidation
authorAnn Lai <ann.lai@oracle.com>
Thu, 30 Jul 2015 17:45:10 -0700
changeset 4723 4193dfeb0e39
parent 4722 2bd832ea7ef7
child 4724 7b96ca49258f
21124729 Move libtasn1 from Desktop to Userland consolidation 21124720 Move libgpg-error from Desktop to Userland consolidation 21124683 Move libgcrypt from Desktop to Userland consolidation
components/libgcrypt/Makefile
components/libgcrypt/libgcrypt.p5m
components/libgcrypt/test/results-all.master
components/libgpg-error/Makefile
components/libgpg-error/libgpg-error.p5m
components/libgpg-error/patches/libgpg-error-01-gettext.patch
components/libgpg-error/test/results-all.master
components/libtasn1/Makefile
components/libtasn1/libtasn1.p5m
components/libtasn1/patches/libtasn1-01-buffer-overflow.patch
components/libtasn1/patches/libtasn1-02-cve-2012-1569.patch
components/libtasn1/patches/libtasn1-03-cve-2014-3468.patch
components/libtasn1/patches/libtasn1-04-cve-2014-3469.patch
components/libtasn1/patches/libtasn1-05-cve-2015-2806.patch
components/libtasn1/patches/libtasn1-06-cve-2014-3467.patch
components/libtasn1/patches/libtasn1-07-cve-2015-3622.patch
components/libtasn1/patches/libtasn1-08-test-parser.patch
components/libtasn1/test/results-all.master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgcrypt/Makefile	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,75 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../../make-rules/shared-macros.mk
+
+COMPONENT_NAME=		libgcrypt
+COMPONENT_VERSION=	1.5.3
+COMPONENT_SRC=		$(COMPONENT_NAME)-$(COMPONENT_VERSION)
+COMPONENT_PROJECT_URL=  ftp://ftp.gnupg.org/gcrypt/libgcrypt/ 
+COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.bz2
+COMPONENT_ARCHIVE_HASH= \
+    sha256:bcf5334e7da352c45de6aec5d2084ce9a1d30029ff4a4a5da13f1848874759d1
+COMPONENT_ARCHIVE_URL=  ftp://ftp.gnupg.org/gcrypt/$(COMPONENT_NAME)/$(COMPONENT_ARCHIVE)
+COMPONENT_BUGDB=	library/libgcrypt
+
+TPNO=			7588
+
+COMPONENT_BUILD_TARGETS = all info
+
+include $(WS_MAKE_RULES)/prep.mk
+include $(WS_MAKE_RULES)/configure.mk
+include $(WS_MAKE_RULES)/ips.mk
+
+CONFIGURE_OPTIONS += --sysconfdir=/etc
+CONFIGURE_OPTIONS += --infodir=$(CONFIGURE_INFODIR)
+CONFIGURE_OPTIONS += --enable-maintainer-mode 
+CONFIGURE_OPTIONS += --disable-asm 
+CONFIGURE_OPTIONS += --enable-ciphers=arcfour:blowfish:des:aes:twofish:serpent:rfc2268:seed:camellia:cast5
+CONFIGURE_OPTIONS.64 += CC="$(CC) -m64"
+
+ASLR_MODE = $(ASLR_ENABLE)
+
+include ../../make-rules/shared-targets.mk
+
+configure:      $(CONFIGURE_32_and_64)
+
+build:          $(BUILD_32_and_64)
+
+install:        $(INSTALL_32_and_64)
+
+COMPONENT_TEST_MASTER = $(COMPONENT_TEST_RESULTS_DIR)/results-all.master
+
+COMPONENT_TEST_TRANSFORMS += \
+        '-n -e "/PASS/p" ' \
+        '-e "/FAIL/p" ' \
+        '-e "/All/p" '
+
+test:           $(TEST_32_and_64)
+
+system-test:    $(SYSTEM_TESTS_NOT_IMPLEMENTED)
+
+REQUIRED_PACKAGES += library/security/libgpg-error
+REQUIRED_PACKAGES += system/library
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgcrypt/libgcrypt.p5m	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+set name=pkg.fmri \
+    value=pkg:/system/library/security/libgcrypt@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary value="libgcrypt - cryptographic library"
+set name=pkg.description \
+    value="Libgcrypt is a general purpose crypto library based on the code used in GnuPG."
+set name=com.oracle.info.description value="the libgcrypt cryptographic library"
+set name=com.oracle.info.tpno value=$(TPNO)
+set name=info.classification \
+    value=org.opensolaris.category.2008:System/Libraries
+set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
+set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
+set name=org.opensolaris.arc-caseid value=PSARC/2013/422
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+file path=usr/bin/$(MACH64)/libgcrypt-config
+file usr/bin/$(MACH64)/dumpsexp path=usr/bin/dumpsexp
+file usr/bin/$(MACH64)/hmac256 path=usr/bin/hmac256
+file path=usr/bin/libgcrypt-config
+file path=usr/include/gcrypt-module.h
+file path=usr/include/gcrypt.h
+link path=usr/lib/$(MACH64)/libgcrypt.so target=libgcrypt.so.11.8.2
+link path=usr/lib/$(MACH64)/libgcrypt.so.11 target=libgcrypt.so.11.8.2
+file path=usr/lib/$(MACH64)/libgcrypt.so.11.8.2
+link path=usr/lib/libgcrypt.so target=libgcrypt.so.11.8.2
+link path=usr/lib/libgcrypt.so.11 target=libgcrypt.so.11.8.2
+file path=usr/lib/libgcrypt.so.11.8.2
+file path=usr/share/aclocal/libgcrypt.m4
+license COPYING license=GPLv2
+license COPYING.LIB license=LGPLv2.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgcrypt/test/results-all.master	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,22 @@
+PASS: version
+PASS: t-mpi-bit
+PASS: prime
+PASS: register
+PASS: ac
+PASS: ac-schemes
+PASS: ac-data
+PASS: basic
+PASS: mpitests
+PASS: tsexp
+PASS: keygen
+PASS: pubkey
+PASS: hmac
+PASS: keygrip
+PASS: fips186-dsa
+PASS: aeswrap
+PASS: curves
+PASS: t-kdf
+PASS: pkcs1v2
+PASS: random
+PASS: benchmark
+All 21 tests passed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgpg-error/Makefile	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../../make-rules/shared-macros.mk
+
+COMPONENT_NAME=		libgpg-error
+COMPONENT_VERSION=	1.12
+COMPONENT_SRC=		$(COMPONENT_NAME)-$(COMPONENT_VERSION)
+COMPONENT_PROJECT_URL=  ftp://ftp.gnupg.org/gcrypt/$(COMPONENT_NAME)
+COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.bz2
+COMPONENT_ARCHIVE_HASH= \
+    sha256:cafc9ed6a87c53a35175d5a1220a96ca386696eef2fa059cc0306211f246e55f
+COMPONENT_ARCHIVE_URL=  ftp://ftp.gnupg.org/gcrypt/$(COMPONENT_NAME)/$(COMPONENT_ARCHIVE)
+COMPONENT_BUGDB=	library/libgpg-error
+
+TPNO=			7588
+
+COMPONENT_BUILD_TARGETS = all info
+
+include $(WS_MAKE_RULES)/prep.mk
+include $(WS_MAKE_RULES)/configure.mk
+include $(WS_MAKE_RULES)/ips.mk
+
+CONFIGURE_OPTIONS += --sysconfdir=/etc
+CONFIGURE_OPTIONS += --infodir=$(CONFIGURE_INFODIR)
+CONFIGURE_OPTIONS.64 += CC="$(CC) -m64"
+
+COMPONENT_TEST_MASTER = $(COMPONENT_TEST_RESULTS_DIR)/results-all.master
+
+ASLR_MODE = $(ASLR_ENABLE)
+
+include ../../make-rules/shared-targets.mk
+
+configure:      $(CONFIGURE_32_and_64)
+
+build:          $(BUILD_32_and_64)
+
+install:        $(INSTALL_32_and_64)
+
+test:           $(TEST_32_and_64)
+
+system-test:    $(SYSTEM_TESTS_NOT_IMPLEMENTED)
+
+REQUIRED_PACKAGES += system/library
+REQUIRED_PACKAGES += consolidation/desktop/desktop-incorporation
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgpg-error/libgpg-error.p5m	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,69 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+set name=pkg.fmri \
+    value=pkg:/library/security/libgpg-error@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary value="Common error codes for GnuPG, libgcrypt"
+set name=pkg.description \
+    value="This is a library that defines common error values for all GnuPG components.  Among these are GPG, GPGSM, GPGME, GPG-Agent, libgcrypt, pinentry, SmartCard Daemon and possibly more in the future."
+set name=com.oracle.info.description value="the GnuPG error library"
+set name=com.oracle.info.tpno value=$(TPNO)
+set name=info.classification \
+    value=org.opensolaris.category.2008:System/Libraries
+set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
+set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
+set name=org.opensolaris.arc-caseid value=PSARC/2009/397
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+file path=usr/bin/$(MACH64)/gpg-error-config
+file usr/bin/$(MACH64)/gpg-error path=usr/bin/gpg-error
+file path=usr/bin/gpg-error-config
+file path=usr/include/gpg-error.h
+link path=usr/lib/$(MACH64)/libgpg-error.so target=libgpg-error.so.0.10.0
+link path=usr/lib/$(MACH64)/libgpg-error.so.0 target=libgpg-error.so.0.10.0
+file path=usr/lib/$(MACH64)/libgpg-error.so.0.10.0
+link path=usr/lib/libgpg-error.so target=libgpg-error.so.0.10.0
+link path=usr/lib/libgpg-error.so.0 target=libgpg-error.so.0.10.0
+file path=usr/lib/libgpg-error.so.0.10.0
+file path=usr/share/aclocal/gpg-error.m4
+file path=usr/share/common-lisp/source/gpg-error/gpg-error-codes.lisp
+file path=usr/share/common-lisp/source/gpg-error/gpg-error-package.lisp
+file path=usr/share/common-lisp/source/gpg-error/gpg-error.asd
+file path=usr/share/common-lisp/source/gpg-error/gpg-error.lisp
+file path=usr/share/locale/cs/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/da/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/de/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/eo/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/fr/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/it/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/ja/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/nl/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/pl/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/ro/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/sv/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/uk/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/vi/LC_MESSAGES/libgpg-error.mo
+file path=usr/share/locale/zh_CN/LC_MESSAGES/libgpg-error.mo
+license COPYING license=GPLv2
+license COPYING.LIB license=LGPLv2.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgpg-error/patches/libgpg-error-01-gettext.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,34 @@
+Source:
+Internal
+
+Info:
+https://www.gnu.org/software/gettext/manual/html_node/AM_005fGNU_005fGETTEXT_005fVERSION.html
+The AM_GNU_GETTEXT_VERSION macro declares the version number of the GNU 
+gettext infrastructure that is used by the package.
+The use of this macro is optional; only the autopoint program makes use of 
+it.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- libgpg-error-1.12/configure.ac.orig	2010-10-26 17:13:48.000000000 +0800
++++ libgpg-error-1.12/configure.ac	2010-11-11 17:15:10.972945315 +0800
+@@ -110,11 +110,13 @@
+ #define GPG_ERR_ENABLE_ERRNO_MACROS 1
+ ])
+ 
+-
+-# Note, that autogen.sh greps for the next line.
+-AM_GNU_GETTEXT_VERSION([0.17])
+-AM_GNU_GETTEXT([external])
+-
++LTLIBINTL=
++AC_SUBST(LTLIBINTL)
++GETTEXT_PACKAGE=libgpg-error
++AC_SUBST(GETTEXT_PACKAGE)
++ALL_LINGUAS="cs de es fr hu it ja ko pl pt_BR ro ru sv vi zh_CN zh_HK zh_TW    "
++AM_GLIB_GNU_GETTEXT
++ 
+ # Checks for header files.
+ AC_HEADER_STDC
+ AC_CHECK_HEADERS([stdlib.h locale.h])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libgpg-error/test/results-all.master	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,49 @@
+make[1]: Entering directory `$(@D)'
+Making check in m4
+make[2]: Entering directory `$(@D)/m4'
+make[2]: Nothing to be done for `check'.
+make[2]: Leaving directory `$(@D)/m4'
+Making check in src
+make[2]: Entering directory `$(@D)/src'
+/usr/gnu/bin/make  check-am
+make[3]: Entering directory `$(@D)/src'
+make[3]: Nothing to be done for `check-am'.
+make[3]: Leaving directory `$(@D)/src'
+make[2]: Leaving directory `$(@D)/src'
+Making check in tests
+make[2]: Entering directory `$(@D)/tests'
+/usr/gnu/bin/make  check-TESTS
+make[3]: Entering directory `$(@D)/tests'
+PASS: t-version
+Unspecified source: Success
+gcrypt: Invalid length specifier in S-expression
+GnuPG: Unknown packet
+GpgSM: Certificate too young
+GPG Agent: Bad CA certificate
+Pinentry: Operation cancelled
+SCD: Card removed
+GPGME: Bad secret key
+Keybox: Unknown error code
+PASS: t-strerror
+PASS: t-syserror
+==================
+All 3 tests passed
+==================
+make[3]: Leaving directory `$(@D)/tests'
+make[2]: Leaving directory `$(@D)/tests'
+Making check in po
+make[2]: Entering directory `$(@D)/po'
+make[2]: Leaving directory `$(@D)/po'
+Making check in lang
+make[2]: Entering directory `$(@D)/lang'
+Making check in cl
+make[3]: Entering directory `$(@D)/lang/cl'
+make[3]: Nothing to be done for `check'.
+make[3]: Leaving directory `$(@D)/lang/cl'
+make[3]: Entering directory `$(@D)/lang'
+make[3]: Nothing to be done for `check-am'.
+make[3]: Leaving directory `$(@D)/lang'
+make[2]: Leaving directory `$(@D)/lang'
+make[2]: Entering directory `$(@D)'
+make[2]: Leaving directory `$(@D)'
+make[1]: Leaving directory `$(@D)'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/Makefile	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,74 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+include ../../make-rules/shared-macros.mk
+
+COMPONENT_NAME=		libtasn1
+COMPONENT_VERSION=	2.8
+COMPONENT_SRC=		$(COMPONENT_NAME)-$(COMPONENT_VERSION)
+COMPONENT_PROJECT_URL=  http://ftp.gnu.org/gnu/libtasn1/
+COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.gz
+COMPONENT_ARCHIVE_HASH= \
+    sha256:2b7d74f4b10b18ae2f0291fcafabe30e42c9ededdea41add8c622302132d545a
+COMPONENT_ARCHIVE_URL=  http://ftp.gnu.org/gnu/$(COMPONENT_NAME)/$(COMPONENT_ARCHIVE)
+COMPONENT_BUGDB=	library/libtasn1
+
+TPNO=			9381
+
+COMPONENT_BUILD_TARGETS = all info
+
+include $(WS_MAKE_RULES)/prep.mk
+include $(WS_MAKE_RULES)/configure.mk
+include $(WS_MAKE_RULES)/ips.mk
+
+CONFIGURE_OPTIONS += --sysconfdir=/etc
+CONFIGURE_OPTIONS += --includedir=$(CONFIGURE_INCLUDEDIR)
+CONFIGURE_OPTIONS += --infodir=$(CONFIGURE_INFODIR)
+CONFIGURE_OPTIONS += --disable-static
+CONFIGURE_OPTIONS += --enable-shared
+CONFIGURE_OPTIONS.64 += CC="$(CC) -m64"
+
+ASLR_MODE = $(ASLR_ENABLE)
+
+include ../../make-rules/shared-targets.mk
+
+configure:      $(CONFIGURE_32_and_64)
+
+build:          $(BUILD_32_and_64)
+
+install:        $(INSTALL_32_and_64)
+
+COMPONENT_TEST_MASTER = $(COMPONENT_TEST_RESULTS_DIR)/results-all.master
+
+COMPONENT_TEST_TRANSFORMS += \
+        '-n -e "/PASS/p" ' \
+        '-e "/FAIL/p" ' \
+        '-e "/All/p" '
+
+test:           $(TEST_32_and_64)
+
+system-test:    $(SYSTEM_TESTS_NOT_IMPLEMENTED)
+
+REQUIRED_PACKAGES += system/library
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/libtasn1.p5m	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,89 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+<transform file path=usr.*/man/.+ -> default mangler.man.stability uncommitted>
+set name=pkg.fmri \
+    value=pkg:/library/libtasn1@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary value="Tiny ASN.1 library"
+set name=pkg.description \
+    value="Libtasn is a library C for manipulating ASN.1 objects."
+set name=com.oracle.info.description value="the ASN.1 library"
+set name=com.oracle.info.tpno value=$(TPNO)
+set name=info.classification \
+    value=org.opensolaris.category.2008:System/Libraries
+set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
+set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
+set name=org.opensolaris.arc-caseid value=PSARC/2008/390
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+file usr/bin/$(MACH64)/asn1Coding path=usr/bin/asn1Coding
+file usr/bin/$(MACH64)/asn1Decoding path=usr/bin/asn1Decoding
+file usr/bin/$(MACH64)/asn1Parser path=usr/bin/asn1Parser
+file path=usr/include/libtasn1.h
+link path=usr/lib/$(MACH64)/libtasn1.so target=libtasn1.so.3.1.10
+link path=usr/lib/$(MACH64)/libtasn1.so.3 target=libtasn1.so.3.1.10
+file path=usr/lib/$(MACH64)/libtasn1.so.3.1.10
+file path=usr/lib/$(MACH64)/pkgconfig/libtasn1.pc
+link path=usr/lib/libtasn1.so target=libtasn1.so.3.1.10
+link path=usr/lib/libtasn1.so.3 target=libtasn1.so.3.1.10
+file path=usr/lib/libtasn1.so.3.1.10
+file path=usr/lib/pkgconfig/libtasn1.pc
+file path=usr/share/man/man1/asn1Coding.1
+file path=usr/share/man/man1/asn1Decoding.1
+file path=usr/share/man/man1/asn1Parser.1
+file path=usr/share/man/man3/asn1_array2tree.3
+file path=usr/share/man/man3/asn1_bit_der.3
+file path=usr/share/man/man3/asn1_check_version.3
+file path=usr/share/man/man3/asn1_copy_node.3
+file path=usr/share/man/man3/asn1_create_element.3
+file path=usr/share/man/man3/asn1_delete_element.3
+file path=usr/share/man/man3/asn1_delete_structure.3
+file path=usr/share/man/man3/asn1_der_coding.3
+file path=usr/share/man/man3/asn1_der_decoding.3
+file path=usr/share/man/man3/asn1_der_decoding_element.3
+file path=usr/share/man/man3/asn1_der_decoding_startEnd.3
+file path=usr/share/man/man3/asn1_expand_any_defined_by.3
+file path=usr/share/man/man3/asn1_expand_octet_string.3
+file path=usr/share/man/man3/asn1_find_node.3
+file path=usr/share/man/man3/asn1_find_structure_from_oid.3
+file path=usr/share/man/man3/asn1_get_bit_der.3
+file path=usr/share/man/man3/asn1_get_length_ber.3
+file path=usr/share/man/man3/asn1_get_length_der.3
+file path=usr/share/man/man3/asn1_get_octet_der.3
+file path=usr/share/man/man3/asn1_get_tag_der.3
+file path=usr/share/man/man3/asn1_length_der.3
+file path=usr/share/man/man3/asn1_number_of_elements.3
+file path=usr/share/man/man3/asn1_octet_der.3
+file path=usr/share/man/man3/asn1_parser2array.3
+file path=usr/share/man/man3/asn1_parser2tree.3
+file path=usr/share/man/man3/asn1_perror.3
+file path=usr/share/man/man3/asn1_print_structure.3
+file path=usr/share/man/man3/asn1_read_tag.3
+file path=usr/share/man/man3/asn1_read_value.3
+file path=usr/share/man/man3/asn1_strerror.3
+file path=usr/share/man/man3/asn1_write_value.3
+file path=usr/share/man/man3/libtasn1_perror.3
+file path=usr/share/man/man3/libtasn1_strerror.3
+license COPYING license=GPLv3
+license COPYING.LIB license=LGPLv2.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-01-buffer-overflow.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,39 @@
+Source:
+Internal
+
+Info:
+To take out buffer overflow issue.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- a/lib/coding.c
++++ b/lib/coding.c
+@@ -253,18 +253,23 @@ static asn1_retCode
+ _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
+ {
+   int len_len, counter, k, first, max_len;
+-  char *temp, *n_end, *n_start;
++  char *temp = NULL, *n_end, *n_start;
+   unsigned char bit7;
+   unsigned long val, val1 = 0;
++  size_t temp_size = str ? strlen (str) : 0;
++
++  temp_size += 2;
++  if (temp_size < 2)
++    return ASN1_MEM_ALLOC_ERROR;
+ 
+   max_len = *der_len;
+ 
+-  temp = (char *) _asn1_malloc (strlen (str) + 2);
++  temp = (char *) _asn1_malloc (temp_size);
+   if (temp == NULL)
+     return ASN1_MEM_ALLOC_ERROR;
+ 
+-  strcpy (temp, str);
+-  strcat (temp, ".");
++  strncpy (temp, str ? (const char *)str : "", temp_size);
++  strncat (temp, ".", 1);
+ 
+   counter = 0;
+   n_start = temp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-02-cve-2012-1569.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,57 @@
+Source:
+Internal
+
+Info:
+http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-1569
+The asn1_get_length_der function in decoding.c in GNU Libtasn1 before 2.12, as 
+used in GnuTLS before 3.0.16 and other products, does not properly handle 
+certain large length values, which allows remote attackers to cause a denial 
+of service (heap memory corruption and application crash) or possibly have 
+unspecified other impact via a crafted ASN.1 structure. 
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- libtasn1-2.8/lib/decoding.c.orig	2012-04-06 12:19:39.986443804 +0800
++++ libtasn1-2.8/lib/decoding.c	2012-04-06 12:38:38.607157322 +0800
+@@ -55,12 +55,14 @@
+  * Extract a length field from DER data.
+  *
+  * Returns: Return the decoded length value, or -1 on indefinite
+- *   length, or -2 when the value was too big.
++ *   length, or -2 when the value was too big to fit in a int, or -4
++ *   when the decoed length value plus @len would exceed @der_len.
++
+  **/
+ signed long
+ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
+ {
+-  unsigned long ans;
++  int ans;
+   int k, punt;
+ 
+   *len = 0;
+@@ -83,7 +85,7 @@
+ 	  ans = 0;
+ 	  while (punt <= k && punt < der_len)
+ 	    {
+-	      unsigned long last = ans;
++              int last = ans;
+ 
+ 	      ans = ans * 256 + der[punt++];
+ 	      if (ans < last)
+@@ -93,10 +95,13 @@
+ 	}
+       else
+ 	{			/* indefinite length method */
+-	  ans = -1;
++           *len = punt;
++           return -1;
+ 	}
+ 
+       *len = punt;
++      if (ans + *len < ans || ans + *len > der_len)
++       return -4;
+       return ans;
+     }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-03-cve-2014-3468.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,43 @@
+Source:
+Internal
+
+Info:
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3468
+The asn1_get_bit_der function in GNU Libtasn1 before 3.6 does not properly 
+report an error when a negative bit length is identified, which allows 
+context-dependent attackers to cause out-of-bounds access via crafted ASN.1 
+data. 
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- libtasn1-2.8/lib/decoding.c.orig	2014-06-05 10:36:51.728076396 +0530
++++ libtasn1-2.8/lib/decoding.c	2014-06-05 10:39:39.072295803 +0530
+@@ -214,7 +214,7 @@ asn1_get_octet_der (const unsigned char
+ 		    int *ret_len, unsigned char *str, int str_size,
+ 		    int *str_len)
+ {
+-  int len_len;
++  int len_len = 0;
+ 
+   if (der_len <= 0)
+     return ASN1_GENERIC_ERROR;
+@@ -335,7 +335,7 @@ asn1_get_bit_der (const unsigned char *d
+ 		  int *ret_len, unsigned char *str, int str_size,
+ 		  int *bit_len)
+ {
+-  int len_len, len_byte;
++  int len_len = 0, len_byte;
+ 
+   if (der_len <= 0)
+     return ASN1_GENERIC_ERROR;
+@@ -346,6 +346,9 @@ asn1_get_bit_der (const unsigned char *d
+   *ret_len = len_byte + len_len + 1;
+   *bit_len = len_byte * 8 - der[len_len];
+ 
++  if (*bit_len <= 0)
++    return ASN1_DER_ERROR;
++
+   if (str_size >= len_byte)
+     memcpy (str, der + len_len + 1, len_byte);
+   else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-04-cve-2014-3469.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,86 @@
+Source:
+Internal
+
+Info:
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3469
+The (1) asn1_read_value_type and (2) asn1_read_value functions in GNU Libtasn1 
+before 3.6 allows context-dependent attackers to cause a denial of service 
+(NULL pointer dereference and crash) via a NULL value in an ivalue argument.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- libtasn1-2.8/lib/element.c.orig	2014-06-05 10:41:52.955725412 +0530
++++ libtasn1-2.8/lib/element.c	2014-06-05 11:09:52.177695875 +0530
+@@ -113,8 +113,11 @@ _asn1_convert_integer (const char *value
+     /* VALUE_OUT is too short to contain the value conversion */
+     return ASN1_MEM_ERROR;
+ 
+-  for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
++  if (value_out != NULL)
++  {
++    for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+     value_out[k2 - k] = val[k2];
++  }
+ 
+ #if 0
+   printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
+@@ -622,7 +625,8 @@ asn1_write_value (ASN1_TYPE node_root, c
+ 	if (ptr_size < data_size) { \
+ 		return ASN1_MEM_ERROR; \
+ 	} else { \
+-		memcpy( ptr, data, data_size); \
++		if (ptr && data_size > 0) \
++			memcpy( ptr, data, data_size); \
+ 	}
+ 
+ #define PUT_STR_VALUE( ptr, ptr_size, data) \
+@@ -631,36 +635,39 @@ asn1_write_value (ASN1_TYPE node_root, c
+ 		return ASN1_MEM_ERROR; \
+ 	} else { \
+ 		/* this strcpy is checked */ \
+-		strcpy(ptr, data); \
++		if (ptr) { \
++			strcpy(ptr, data); \
++		} \
+ 	}
+ 
+ #define ADD_STR_VALUE( ptr, ptr_size, data) \
+-	*len = (int) strlen(data) + 1; \
+-	if (ptr_size < (int) strlen(ptr)+(*len)) { \
++	*len += strlen(data); \
++	if (ptr_size < (int) *len) { \
++		(*len)++; \
+ 		return ASN1_MEM_ERROR; \
+ 	} else { \
+ 		/* this strcat is checked */ \
+-		strcat(ptr, data); \
++		if (ptr) strcat (ptr, data); \
+ 	}
+-
+ /**
+  * asn1_read_value:
+  * @root: pointer to a structure.
+  * @name: the name of the element inside a structure that you want to read.
+  * @ivalue: vector that will contain the element's content, must be a
+- *   pointer to memory cells already allocated.
++ *   pointer to memory cells already allocated (may be %NULL).
+  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
+  *   holds the sizeof value.
+  *
+  * Returns the value of one element inside a structure.
+- *
+- * If an element is OPTIONAL and the function "read_value" returns
++ * If an element is OPTIONAL and this returns
+  * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
+  * in the der encoding that created the structure.  The first element
+  * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
+  * so on.
+  *
+- * INTEGER: VALUE will contain a two's complement form integer.
++ * Note that there can be valid values with length zero. In these case
++ * this function will succeed and @len will be zero.
++ *
+  *
+  *            integer=-1  -> value[0]=0xFF , len=1.
+  *            integer=1   -> value[0]=0x01 , len=1.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-05-cve-2015-2806.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,44 @@
+Source:
+Internal
+
+Info:
+https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-2806
+Stack-based buffer overflow in asn1_der_decoding in libtasn1 before 4.4 allows 
+remote attackers to have unspecified impact via unknown vectors.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- libtasn1-2.8/lib/parser_aux.c.orig	2015-04-15 12:36:59.603251259 +0530
++++ libtasn1-2.8/lib/parser_aux.c	2015-04-15 12:38:34.145677358 +0530
+@@ -580,7 +580,7 @@ _asn1_delete_list_and_nodes (void)
+ 
+ 
+ char *
+-_asn1_ltostr (long v, char *str)
++_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE])
+ {
+   long d, r;
+   char temp[20];
+@@ -604,7 +604,7 @@ _asn1_ltostr (long v, char *str)
+       count++;
+       v = d;
+     }
+-  while (v);
++  while (v && ((start+count) < LTOSTR_MAX_SIZE-1));
+ 
+   for (k = 0; k < count; k++)
+     str[k + start] = temp[start + count - k - 1];
+--- libtasn1-2.8/lib/parser_aux.h.orig	2015-04-15 12:38:41.020519734 +0530
++++ libtasn1-2.8/lib/parser_aux.h	2015-04-15 12:40:23.768693524 +0530
+@@ -63,7 +63,9 @@ void _asn1_delete_list (void);
+ 
+ void _asn1_delete_list_and_nodes (void);
+ 
+-char *_asn1_ltostr (long v, char *str);
++/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */
++#define LTOSTR_MAX_SIZE 22
++char *_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE]);
+ 
+ ASN1_TYPE _asn1_find_up (ASN1_TYPE node);
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-06-cve-2014-3467.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,11708 @@
+Source:
+Internal
+
+Info:
+https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-3467
+Multiple unspecified vulnerabilities in the DER decoder in GNU Libtasn1 before
+3.6, as used in GnutTLS, allow remote attackers to cause a denial of service
+(out-of-bounds read) via crafted ASN.1 data.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- ORIGINAL/./lib/parser_aux.c	2015-07-14 18:28:22.919544825 -0700
++++ libtasn1-2.8/./lib/parser_aux.c	2015-07-14 18:45:02.691801820 -0700
+@@ -21,6 +21,7 @@
+  */
+ 
+ #include <int.h>
++/*#include <hash-pjw-bare.h>*/
+ #include "parser_aux.h"
+ #include "gstr.h"
+ #include "structure.h"
+@@ -44,28 +45,28 @@
+ list_type *firstElement = NULL;
+ 
+ /******************************************************/
+-/* Function : _asn1_add_node                          */
++/* Function : _asn1_add_static_node                   */
+ /* Description: creates a new NODE_ASN element and    */
+ /* puts it in the list pointed by firstElement.       */
+ /* Parameters:                                        */
+-/*   type: type of the new element (see TYPE_         */
++/*   type: type of the new element (see TYPE_   */
+ /*         and CONST_ constants).                     */
+ /* Return: pointer to the new element.                */
+ /******************************************************/
+ ASN1_TYPE
+-_asn1_add_node (unsigned int type)
++_asn1_add_static_node (unsigned int type)
+ {
+   list_type *listElement;
+   ASN1_TYPE punt;
+ 
+-  punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
++  punt = calloc (1, sizeof (struct node_asn_struct));
+   if (punt == NULL)
+     return NULL;
+ 
+-  listElement = (list_type *) _asn1_malloc (sizeof (list_type));
++  listElement = malloc (sizeof (list_type));
+   if (listElement == NULL)
+     {
+-      _asn1_free (punt);
++      free (punt);
+       return NULL;
+     }
+ 
+@@ -78,6 +79,26 @@
+   return punt;
+ }
+ 
++#define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
++
++/* Return a hash of the N bytes of X using the method described by
++   Bruno Haible in http://www.haible.de/bruno/hashfunc.html.
++   Note that while many hash functions reduce their result via modulo
++   to a 0..table_size-1 range, this function does not do that.  */
++
++size_t
++hash_pjw_bare (const void *x, size_t n)
++{
++  const unsigned char *s = x;
++  size_t h = 0;
++  unsigned i;
++
++  for (i = 0; i < n; i++)
++    h = s[i] + ((h << 9) | (h >> (SIZE_BITS - 9)));
++
++  return h;
++}
++
+ /**
+  * asn1_find_node:
+  * @pointer: NODE_ASN element pointer.
+@@ -96,6 +117,8 @@
+   ASN1_TYPE p;
+   char *n_end, n[ASN1_MAX_NAME_SIZE + 1];
+   const char *n_start;
++  unsigned int nsize;
++  unsigned int nhash;
+ 
+   if (pointer == NULL)
+     return NULL;
+@@ -106,25 +129,30 @@
+   p = pointer;
+   n_start = name;
+ 
+-  if (p->name != NULL)
++  if (p->name[0] != 0)
+     {				/* has *pointer got a name ? */
+       n_end = strchr (n_start, '.');	/* search the first dot */
+       if (n_end)
+ 	{
+-	  memcpy (n, n_start, n_end - n_start);
+-	  n[n_end - n_start] = 0;
++	  nsize = n_end - n_start;
++	  memcpy (n, n_start, nsize);
++	  n[nsize] = 0;
+ 	  n_start = n_end;
+ 	  n_start++;
++
++	  nhash = hash_pjw_bare (n, nsize);
+ 	}
+       else
+ 	{
+-	  _asn1_str_cpy (n, sizeof (n), n_start);
++	  nsize = _asn1_str_cpy (n, sizeof (n), n_start);
++	  nhash = hash_pjw_bare (n, nsize);
++
+ 	  n_start = NULL;
+ 	}
+ 
+       while (p)
+ 	{
+-	  if ((p->name) && (!strcmp (p->name, n)))
++	  if (nhash == p->name_hash && (!strcmp (p->name, n)))
+ 	    break;
+ 	  else
+ 	    p = p->right;
+@@ -144,14 +172,18 @@
+       n_end = strchr (n_start, '.');	/* search the next dot */
+       if (n_end)
+ 	{
+-	  memcpy (n, n_start, n_end - n_start);
+-	  n[n_end - n_start] = 0;
++	  nsize = n_end - n_start;
++	  memcpy (n, n_start, nsize);
++	  n[nsize] = 0;
+ 	  n_start = n_end;
+ 	  n_start++;
++
++	  nhash = hash_pjw_bare (n, nsize);
+ 	}
+       else
+ 	{
+-	  _asn1_str_cpy (n, sizeof (n), n_start);
++	  nsize = _asn1_str_cpy (n, sizeof (n), n_start);
++	  nhash = hash_pjw_bare (n, nsize);
+ 	  n_start = NULL;
+ 	}
+ 
+@@ -173,7 +205,7 @@
+ 	{			/* no "?LAST" */
+ 	  while (p)
+ 	    {
+-	      if ((p->name) && (!strcmp (p->name, n)))
++	      if (p->name_hash == nhash && !strcmp (p->name, n))
+ 		break;
+ 	      else
+ 		p = p->right;
+@@ -205,7 +237,7 @@
+   if (node->value)
+     {
+       if (node->value != node->small_value)
+-	_asn1_free (node->value);
++	free (node->value);
+       node->value = NULL;
+       node->value_len = 0;
+     }
+@@ -219,7 +251,7 @@
+     }
+   else
+     {
+-      node->value = _asn1_malloc (len);
++      node->value = malloc (len);
+       if (node->value == NULL)
+ 	return NULL;
+     }
+@@ -230,10 +262,10 @@
+ }
+ 
+ /******************************************************************/
+-/* Function : _asn1_set_value_octet                               */
++/* Function : _asn1_set_value_lv                                  */
+ /* Description: sets the field VALUE in a NODE_ASN element. The   */
+ /*              previous value (if exist) will be lost. The value */
+-/*		given is stored as an octet string.               */
++/*		given is stored as an length-value format (LV     */
+ /* Parameters:                                                    */
+ /*   node: element pointer.                                       */
+ /*   value: pointer to the value that you want to set.            */
+@@ -241,7 +273,7 @@
+ /* Return: pointer to the NODE_ASN element.                       */
+ /******************************************************************/
+ ASN1_TYPE
+-_asn1_set_value_octet (ASN1_TYPE node, const void *value, unsigned int len)
++_asn1_set_value_lv (ASN1_TYPE node, const void *value, unsigned int len)
+ {
+   int len2;
+   void *temp;
+@@ -250,7 +282,7 @@
+     return node;
+ 
+   asn1_length_der (len, NULL, &len2);
+-  temp = (unsigned char *) _asn1_malloc (len + len2);
++  temp = malloc (len + len2);
+   if (temp == NULL)
+     return NULL;
+ 
+@@ -270,7 +302,7 @@
+   if (node->value)
+     {
+       if (node->value != node->small_value)
+-	_asn1_free (node->value);
++	free (node->value);
+       node->value = NULL;
+       node->value_len = 0;
+     }
+@@ -304,7 +336,7 @@
+       /* value is allocated */
+       int prev_len = node->value_len;
+       node->value_len += len;
+-      node->value = _asn1_realloc (node->value, node->value_len);
++      node->value = realloc (node->value, node->value_len);
+       if (node->value == NULL)
+ 	{
+ 	  node->value_len = 0;
+@@ -319,7 +351,7 @@
+       /* value is in node */
+       int prev_len = node->value_len;
+       node->value_len += len;
+-      node->value = _asn1_malloc (node->value_len);
++      node->value = malloc (node->value_len);
+       if (node->value == NULL)
+ 	{
+ 	  node->value_len = 0;
+@@ -347,27 +379,49 @@
+ ASN1_TYPE
+ _asn1_set_name (ASN1_TYPE node, const char *name)
+ {
++  unsigned int nsize;
++
+   if (node == NULL)
+     return node;
+ 
+-  if (node->name)
++  if (name == NULL)
+     {
+-      _asn1_free (node->name);
+-      node->name = NULL;
++      node->name[0] = 0;
++      node->name_hash = hash_pjw_bare (node->name, 0);
++      return node;
+     }
+ 
+-  if (name == NULL)
+-    return node;
++  nsize = _asn1_str_cpy (node->name, sizeof (node->name), name);
++  node->name_hash = hash_pjw_bare (node->name, nsize);
++
++  return node;
++}
+ 
+-  if (strlen (name))
++/******************************************************************/
++/* Function : _asn1_cpy_name                                      */
++/* Description: copies the field NAME in a NODE_ASN element.      */
++/* Parameters:                                                    */
++/*   dst: a dest element pointer.                                 */
++/*   src: a source element pointer.                               */
++/* Return: pointer to the NODE_ASN element.                       */
++/******************************************************************/
++ASN1_TYPE
++_asn1_cpy_name (ASN1_TYPE dst, ASN1_TYPE src)
++{
++  if (dst == NULL)
++    return dst;
++
++  if (src == NULL)
+     {
+-      node->name = (char *) _asn1_strdup (name);
+-      if (node->name == NULL)
+-	return NULL;
++      dst->name[0] = 0;
++      dst->name_hash = hash_pjw_bare (dst->name, 0);
++      return dst;
+     }
+-  else
+-    node->name = NULL;
+-  return node;
++
++  _asn1_str_cpy (dst->name, sizeof (dst->name), src->name);
++  dst->name_hash = src->name_hash;
++
++  return dst;
+ }
+ 
+ /******************************************************************/
+@@ -390,21 +444,6 @@
+   return node;
+ }
+ 
+-/******************************************************************/
+-/* Function : _asn1_get_right                                     */
+-/* Description: returns the element pointed by the RIGHT field of */
+-/*              a NODE_ASN element.                               */
+-/* Parameters:                                                    */
+-/*   node: NODE_ASN element pointer.                              */
+-/* Return: field RIGHT of NODE.                                   */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_get_right (ASN1_TYPE node)
+-{
+-  if (node == NULL)
+-    return NULL;
+-  return node->right;
+-}
+ 
+ /******************************************************************/
+ /* Function : _asn1_get_last_right                                */
+@@ -427,95 +466,30 @@
+ }
+ 
+ /******************************************************************/
+-/* Function : _asn1_set_down                                      */
+-/* Description: sets the field DOWN in a NODE_ASN element.        */
+-/* Parameters:                                                    */
+-/*   node: element pointer.                                       */
+-/*   down: pointer to a NODE_ASN element that you want be pointed */
+-/*          by NODE.                                              */
+-/* Return: pointer to *NODE.                                      */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_set_down (ASN1_TYPE node, ASN1_TYPE down)
+-{
+-  if (node == NULL)
+-    return node;
+-  node->down = down;
+-  if (down)
+-    down->left = node;
+-  return node;
+-}
+-
+-/******************************************************************/
+-/* Function : _asn1_get_down                                      */
+-/* Description: returns the element pointed by the DOWN field of  */
+-/*              a NODE_ASN element.                               */
+-/* Parameters:                                                    */
+-/*   node: NODE_ASN element pointer.                              */
+-/* Return: field DOWN of NODE.                                    */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_get_down (ASN1_TYPE node)
+-{
+-  if (node == NULL)
+-    return NULL;
+-  return node->down;
+-}
+-
+-/******************************************************************/
+-/* Function : _asn1_get_name                                      */
+-/* Description: returns the name of a NODE_ASN element.           */
+-/* Parameters:                                                    */
+-/*   node: NODE_ASN element pointer.                              */
+-/* Return: a null terminated string.                              */
+-/******************************************************************/
+-char *
+-_asn1_get_name (ASN1_TYPE node)
+-{
+-  if (node == NULL)
+-    return NULL;
+-  return node->name;
+-}
+-
+-/******************************************************************/
+-/* Function : _asn1_mod_type                                      */
+-/* Description: change the field TYPE of an NODE_ASN element.     */
+-/*              The new value is the old one | (bitwise or) the   */
+-/*              paramener VALUE.                                  */
+-/* Parameters:                                                    */
+-/*   node: NODE_ASN element pointer.                              */
+-/*   value: the integer value that must be or-ed with the current */
+-/*          value of field TYPE.                                  */
+-/* Return: NODE pointer.                                          */
+-/******************************************************************/
+-ASN1_TYPE
+-_asn1_mod_type (ASN1_TYPE node, unsigned int value)
+-{
+-  if (node == NULL)
+-    return node;
+-  node->type |= value;
+-  return node;
+-}
+-
+-
+-/******************************************************************/
+ /* Function : _asn1_remove_node                                   */
+ /* Description: gets free the memory allocated for an NODE_ASN    */
+ /*              element (not the elements pointed by it).         */
+ /* Parameters:                                                    */
+ /*   node: NODE_ASN element pointer.                              */
++/*   flags: ASN1_DELETE_FLAG_*                                    */
+ /******************************************************************/
+ void
+-_asn1_remove_node (ASN1_TYPE node)
++_asn1_remove_node (ASN1_TYPE node, unsigned int flags)
+ {
+   if (node == NULL)
+     return;
+ 
+-  if (node->name != NULL)
+-    _asn1_free (node->name);
+-  if (node->value != NULL && node->value != node->small_value)
+-    _asn1_free (node->value);
+-  _asn1_free (node);
++  if (node->value != NULL)
++    {
++      if (flags & ASN1_DELETE_FLAG_ZEROIZE)
++        {
++          safe_memset(node->value, 0, node->value_len);
++        }
++
++      if (node->value != node->small_value)
++        free (node->value);
++    }
++  free (node);
+ }
+ 
+ /******************************************************************/
+@@ -555,7 +529,7 @@
+     {
+       listElement = firstElement;
+       firstElement = firstElement->next;
+-      _asn1_free (listElement);
++      free (listElement);
+     }
+ }
+ 
+@@ -573,17 +547,17 @@
+     {
+       listElement = firstElement;
+       firstElement = firstElement->next;
+-      _asn1_remove_node (listElement->node);
+-      _asn1_free (listElement);
++      _asn1_remove_node (listElement->node, 0);
++      free (listElement);
+     }
+ }
+ 
+ 
+ char *
+-_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE])
++_asn1_ltostr (long v, char *str)
+ {
+   long d, r;
+-  char temp[20];
++  char temp[LTOSTR_MAX_SIZE];
+   int count, k, start;
+ 
+   if (v < 0)
+@@ -604,7 +578,7 @@
+       count++;
+       v = d;
+     }
+-  while (v && ((start+count) < LTOSTR_MAX_SIZE-1));
++  while (v);
+ 
+   for (k = 0; k < count; k++)
+     str[k + start] = temp[start + count - k - 1];
+@@ -623,7 +597,7 @@
+ /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
+ /*   otherwise ASN1_SUCCESS                                             */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_change_integer_value (ASN1_TYPE node)
+ {
+   ASN1_TYPE p;
+@@ -637,7 +611,8 @@
+   p = node;
+   while (p)
+     {
+-      if ((type_field (p->type) == TYPE_INTEGER) && (p->type & CONST_ASSIGN))
++      if ((type_field (p->type) == TYPE_INTEGER)
++	  && (p->type & CONST_ASSIGN))
+ 	{
+ 	  if (p->value)
+ 	    {
+@@ -690,7 +665,7 @@
+ /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
+ /*   otherwise ASN1_SUCCESS                                             */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_expand_object_id (ASN1_TYPE node)
+ {
+   ASN1_TYPE p, p2, p3, p4, p5;
+@@ -719,22 +694,25 @@
+ 		    {
+ 		      _asn1_str_cpy (name2, sizeof (name2), name_root);
+ 		      _asn1_str_cat (name2, sizeof (name2), ".");
+-		      _asn1_str_cat (name2, sizeof (name2), p2->value);
++		      _asn1_str_cat (name2, sizeof (name2),
++				     (char *) p2->value);
+ 		      p3 = asn1_find_node (node, name2);
+-		      if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+-			  !(p3->type & CONST_ASSIGN))
++		      if (!p3
++			  || (type_field (p3->type) != TYPE_OBJECT_ID)
++			  || !(p3->type & CONST_ASSIGN))
+ 			return ASN1_ELEMENT_NOT_FOUND;
+ 		      _asn1_set_down (p, p2->right);
+-		      _asn1_remove_node (p2);
++		      _asn1_remove_node (p2, 0);
+ 		      p2 = p;
+ 		      p4 = p3->down;
+ 		      while (p4)
+ 			{
+ 			  if (type_field (p4->type) == TYPE_CONSTANT)
+ 			    {
+-			      p5 = _asn1_add_node_only (TYPE_CONSTANT);
++			      p5 =
++				_asn1_add_single_node (TYPE_CONSTANT);
+ 			      _asn1_set_name (p5, p4->name);
+-			      tlen = strlen (p4->value);
++			      tlen = _asn1_strlen (p4->value);
+ 			      if (tlen > 0)
+ 				_asn1_set_value (p5, p4->value, tlen + 1);
+ 			      if (p2 == p)
+@@ -805,10 +783,10 @@
+ 		{
+ 		  _asn1_str_cpy (name2, sizeof (name2), name_root);
+ 		  _asn1_str_cat (name2, sizeof (name2), ".");
+-		  _asn1_str_cat (name2, sizeof (name2), p2->value);
++		  _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
+ 		  p3 = asn1_find_node (node, name2);
+-		  if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+-		      !(p3->type & CONST_ASSIGN))
++		  if (!p3 || (type_field (p3->type) != TYPE_OBJECT_ID)
++		      || !(p3->type & CONST_ASSIGN))
+ 		    return ASN1_ELEMENT_NOT_FOUND;
+ 		  p4 = p3->down;
+ 		  name2[0] = 0;
+@@ -818,7 +796,8 @@
+ 			{
+ 			  if (name2[0])
+ 			    _asn1_str_cat (name2, sizeof (name2), ".");
+-			  _asn1_str_cat (name2, sizeof (name2), p4->value);
++			  _asn1_str_cat (name2, sizeof (name2),
++					 (char *) p4->value);
+ 			}
+ 		      p4 = p4->right;
+ 		    }
+@@ -871,7 +850,7 @@
+ /*   ASN1_ELEMENT_NOT_FOUND if NODE is NULL,                       */
+ /*   otherwise ASN1_SUCCESS                                             */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_type_set_config (ASN1_TYPE node)
+ {
+   ASN1_TYPE p, p2;
+@@ -944,7 +923,7 @@
+ /*   ASN1_IDENTIFIER_NOT_FOUND   if an identifier is not defined, */
+ /*   otherwise ASN1_SUCCESS                                       */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_check_identifier (ASN1_TYPE node)
+ {
+   ASN1_TYPE p, p2;
+@@ -956,15 +935,18 @@
+   p = node;
+   while (p)
+     {
+-      if (type_field (p->type) == TYPE_IDENTIFIER)
++      if (p->value && type_field (p->type) == TYPE_IDENTIFIER)
+ 	{
+ 	  _asn1_str_cpy (name2, sizeof (name2), node->name);
+ 	  _asn1_str_cat (name2, sizeof (name2), ".");
+-	  _asn1_str_cat (name2, sizeof (name2), p->value);
++	  _asn1_str_cat (name2, sizeof (name2), (char *) p->value);
+ 	  p2 = asn1_find_node (node, name2);
+ 	  if (p2 == NULL)
+ 	    {
+-	      strcpy (_asn1_identifierMissing, p->value);
++	      if (p->value)
++		_asn1_strcpy (_asn1_identifierMissing, p->value);
++	      else
++		_asn1_strcpy (_asn1_identifierMissing, "(null)");
+ 	      return ASN1_IDENTIFIER_NOT_FOUND;
+ 	    }
+ 	}
+@@ -976,8 +958,8 @@
+ 	    {
+ 	      _asn1_str_cpy (name2, sizeof (name2), node->name);
+ 	      _asn1_str_cat (name2, sizeof (name2), ".");
+-	      _asn1_str_cat (name2, sizeof (name2), p2->value);
+-	      strcpy (_asn1_identifierMissing, p2->value);
++	      _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
++	      _asn1_strcpy (_asn1_identifierMissing, p2->value);
+ 	      p2 = asn1_find_node (node, name2);
+ 	      if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
+ 		  !(p2->type & CONST_ASSIGN))
+@@ -996,11 +978,11 @@
+ 		{
+ 		  _asn1_str_cpy (name2, sizeof (name2), node->name);
+ 		  _asn1_str_cat (name2, sizeof (name2), ".");
+-		  _asn1_str_cat (name2, sizeof (name2), p2->value);
+-		  strcpy (_asn1_identifierMissing, p2->value);
++		  _asn1_str_cat (name2, sizeof (name2), (char *) p2->value);
++		  _asn1_strcpy (_asn1_identifierMissing, p2->value);
+ 		  p2 = asn1_find_node (node, name2);
+-		  if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID) ||
+-		      !(p2->type & CONST_ASSIGN))
++		  if (!p2 || (type_field (p2->type) != TYPE_OBJECT_ID)
++		      || !(p2->type & CONST_ASSIGN))
+ 		    return ASN1_IDENTIFIER_NOT_FOUND;
+ 		  else
+ 		    _asn1_identifierMissing[0] = 0;
+@@ -1048,7 +1030,7 @@
+ /*     a DEFINITIONS element,                                     */
+ /*   otherwise ASN1_SUCCESS                                       */
+ /******************************************************************/
+-asn1_retCode
++int
+ _asn1_set_default_tag (ASN1_TYPE node)
+ {
+   ASN1_TYPE p;
+--- ORIGINAL/./lib/libtasn1.h	2015-07-14 18:28:22.936872981 -0700
++++ libtasn1-2.8/./lib/libtasn1.h	2015-07-14 18:45:02.744075374 -0700
+@@ -47,6 +47,17 @@
+ 
+ #define ASN1_VERSION "2.8"
+ 
++#if defined(__GNUC__) && !defined(ASN1_INTERNAL_BUILD)
++# define _ASN1_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
++# if _ASN1_GCC_VERSION >= 30100
++#  define _ASN1_GCC_ATTR_DEPRECATED __attribute__ ((__deprecated__))
++# endif
++#endif
++
++#ifndef _ASN1_GCC_ATTR_DEPRECATED
++#define _ASN1_GCC_ATTR_DEPRECATED
++#endif
++
+   typedef int asn1_retCode;	/* type returned by libtasn1 functions */
+ 
+   /*****************************************/
+@@ -103,53 +114,73 @@
+ #define ASN1_TAG_ENUMERATED		0x0A
+ #define ASN1_TAG_NULL			0x05
+ #define ASN1_TAG_GENERALSTRING		0x1B
++#define ASN1_TAG_NUMERIC_STRING         0x12
++#define ASN1_TAG_IA5_STRING             0x16
++#define ASN1_TAG_TELETEX_STRING         0x14
++#define ASN1_TAG_PRINTABLE_STRING       0x13
++#define ASN1_TAG_UNIVERSAL_STRING       0x1C
++#define ASN1_TAG_BMP_STRING             0x1E
++#define ASN1_TAG_UTF8_STRING            0x0C
++#define ASN1_TAG_VISIBLE_STRING         0x1A
+ 
+   /******************************************************/
+   /* Structure definition used for the node of the tree */
+   /* that represent an ASN.1 DEFINITION.                */
+   /******************************************************/
+ 
++  /* maximum number of characters of a name */
++  /* inside a file with ASN1 definitons     */
++#define ASN1_MAX_NAME_SIZE 64
++
++  typedef struct node_asn_struct node_asn;
++
++  typedef node_asn *ASN1_TYPE;
++
+ #if !defined ASN1_BUILDING
+   /* This structure is also in internal.h, but then contains more
+      fields.  You cannot make any modifications to these fields
+      without breaking ABI.  */
+   struct node_asn_struct
+   {
+-    char *name;			/* Node name */
++    char name[ASN1_MAX_NAME_SIZE + 1];    /* Node name */
++    unsigned int name_hash;
+     unsigned int type;		/* Node type */
+     unsigned char *value;	/* Node value */
+     int value_len;
+-    struct node_asn_struct *down;	/* Pointer to the son node */
+-    struct node_asn_struct *right;	/* Pointer to the brother node */
+-    struct node_asn_struct *left;	/* Pointer to the next list element */
++    ASN1_TYPE down;	/* Pointer to the son node */
++    ASN1_TYPE right;	/* Pointer to the brother node */
++    ASN1_TYPE left;	/* Pointer to the next list element */
+   };
+ #endif
+ 
+-  typedef struct node_asn_struct node_asn;
+-
+-  typedef node_asn *ASN1_TYPE;
+-
+ #define ASN1_TYPE_EMPTY  NULL
+ 
++#define ASN1_DELETE_FLAG_ZEROIZE 1
++
+   /*****************************************/
+   /* For the on-disk format of ASN.1 trees */
+   /*****************************************/
+   struct static_struct_asn
+   {
+-    const char *name;		/* Node name */
+-    unsigned int type;		/* Node type */
+-    const void *value;		/* Node value */
++    const char *name;           /* Node name */
++    unsigned int type;          /* Node type */
++    const void *value;          /* Node value */
+   };
+   typedef struct static_struct_asn ASN1_ARRAY_TYPE;
+ 
++  struct asn1_data_node_st
++  {
++    const char *name;           /* Node name */
++    const void *value;          /* Node value */
++    unsigned int value_len;     /* Node value size */
++    unsigned int type;          /* Node value type (TYPE_*) */
++  };
++  typedef struct asn1_data_node_st asn1_data_node_st;
++
+   /***********************************/
+   /*  Fixed constants                */
+   /***********************************/
+ 
+-  /* maximum number of characters of a name */
+-  /* inside a file with ASN1 definitons     */
+-#define ASN1_MAX_NAME_SIZE 128
+-
+   /* maximum number of characters */
+   /* of a description message     */
+   /* (null character included)    */
+@@ -182,6 +213,8 @@
+ 
+   extern ASN1_API asn1_retCode asn1_delete_structure (ASN1_TYPE * structure);
+ 
++  extern ASN1_API asn1_retCode asn1_delete_structure2 (ASN1_TYPE * structure, unsigned int flags);
++
+   extern ASN1_API asn1_retCode
+     asn1_delete_element (ASN1_TYPE structure, const char *element_name);
+ 
+@@ -194,6 +227,13 @@
+ 		     void *ivalue, int *len);
+ 
+   extern ASN1_API asn1_retCode
++    asn1_read_value_type (ASN1_TYPE root, const char *name,
++                          void *ivalue, int *len, unsigned int *etype);
++
++  extern ASN1_API asn1_retCode
++    asn1_read_node_value (ASN1_TYPE node, asn1_data_node_st * data);
++
++  extern ASN1_API asn1_retCode
+     asn1_number_of_elements (ASN1_TYPE element, const char *name, int *num);
+ 
+   extern ASN1_API asn1_retCode
+@@ -208,7 +248,7 @@
+     asn1_der_decoding_element (ASN1_TYPE * structure,
+ 			       const char *elementName,
+ 			       const void *ider, int len,
+-			       char *errorDescription);
++			       char *errorDescription); _ASN1_GCC_ATTR_DEPRECATED;
+ 
+   extern ASN1_API asn1_retCode
+     asn1_der_decoding_startEnd (ASN1_TYPE element,
+@@ -239,6 +279,10 @@
+ 
+   extern ASN1_API void asn1_perror (asn1_retCode error);
+ 
++#define ASN1_MAX_TAG_SIZE 4
++#define ASN1_MAX_LENGTH_SIZE 9
++#define ASN1_MAX_TL_SIZE (ASN1_MAX_TAG_SIZE+ASN1_MAX_LENGTH_SIZE)
++
+   /* DER utility functions. */
+ 
+   extern ASN1_API int
+@@ -273,6 +317,17 @@
+ 
+   /* Other utility functions. */
+ 
++  extern ASN1_API
++    int asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
++                                unsigned int der_len,
++                                const unsigned char **str,
++                                unsigned int *str_len);
++
++  extern ASN1_API int
++    asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
++                            unsigned int str_len, unsigned char *tl,
++                            unsigned int *tl_len);
++
+   extern ASN1_API ASN1_TYPE
+     asn1_find_node (ASN1_TYPE pointer, const char *name);
+ 
+--- ORIGINAL/./lib/gstr.h	2015-07-14 18:28:22.931870138 -0700
++++ libtasn1-2.8/./lib/gstr.h	2015-07-14 18:45:02.736947739 -0700
+@@ -20,8 +20,24 @@
+  * 02110-1301, USA
+  */
+ 
+-void _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src);
++unsigned int _asn1_str_cpy (char *dest, size_t dest_tot_size,
++			    const char *src);
+ void _asn1_str_cat (char *dest, size_t dest_tot_size, const char *src);
+ 
+ #define Estrcpy(x,y) _asn1_str_cpy(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
+ #define Estrcat(x,y) _asn1_str_cat(x,ASN1_MAX_ERROR_DESCRIPTION_SIZE,y)
++
++inline static
++void safe_memset(void *data, int c, size_t size)
++{
++	volatile unsigned volatile_zero = 0;
++	volatile char *vdata = (volatile char*)data;
++
++	/* This is based on a nice trick for safe memset,
++	 * sent by David Jacobson in the openssl-dev mailing list.
++	 */
++
++	do {
++		memset(data, c, size);
++	} while(vdata[volatile_zero] != c);
++}
+--- ORIGINAL/./lib/decoding.c	2015-07-14 18:28:22.909220237 -0700
++++ libtasn1-2.8/./lib/decoding.c	2015-07-14 18:45:02.647975796 -0700
+@@ -27,13 +27,113 @@
+ /*****************************************************/
+ 
+ #include <int.h>
+-#include "parser_aux.h"
++#include <parser_aux.h>
+ #include <gstr.h>
+-#include "structure.h"
+-#include "element.h"
++#include <structure.h>
++#include <element.h>
++#include <limits.h>
++/*#include <intprops.h>*/
++
++#define INT_ADD_OVERFLOW(a, b) \
++  _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW)
++#define INT_MULTIPLY_OVERFLOW(a, b) \
++  _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW)
++/* Return 1 if the expression A <op> B would overflow,
++   where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test,
++   assuming MIN and MAX are the minimum and maximum for the result type.
++   Arguments should be free of side effects.  */
++#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow)        \
++  op_result_overflow (a, b,                                     \
++                      _GL_INT_MINIMUM (0 * (b) + (a)),          \
++                      _GL_INT_MAXIMUM (0 * (b) + (a)))
++#define _GL_ADD_OVERFLOW(a, b, min, max)                                \
++  ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max)                  \
++   : (a) < 0 ? (b) <= (a) + (b)                                         \
++   : (b) < 0 ? (a) <= (a) + (b)                                         \
++   : (a) + (b) < (b))
++#define _GL_MULTIPLY_OVERFLOW(a, b, min, max)                           \
++  (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a))))       \
++   || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max))
++#define INT_ADD_RANGE_OVERFLOW(a, b, min, max)          \
++  ((b) < 0                                              \
++   ? (a) < (min) - (b)                                  \
++   : (max) - (b) < (a))
++
++#define _GL_SIGNED_INT_MAXIMUM(e)                                       \
++  (((_GL_INT_CONVERT (e, 1) << (sizeof ((e) + 0) * CHAR_BIT - 2)) - 1) * 2 + 1)
++
++#define _GL_INT_CONVERT(e, v) (0 * (e) + (v))
++
++/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see
++   <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00406.html>.  */
++#define _GL_INT_NEGATE_CONVERT(e, v) (0 * (e) - (v))
++
++#define CHAR_BIT        8               /* max # of bits in a "char" */
++
++/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic.
++   See above for restrictions.  Avoid && and || as they tickle
++   bugs in Sun C 5.11 2010/08/13 and other compilers; see
++   <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00401.html>.  */
++#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max)     \
++  ((b) < 0                                              \
++   ? ((a) < 0                                           \
++      ? (a) < (max) / (b)                               \
++      : (b) == -1                                       \
++      ? 0                                               \
++      : (min) / (b) < (a))                              \
++   : (b) == 0                                           \
++   ? 0                                                  \
++   : ((a) < 0                                           \
++      ? (a) < (min) / (b)                               \
++      : (max) / (b) < (a)))
++
++/* The maximum and minimum values for the type of the expression E,
++   after integer promotion.  E should not have side effects.  */
++#define _GL_INT_MINIMUM(e)                                              \
++  (_GL_INT_SIGNED (e)                                                   \
++   ? - _GL_INT_TWOS_COMPLEMENT (e) - _GL_SIGNED_INT_MAXIMUM (e)         \
++   : _GL_INT_CONVERT (e, 0))
++#define _GL_INT_MAXIMUM(e)                                              \
++  (_GL_INT_SIGNED (e)                                                   \
++   ? _GL_SIGNED_INT_MAXIMUM (e)                                         \
++   : _GL_INT_NEGATE_CONVERT (e, 1))
++
++/* True if the signed integer expression E uses two's complement.  */
++#define _GL_INT_TWOS_COMPLEMENT(e) (~ _GL_INT_CONVERT (e, 0) == -1)
++
++/* Return 1 if the integer expression E, after integer promotion, has
++   a signed type.  */
++#define _GL_INT_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
++
++#define INT_LEFT_SHIFT_OVERFLOW(a, b) \
++  INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \
++                                 _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a))
++
++#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max)   \
++  ((a) < 0                                              \
++   ? (a) < (min) >> (b)                                 \
++   : (max) >> (b) < (a))
++
++
++#ifdef DEBUG
++# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__)
++#else
++# define warn()
++#endif
++
++#define HAVE_TWO(x) (x>=2?1:0)
++
++#define DECR_LEN(l, s) do { \
++	  l -= s; \
++	  if (l < 0) { \
++	    warn(); \
++	    result = ASN1_DER_ERROR; \
++	    goto cleanup; \
++	  } \
++	} while (0)
+ 
+-static asn1_retCode
+-_asn1_get_indefinite_length_string (const unsigned char *der, int *len);
++static int
++_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len);
+ 
+ static void
+ _asn1_error_description_tag_error (ASN1_TYPE node, char *ErrorDescription)
+@@ -56,14 +156,13 @@
+  *
+  * Returns: Return the decoded length value, or -1 on indefinite
+  *   length, or -2 when the value was too big to fit in a int, or -4
+- *   when the decoed length value plus @len would exceed @der_len.
+-
++ *   when the decoded length value plus @len would exceed @der_len.
+  **/
+-signed long
++long
+ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
+ {
+-  int ans;
+-  int k, punt;
++  unsigned int ans;
++  int k, punt, sum;
+ 
+   *len = 0;
+   if (der_len <= 0)
+@@ -73,7 +172,7 @@
+     {
+       /* short form */
+       *len = 1;
+-      return der[0];
++      ans = der[0];
+     }
+   else
+     {
+@@ -85,25 +184,34 @@
+ 	  ans = 0;
+ 	  while (punt <= k && punt < der_len)
+ 	    {
+-              int last = ans;
++	      if (INT_MULTIPLY_OVERFLOW (ans, 256))
++		return -2;
++	      ans *= 256;
+ 
+-	      ans = ans * 256 + der[punt++];
+-	      if (ans < last)
+-		/* we wrapped around, no bignum support... */
++	      if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt])))
+ 		return -2;
++	      ans += der[punt];
++	      punt++;
+ 	    }
+ 	}
+       else
+ 	{			/* indefinite length method */
+-           *len = punt;
+-           return -1;
++	  *len = punt;
++	  return -1;
+ 	}
+ 
+       *len = punt;
+-      if (ans + *len < ans || ans + *len > der_len)
+-       return -4;
+-      return ans;
+     }
++
++  sum = ans;
++  if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len)))
++    return -2;
++  sum += *len;
++
++  if (sum > der_len)
++    return -4;
++
++  return ans;
+ }
+ 
+ /**
+@@ -122,7 +230,8 @@
+ asn1_get_tag_der (const unsigned char *der, int der_len,
+ 		  unsigned char *cls, int *len, unsigned long *tag)
+ {
+-  int punt, ris;
++  unsigned int ris;
++  int punt;
+ 
+   if (der == NULL || der_len < 2 || len == NULL)
+     return ASN1_DER_ERROR;
+@@ -139,25 +248,34 @@
+       /* Long form */
+       punt = 1;
+       ris = 0;
+-      while (punt <= der_len && der[punt] & 128)
++      while (punt < der_len && der[punt] & 128)
+ 	{
+-	  int last = ris;
+-	  ris = ris * 128 + (der[punt++] & 0x7F);
+-	  if (ris < last)
+-	    /* wrapper around, and no bignums... */
++
++	  if (INT_MULTIPLY_OVERFLOW (ris, 128))
+ 	    return ASN1_DER_ERROR;
++	  ris *= 128;
++
++	  if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
++	    return ASN1_DER_ERROR;
++	  ris += (der[punt] & 0x7F);
++	  punt++;
+ 	}
++
+       if (punt >= der_len)
+ 	return ASN1_DER_ERROR;
+-      {
+-	int last = ris;
+-	ris = ris * 128 + (der[punt++] & 0x7F);
+-	if (ris < last)
+-	  /* wrapper around, and no bignums... */
+-	  return ASN1_DER_ERROR;
+-      }
++
++      if (INT_MULTIPLY_OVERFLOW (ris, 128))
++	return ASN1_DER_ERROR;
++      ris *= 128;
++
++      if (INT_ADD_OVERFLOW (ris, ((unsigned) (der[punt] & 0x7F))))
++	return ASN1_DER_ERROR;
++      ris += (der[punt] & 0x7F);
++      punt++;
++
+       *len = punt;
+     }
++
+   if (tag)
+     *tag = ris;
+   return ASN1_SUCCESS;
+@@ -178,7 +296,7 @@
+  *
+  * Since: 2.0
+  **/
+-signed long
++long
+ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len)
+ {
+   int ret;
+@@ -187,8 +305,7 @@
+   ret = asn1_get_length_der (ber, ber_len, len);
+   if (ret == -1)
+     {				/* indefinite length method */
+-      ret = ber_len;
+-      err = _asn1_get_indefinite_length_string (ber + 1, &ret);
++      err = _asn1_get_indefinite_length_string (ber + 1, ber_len, &ret);
+       if (err != ASN1_SUCCESS)
+ 	return -3;
+     }
+@@ -219,7 +336,6 @@
+   if (der_len <= 0)
+     return ASN1_GENERIC_ERROR;
+ 
+-  /* if(str==NULL) return ASN1_SUCCESS; */
+   *str_len = asn1_get_length_der (der, der_len, &len_len);
+ 
+   if (*str_len < 0)
+@@ -227,7 +343,10 @@
+ 
+   *ret_len = *str_len + len_len;
+   if (str_size >= *str_len)
+-    memcpy (str, der + len_len, *str_len);
++    {
++      if (*str_len > 0 && str != NULL)
++        memcpy (str, der + len_len, *str_len);
++    }
+   else
+     {
+       return ASN1_MEM_ERROR;
+@@ -246,9 +365,11 @@
+ 
+   if (der_len <= 0 || str == NULL)
+     return ASN1_DER_ERROR;
++
+   str_len = asn1_get_length_der (der, der_len, &len_len);
+-  if (str_len < 0 || str_size < str_len)
++  if (str_len <= 0 || str_size < str_len)
+     return ASN1_DER_ERROR;
++
+   memcpy (str, der + len_len, str_len);
+   str[str_len] = 0;
+   *ret_len = str_len + len_len;
+@@ -262,8 +383,8 @@
+ {
+   int len_len, len, k;
+   int leading;
+-  char temp[20];
+-  unsigned long val, val1, prev_val;
++  char temp[LTOSTR_MAX_SIZE];
++  unsigned long val, val1;
+ 
+   *ret_len = 0;
+   if (str && str_size > 0)
+@@ -271,9 +392,10 @@
+ 
+   if (str == NULL || der_len <= 0)
+     return ASN1_GENERIC_ERROR;
++
+   len = asn1_get_length_der (der, der_len, &len_len);
+ 
+-  if (len < 0 || len > der_len || len_len > der_len)
++  if (len <= 0 || len + len_len > der_len)
+     return ASN1_DER_ERROR;
+ 
+   val1 = der[len_len] / 40;
+@@ -283,7 +405,6 @@
+   _asn1_str_cat (str, str_size, ".");
+   _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+ 
+-  prev_val = 0;
+   val = 0;
+   leading = 1;
+   for (k = 1; k < len; k++)
+@@ -295,23 +416,24 @@
+       leading = 0;
+ 
+       /* check for wrap around */
+-      val = val << 7;
+-      val |= der[len_len + k] & 0x7F;
+-
+-      if (val < prev_val)
++      if (INT_LEFT_SHIFT_OVERFLOW (val, 7))
+ 	return ASN1_DER_ERROR;
+ 
+-      prev_val = val;
++      val = val << 7;
++      val |= der[len_len + k] & 0x7F;
+ 
+       if (!(der[len_len + k] & 0x80))
+ 	{
+ 	  _asn1_str_cat (str, str_size, ".");
+ 	  _asn1_str_cat (str, str_size, _asn1_ltostr (val, temp));
+ 	  val = 0;
+-	  prev_val = 0;
+ 	  leading = 1;
+ 	}
+     }
++
++  if (INT_ADD_OVERFLOW (len, len_len))
++    return ASN1_DER_ERROR;
++
+   *ret_len = len + len_len;
+ 
+   return ASN1_SUCCESS;
+@@ -339,6 +461,7 @@
+ 
+   if (der_len <= 0)
+     return ASN1_GENERIC_ERROR;
++
+   len_byte = asn1_get_length_der (der, der_len, &len_len) - 1;
+   if (len_byte < 0)
+     return ASN1_DER_ERROR;
+@@ -346,11 +469,14 @@
+   *ret_len = len_byte + len_len + 1;
+   *bit_len = len_byte * 8 - der[len_len];
+ 
+-  if (*bit_len <= 0)
++  if (*bit_len < 0)
+     return ASN1_DER_ERROR;
+ 
+   if (str_size >= len_byte)
+-    memcpy (str, der + len_len + 1, len_byte);
++    {
++      if (len_byte > 0 && str)
++        memcpy (str, der + len_len + 1, len_byte);
++    }
+   else
+     {
+       return ASN1_MEM_ERROR;
+@@ -359,12 +485,14 @@
+   return ASN1_SUCCESS;
+ }
+ 
++
+ static int
+ _asn1_extract_tag_der (ASN1_TYPE node, const unsigned char *der, int der_len,
+ 		       int *ret_len)
+ {
+   ASN1_TYPE p;
+   int counter, len2, len3, is_tag_implicit;
++  int result;
+   unsigned long tag, tag_implicit = 0;
+   unsigned char class, class2, class_implicit = 0;
+ 
+@@ -392,23 +520,21 @@
+ 	      if (p->type & CONST_EXPLICIT)
+ 		{
+ 		  if (asn1_get_tag_der
+-		      (der + counter, der_len - counter, &class, &len2,
++		      (der + counter, der_len, &class, &len2,
+ 		       &tag) != ASN1_SUCCESS)
+ 		    return ASN1_DER_ERROR;
+ 
+-		  if (counter + len2 > der_len)
+-		    return ASN1_DER_ERROR;
++                  DECR_LEN(der_len, len2);
+ 		  counter += len2;
+ 
+ 		  len3 =
+-		    asn1_get_length_ber (der + counter, der_len - counter,
++		    asn1_get_length_ber (der + counter, der_len,
+ 					 &len2);
+ 		  if (len3 < 0)
+ 		    return ASN1_DER_ERROR;
+ 
++                  DECR_LEN(der_len, len2);
+ 		  counter += len2;
+-		  if (counter > der_len)
+-		    return ASN1_DER_ERROR;
+ 
+ 		  if (!is_tag_implicit)
+ 		    {
+@@ -428,9 +554,9 @@
+ 		  if (!is_tag_implicit)
+ 		    {
+ 		      if ((type_field (node->type) == TYPE_SEQUENCE) ||
+-			  (type_field (node->type) == TYPE_SEQUENCE_OF) ||
+-			  (type_field (node->type) == TYPE_SET) ||
+-			  (type_field (node->type) == TYPE_SET_OF))
++			  (type_field (node->type) == TYPE_SEQUENCE_OF)
++			  || (type_field (node->type) == TYPE_SET)
++			  || (type_field (node->type) == TYPE_SET_OF))
+ 			class2 |= ASN1_CLASS_STRUCTURED;
+ 		      class_implicit = class2;
+ 		      tag_implicit = strtoul ((char *) p->value, NULL, 10);
+@@ -445,11 +571,11 @@
+   if (is_tag_implicit)
+     {
+       if (asn1_get_tag_der
+-	  (der + counter, der_len - counter, &class, &len2,
++	  (der + counter, der_len, &class, &len2,
+ 	   &tag) != ASN1_SUCCESS)
+ 	return ASN1_DER_ERROR;
+-      if (counter + len2 > der_len)
+-	return ASN1_DER_ERROR;
++
++      DECR_LEN(der_len, len2);
+ 
+       if ((class != class_implicit) || (tag != tag_implicit))
+ 	{
+@@ -465,87 +591,62 @@
+     }
+   else
+     {
+-      if (type_field (node->type) == TYPE_TAG)
++      unsigned type = type_field (node->type);
++      if (type == TYPE_TAG)
+ 	{
+-	  counter = 0;
+-	  *ret_len = counter;
++	  *ret_len = 0;
+ 	  return ASN1_SUCCESS;
+ 	}
+ 
+       if (asn1_get_tag_der
+-	  (der + counter, der_len - counter, &class, &len2,
++	  (der + counter, der_len, &class, &len2,
+ 	   &tag) != ASN1_SUCCESS)
+ 	return ASN1_DER_ERROR;
+ 
+-      if (counter + len2 > der_len)
+-	return ASN1_DER_ERROR;
++      DECR_LEN(der_len, len2);
+ 
+-      switch (type_field (node->type))
++      switch (type)
+ 	{
+ 	case TYPE_NULL:
+-	  if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_NULL))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_BOOLEAN:
+-	  if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_BOOLEAN))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_INTEGER:
+-	  if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_INTEGER))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_ENUMERATED:
+-	  if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_ENUMERATED))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_OBJECT_ID:
+-	  if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_OBJECT_ID))
+-	    return ASN1_DER_ERROR;
+-	  break;
+-	case TYPE_TIME:
+-	  if (node->type & CONST_UTC)
+-	    {
+-	      if ((class != ASN1_CLASS_UNIVERSAL)
+-		  || (tag != ASN1_TAG_UTCTime))
+-		return ASN1_DER_ERROR;
+-	    }
+-	  else
+-	    {
+-	      if ((class != ASN1_CLASS_UNIVERSAL)
+-		  || (tag != ASN1_TAG_GENERALIZEDTime))
+-		return ASN1_DER_ERROR;
+-	    }
+-	  break;
+-	case TYPE_OCTET_STRING:
+-	  if (((class != ASN1_CLASS_UNIVERSAL)
+-	       && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED)))
+-	      || (tag != ASN1_TAG_OCTET_STRING))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_GENERALSTRING:
+-	  if ((class != ASN1_CLASS_UNIVERSAL)
+-	      || (tag != ASN1_TAG_GENERALSTRING))
+-	    return ASN1_DER_ERROR;
+-	  break;
++	case TYPE_NUMERIC_STRING:
++	case TYPE_IA5_STRING:
++	case TYPE_TELETEX_STRING:
++	case TYPE_PRINTABLE_STRING:
++	case TYPE_UNIVERSAL_STRING:
++	case TYPE_BMP_STRING:
++	case TYPE_UTF8_STRING:
++	case TYPE_VISIBLE_STRING:
+ 	case TYPE_BIT_STRING:
+-	  if ((class != ASN1_CLASS_UNIVERSAL) || (tag != ASN1_TAG_BIT_STRING))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_SEQUENCE:
+ 	case TYPE_SEQUENCE_OF:
+-	  if ((class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))
+-	      || (tag != ASN1_TAG_SEQUENCE))
+-	    return ASN1_DER_ERROR;
+-	  break;
+ 	case TYPE_SET:
+ 	case TYPE_SET_OF:
+-	  if ((class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED))
+-	      || (tag != ASN1_TAG_SET))
++	case TYPE_GENERALIZED_TIME:
++	case TYPE_UTC_TIME:
++	  if ((class != _asn1_tags[type].class)
++	      || (tag != _asn1_tags[type].tag))
++	    return ASN1_DER_ERROR;
++	  break;
++
++	case TYPE_OCTET_STRING:
++	  /* OCTET STRING is handled differently to allow
++	   * BER encodings (structured class). */
++	  if (((class != ASN1_CLASS_UNIVERSAL)
++	       && (class != (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED)))
++	      || (tag != ASN1_TAG_OCTET_STRING))
+ 	    return ASN1_DER_ERROR;
+ 	  break;
+ 	case TYPE_ANY:
+ 	  counter -= len2;
+ 	  break;
++	case TYPE_CHOICE:
++	  counter -= len2;
++	  break;
+ 	default:
+ 	  return ASN1_DER_ERROR;
+ 	  break;
+@@ -555,6 +656,34 @@
+   counter += len2;
+   *ret_len = counter;
+   return ASN1_SUCCESS;
++
++cleanup:
++  return result;
++}
++
++static int
++extract_tag_der_recursive(ASN1_TYPE node, const unsigned char *der, int der_len,
++		       int *ret_len)
++{
++ASN1_TYPE p;
++int ris = ASN1_DER_ERROR;
++
++  if (type_field (node->type) == TYPE_CHOICE)
++    {
++      p = node->down;
++      while (p)
++        {
++          ris = _asn1_extract_tag_der (p, der, der_len, ret_len);
++          if (ris == ASN1_SUCCESS)
++            break;
++          p = p->right;
++	}
++
++      *ret_len = 0;
++      return ris;
++    }
++  else
++    return _asn1_extract_tag_der (node, der, der_len, ret_len);
+ }
+ 
+ static int
+@@ -616,102 +745,116 @@
+   return ASN1_SUCCESS;
+ }
+ 
+-static asn1_retCode
++static int
+ _asn1_extract_der_octet (ASN1_TYPE node, const unsigned char *der,
+ 			 int der_len)
+ {
+   int len2, len3;
+-  int counter2, counter_end;
++  int counter, counter_end;
++  int result;
+ 
+   len2 = asn1_get_length_der (der, der_len, &len3);
+   if (len2 < -1)
+     return ASN1_DER_ERROR;
+ 
+-  counter2 = len3 + 1;
++  counter = len3 + 1;
+ 
+   if (len2 == -1)
+     counter_end = der_len - 2;
+   else
+     counter_end = der_len;
+ 
+-  while (counter2 < counter_end)
++  while (counter < counter_end)
+     {
+-      len2 = asn1_get_length_der (der + counter2, der_len - counter2, &len3);
++      len2 = asn1_get_length_der (der + counter, der_len, &len3);
+ 
+       if (len2 < -1)
+ 	return ASN1_DER_ERROR;
+ 
+       if (len2 > 0)
+ 	{
+-	  _asn1_append_value (node, der + counter2 + len3, len2);
++	  DECR_LEN(der_len, len2+len3);
++	  _asn1_append_value (node, der + counter + len3, len2);
+ 	}
+       else
+ 	{			/* indefinite */
+-
+-	  len2 =
+-	    _asn1_extract_der_octet (node, der + counter2 + len3,
+-				     der_len - counter2 - len3);
+-	  if (len2 < 0)
+-	    return len2;
++	  DECR_LEN(der_len, len3);
++	  result =
++	    _asn1_extract_der_octet (node, der + counter + len3,
++				     der_len);
++	  if (result != ASN1_SUCCESS)
++	    return result;
++	  DECR_LEN(der_len, len2);
+ 	}
+ 
+-      counter2 += len2 + len3 + 1;
++      DECR_LEN(der_len, 1);
++      counter += len2 + len3 + 1;
+     }
+ 
+   return ASN1_SUCCESS;
++
++cleanup:
++  return result;
+ }
+ 
+-static asn1_retCode
+-_asn1_get_octet_string (const unsigned char *der, ASN1_TYPE node, int *len)
++static int
++_asn1_get_octet_string (ASN1_TYPE node, const unsigned char *der, int der_len, int *len)
+ {
+   int len2, len3, counter, tot_len, indefinite;
++  int result;
+ 
+   counter = 0;
+ 
+   if (*(der - 1) & ASN1_CLASS_STRUCTURED)
+     {
+       tot_len = 0;
+-      indefinite = asn1_get_length_der (der, *len, &len3);
++      indefinite = asn1_get_length_der (der, der_len, &len3);
+       if (indefinite < -1)
+ 	return ASN1_DER_ERROR;
+ 
+       counter += len3;
++      DECR_LEN(der_len, len3);
++
+       if (indefinite >= 0)
+ 	indefinite += len3;
+ 
+       while (1)
+ 	{
+-	  if (counter > (*len))
++	  if (counter > der_len)
+ 	    return ASN1_DER_ERROR;
+ 
+ 	  if (indefinite == -1)
+ 	    {
+-	      if ((der[counter] == 0) && (der[counter + 1] == 0))
++	      if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
+ 		{
+ 		  counter += 2;
++		  DECR_LEN(der_len, 2);
+ 		  break;
+ 		}
+ 	    }
+ 	  else if (counter >= indefinite)
+ 	    break;
+ 
++          DECR_LEN(der_len, 1);
+ 	  if (der[counter] != ASN1_TAG_OCTET_STRING)
+ 	    return ASN1_DER_ERROR;
+ 
+ 	  counter++;
+ 
+-	  len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
++	  len2 = asn1_get_length_der (der + counter, der_len, &len3);
+ 	  if (len2 <= 0)
+ 	    return ASN1_DER_ERROR;
+ 
++          DECR_LEN(der_len, len3 + len2);
+ 	  counter += len3 + len2;
++
+ 	  tot_len += len2;
+ 	}
+ 
+       /* copy */
+       if (node)
+ 	{
+-	  unsigned char temp[DER_LEN];
++	  unsigned char temp[ASN1_MAX_LENGTH_SIZE];
+ 	  int ret;
+ 
+ 	  len2 = sizeof (temp);
+@@ -719,9 +862,7 @@
+ 	  asn1_length_der (tot_len, temp, &len2);
+ 	  _asn1_set_value (node, temp, len2);
+ 
+-	  tot_len += len2;
+-
+-	  ret = _asn1_extract_der_octet (node, der, *len);
++	  ret = _asn1_extract_der_octet (node, der, der_len);
+ 	  if (ret != ASN1_SUCCESS)
+ 	    return ret;
+ 
+@@ -729,25 +870,29 @@
+     }
+   else
+     {				/* NOT STRUCTURED */
+-      len2 = asn1_get_length_der (der, *len, &len3);
++      len2 = asn1_get_length_der (der, der_len, &len3);
+       if (len2 < 0)
+ 	return ASN1_DER_ERROR;
+-      if (len3 + len2 > *len)
+-	return ASN1_DER_ERROR;
+-      if (node)
+-	_asn1_set_value (node, der, len3 + len2);
++
++      DECR_LEN(der_len, len3+len2);
+       counter = len3 + len2;
++      if (node)
++	_asn1_set_value (node, der, counter);
+     }
+ 
+   *len = counter;
+   return ASN1_SUCCESS;
+ 
++cleanup:
++  return result;
+ }
+ 
+-static asn1_retCode
+-_asn1_get_indefinite_length_string (const unsigned char *der, int *len)
++static int
++_asn1_get_indefinite_length_string (const unsigned char *der,
++				    int der_len, int *len)
+ {
+   int len2, len3, counter, indefinite;
++  int result;
+   unsigned long tag;
+   unsigned char class;
+ 
+@@ -755,12 +900,11 @@
+ 
+   while (1)
+     {
+-      if ((*len) < counter)
+-	return ASN1_DER_ERROR;
+-
+-      if ((der[counter] == 0) && (der[counter + 1] == 0))
++      if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0))
+ 	{
+ 	  counter += 2;
++	  DECR_LEN(der_len, 2);
++
+ 	  indefinite--;
+ 	  if (indefinite <= 0)
+ 	    break;
+@@ -769,36 +913,55 @@
+ 	}
+ 
+       if (asn1_get_tag_der
+-	  (der + counter, *len - counter, &class, &len2,
++	  (der + counter, der_len, &class, &len2,
+ 	   &tag) != ASN1_SUCCESS)
+ 	return ASN1_DER_ERROR;
+-      if (counter + len2 > *len)
+-	return ASN1_DER_ERROR;
++
++      DECR_LEN(der_len, len2);
+       counter += len2;
+-      len2 = asn1_get_length_der (der + counter, *len - counter, &len3);
++
++      len2 = asn1_get_length_der (der + counter, der_len, &len3);
+       if (len2 < -1)
+ 	return ASN1_DER_ERROR;
++
+       if (len2 == -1)
+ 	{
+ 	  indefinite++;
+ 	  counter += 1;
++          DECR_LEN(der_len, 1);
+ 	}
+       else
+ 	{
+ 	  counter += len2 + len3;
++          DECR_LEN(der_len, len2+len3);
+ 	}
+     }
+ 
+   *len = counter;
+   return ASN1_SUCCESS;
+ 
++cleanup:
++  return result;
++}
++
++static void delete_unneeded_choice_fields(ASN1_TYPE p)
++{
++  ASN1_TYPE p2;
++
++  while (p->right)
++    {
++      p2 = p->right;
++      asn1_delete_structure (&p2);
++    }
+ }
+ 
++
++
+ /**
+  * asn1_der_decoding:
+  * @element: pointer to an ASN1 structure.
+  * @ider: vector that contains the DER encoding.
+- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1].
++ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1].
+  * @errorDescription: null-terminated string contains details when an
+  *   error occurred.
+  *
+@@ -806,15 +969,15 @@
+  * string. The structure must just be created with function
+  * asn1_create_element().  If an error occurs during the decoding
+  * procedure, the *@ELEMENT is deleted and set equal to
+- * %ASN1_TYPE_EMPTY.
++ * %NULL.
+  *
+  * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+- *   if @ELEMENT is %ASN1_TYPE_EMPTY, and %ASN1_TAG_ERROR or
++ *   if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or
+  *   %ASN1_DER_ERROR if the der encoding doesn't match the structure
+  *   name (*@ELEMENT deleted).
+  **/
+-asn1_retCode
+-asn1_der_decoding (ASN1_TYPE * element, const void *ider, int len,
++int
++asn1_der_decoding (ASN1_TYPE * element, const void *ider, int ider_len,
+ 		   char *errorDescription)
+ {
+   ASN1_TYPE node, p, p2, p3;
+@@ -827,13 +990,17 @@
+ 
+   node = *element;
+ 
+-  if (node == ASN1_TYPE_EMPTY)
++  if (errorDescription != NULL)
++    errorDescription[0] = 0;
++
++  if (node == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   if (node->type & CONST_OPTION)
+     {
+-      asn1_delete_structure (element);
+-      return ASN1_GENERIC_ERROR;
++      result = ASN1_GENERIC_ERROR;
++      warn();
++      goto cleanup;
+     }
+ 
+   counter = 0;
+@@ -847,14 +1014,15 @@
+ 	  if (p->type & CONST_SET)
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
+ 	      if (len2 == -1)
+ 		{
+-		  if (!der[counter] && !der[counter + 1])
++		  if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
+ 		    {
+ 		      p = p2;
+ 		      move = UP;
+ 		      counter += 2;
++		      DECR_LEN(ider_len, 2);
+ 		      continue;
+ 		    }
+ 		}
+@@ -866,31 +1034,18 @@
+ 		}
+ 	      else if (counter > len2)
+ 		{
+-		  asn1_delete_structure (element);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
+ 		}
+ 	      p2 = p2->down;
+ 	      while (p2)
+ 		{
+ 		  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ 		    {
+-		      if (type_field (p2->type) != TYPE_CHOICE)
+-			ris =
+-			  _asn1_extract_tag_der (p2, der + counter,
+-						 len - counter, &len2);
+-		      else
+-			{
+-			  p3 = p2->down;
+-			  while (p3)
+-			    {
+-			      ris =
+-				_asn1_extract_tag_der (p3, der + counter,
+-						       len - counter, &len2);
+-			      if (ris == ASN1_SUCCESS)
+-				break;
+-			      p3 = p3->right;
+-			    }
+-			}
++		      ris =
++			  extract_tag_der_recursive (p2, der + counter,
++						     ider_len, &len2);
+ 		      if (ris == ASN1_SUCCESS)
+ 			{
+ 			  p2->type &= ~CONST_NOT_USED;
+@@ -902,15 +1057,16 @@
+ 		}
+ 	      if (p2 == NULL)
+ 		{
+-		  asn1_delete_structure (element);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
+ 		}
+ 	    }
+ 
+ 	  if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
+ 	      if (counter == len2)
+ 		{
+ 		  if (p->right)
+@@ -933,25 +1089,20 @@
+ 	    {
+ 	      while (p->down)
+ 		{
+-		  if (counter < len)
+-		    ris =
+-		      _asn1_extract_tag_der (p->down, der + counter,
+-					     len - counter, &len2);
+-		  else
+-		    ris = ASN1_DER_ERROR;
++		  ris =
++		      extract_tag_der_recursive (p->down, der + counter,
++					         ider_len, &len2);
++
+ 		  if (ris == ASN1_SUCCESS)
+ 		    {
+-		      while (p->down->right)
+-			{
+-			  p2 = p->down->right;
+-			  asn1_delete_structure (&p2);
+-			}
++		      delete_unneeded_choice_fields(p->down);
+ 		      break;
+ 		    }
+ 		  else if (ris == ASN1_ERROR_TYPE_ANY)
+ 		    {
+-		      asn1_delete_structure (element);
+-		      return ASN1_ERROR_TYPE_ANY;
++		      result = ASN1_ERROR_TYPE_ANY;
++                      warn();
++		      goto cleanup;
+ 		    }
+ 		  else
+ 		    {
+@@ -964,25 +1115,28 @@
+ 		{
+ 		  if (!(p->type & CONST_OPTION))
+ 		    {
+-		      asn1_delete_structure (element);
+-		      return ASN1_DER_ERROR;
++		      result = ASN1_DER_ERROR;
++                      warn();
++		      goto cleanup;
+ 		    }
+ 		}
+-	      else
++	      else if (type_field (p->type) != TYPE_CHOICE)
+ 		p = p->down;
+ 	    }
+ 
+ 	  if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
++
+ 	      if ((len2 != -1) && (counter > len2))
+ 		ris = ASN1_TAG_ERROR;
+ 	    }
+ 
+ 	  if (ris == ASN1_SUCCESS)
+ 	    ris =
+-	      _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
++	      extract_tag_der_recursive (p, der + counter, ider_len, &len2);
++
+ 	  if (ris != ASN1_SUCCESS)
+ 	    {
+ 	      if (p->type & CONST_OPTION)
+@@ -1000,12 +1154,16 @@
+ 		  if (errorDescription != NULL)
+ 		    _asn1_error_description_tag_error (p, errorDescription);
+ 
+-		  asn1_delete_structure (element);
+-		  return ASN1_TAG_ERROR;
++		  result = ASN1_TAG_ERROR;
++                  warn();
++		  goto cleanup;
+ 		}
+ 	    }
+ 	  else
+-	    counter += len2;
++	    {
++	      DECR_LEN(ider_len, len2);
++	      counter += len2;
++	    }
+ 	}
+ 
+       if (ris == ASN1_SUCCESS)
+@@ -1013,19 +1171,24 @@
+ 	  switch (type_field (p->type))
+ 	    {
+ 	    case TYPE_NULL:
++	      DECR_LEN(ider_len, 1);
+ 	      if (der[counter])
+ 		{
+-		  asn1_delete_structure (element);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
+ 		}
+ 	      counter++;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_BOOLEAN:
++	      DECR_LEN(ider_len, 2);
++
+ 	      if (der[counter++] != 1)
+ 		{
+-		  asn1_delete_structure (element);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
+ 		}
+ 	      if (der[counter++] == 0)
+ 		_asn1_set_value (p, "F", 1);
+@@ -1036,72 +1199,92 @@
+ 	    case TYPE_INTEGER:
+ 	    case TYPE_ENUMERATED:
+ 	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
++		asn1_get_length_der (der + counter, ider_len, &len3);
+ 	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      if (len2 + len3 > len - counter)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
++		}
++
++	      DECR_LEN(ider_len, len3+len2);
++
+ 	      _asn1_set_value (p, der + counter, len3 + len2);
+ 	      counter += len3 + len2;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_OBJECT_ID:
+ 	      result =
+-		_asn1_get_objectid_der (der + counter, len - counter, &len2,
++		_asn1_get_objectid_der (der + counter, ider_len, &len2,
+ 					temp, sizeof (temp));
+ 	      if (result != ASN1_SUCCESS)
+-		{
+-		  asn1_delete_structure (element);
+-		  return result;
++	        {
++                  warn();
++		  goto cleanup;
+ 		}
+ 
++	      DECR_LEN(ider_len, len2);
++
+ 	      tlen = strlen (temp);
+ 	      if (tlen > 0)
+ 		_asn1_set_value (p, temp, tlen + 1);
++
+ 	      counter += len2;
+ 	      move = RIGHT;
+ 	      break;
+-	    case TYPE_TIME:
++	    case TYPE_GENERALIZED_TIME:
++	    case TYPE_UTC_TIME:
+ 	      result =
+-		_asn1_get_time_der (der + counter, len - counter, &len2, temp,
++		_asn1_get_time_der (der + counter, ider_len, &len2, temp,
+ 				    sizeof (temp) - 1);
+ 	      if (result != ASN1_SUCCESS)
+-		{
+-		  asn1_delete_structure (element);
+-		  return result;
+-		}
++	        {
++                  warn();
++  		  goto cleanup;
++  		}
++
++	      DECR_LEN(ider_len, len2);
++
+ 	      tlen = strlen (temp);
+ 	      if (tlen > 0)
+-		_asn1_set_value (p, temp, tlen + 1);
++		_asn1_set_value (p, temp, tlen);
++
+ 	      counter += len2;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_OCTET_STRING:
+-	      len3 = len - counter;
+-	      ris = _asn1_get_octet_string (der + counter, p, &len3);
+-	      if (ris != ASN1_SUCCESS)
+-		return ris;
++	      result = _asn1_get_octet_string (p, der + counter, ider_len, &len3);
++	      if (result != ASN1_SUCCESS)
++	        {
++                  warn();
++		  goto cleanup;
++		}
++
++	      DECR_LEN(ider_len, len3);
+ 	      counter += len3;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_GENERALSTRING:
+-	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
+-	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      if (len3 + len2 > len - counter)
+-		return ASN1_DER_ERROR;
+-	      _asn1_set_value (p, der + counter, len3 + len2);
+-	      counter += len3 + len2;
+-	      move = RIGHT;
+-	      break;
++	    case TYPE_NUMERIC_STRING:
++	    case TYPE_IA5_STRING:
++	    case TYPE_TELETEX_STRING:
++	    case TYPE_PRINTABLE_STRING:
++	    case TYPE_UNIVERSAL_STRING:
++	    case TYPE_BMP_STRING:
++	    case TYPE_UTF8_STRING:
++	    case TYPE_VISIBLE_STRING:
+ 	    case TYPE_BIT_STRING:
+ 	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
++		asn1_get_length_der (der + counter, ider_len, &len3);
+ 	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      if (len3 + len2 > len - counter)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
++		}
++
++	      DECR_LEN(ider_len, len3+len2);
++
+ 	      _asn1_set_value (p, der + counter, len3 + len2);
+ 	      counter += len3 + len2;
+ 	      move = RIGHT;
+@@ -1110,28 +1293,26 @@
+ 	    case TYPE_SET:
+ 	      if (move == UP)
+ 		{
+-		  len2 = strtol (p->value, NULL, 10);
++		  len2 = _asn1_strtol (p->value, NULL, 10);
+ 		  _asn1_set_value (p, NULL, 0);
+ 		  if (len2 == -1)
+ 		    {		/* indefinite length method */
+-		      if (len - counter + 1 > 0)
+-			{
+-			  if ((der[counter]) || der[counter + 1])
+-			    {
+-			      asn1_delete_structure (element);
+-			      return ASN1_DER_ERROR;
+-			    }
++		      DECR_LEN(ider_len, 2);
++		      if ((der[counter]) || der[counter + 1])
++		        {
++		          result = ASN1_DER_ERROR;
++                          warn();
++		          goto cleanup;
+ 			}
+-		      else
+-			return ASN1_DER_ERROR;
+ 		      counter += 2;
+ 		    }
+ 		  else
+ 		    {		/* definite length method */
+ 		      if (len2 != counter)
+ 			{
+-			  asn1_delete_structure (element);
+-			  return ASN1_DER_ERROR;
++			  result = ASN1_DER_ERROR;
++                          warn();
++			  goto cleanup;
+ 			}
+ 		    }
+ 		  move = RIGHT;
+@@ -1139,10 +1320,17 @@
+ 	      else
+ 		{		/* move==DOWN || move==RIGHT */
+ 		  len3 =
+-		    asn1_get_length_der (der + counter, len - counter, &len2);
++		    asn1_get_length_der (der + counter, ider_len, &len2);
+ 		  if (len3 < -1)
+-		    return ASN1_DER_ERROR;
++		    {
++		      result = ASN1_DER_ERROR;
++                      warn();
++		      goto cleanup;
++		    }
++
++	          DECR_LEN(ider_len, len2);
+ 		  counter += len2;
++
+ 		  if (len3 > 0)
+ 		    {
+ 		      _asn1_ltostr (counter + len3, temp);
+@@ -1178,12 +1366,10 @@
+ 	    case TYPE_SET_OF:
+ 	      if (move == UP)
+ 		{
+-		  len2 = strtol (p->value, NULL, 10);
++		  len2 = _asn1_strtol (p->value, NULL, 10);
+ 		  if (len2 == -1)
+ 		    {		/* indefinite length method */
+-		      if ((counter + 2) > len)
+-			return ASN1_DER_ERROR;
+-		      if ((der[counter]) || der[counter + 1])
++		      if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
+ 			{
+ 			  _asn1_append_sequence_set (p);
+ 			  p = p->down;
+@@ -1192,7 +1378,9 @@
+ 			  move = RIGHT;
+ 			  continue;
+ 			}
++
+ 		      _asn1_set_value (p, NULL, 0);
++		      DECR_LEN(ider_len, 2);
+ 		      counter += 2;
+ 		    }
+ 		  else
+@@ -1206,20 +1394,28 @@
+ 			  move = RIGHT;
+ 			  continue;
+ 			}
++
+ 		      _asn1_set_value (p, NULL, 0);
+ 		      if (len2 != counter)
+ 			{
+-			  asn1_delete_structure (element);
+-			  return ASN1_DER_ERROR;
++			  result = ASN1_DER_ERROR;
++                          warn();
++			  goto cleanup;
+ 			}
+ 		    }
+ 		}
+ 	      else
+ 		{		/* move==DOWN || move==RIGHT */
+ 		  len3 =
+-		    asn1_get_length_der (der + counter, len - counter, &len2);
++		    asn1_get_length_der (der + counter, ider_len, &len2);
+ 		  if (len3 < -1)
+-		    return ASN1_DER_ERROR;
++		    {
++		      result = ASN1_DER_ERROR;
++                      warn();
++		      goto cleanup;
++		    }
++
++		  DECR_LEN(ider_len, len2);
+ 		  counter += len2;
+ 		  if (len3)
+ 		    {
+@@ -1248,56 +1444,76 @@
+ 	      break;
+ 	    case TYPE_ANY:
+ 	      if (asn1_get_tag_der
+-		  (der + counter, len - counter, &class, &len2,
++		  (der + counter, ider_len, &class, &len2,
+ 		   &tag) != ASN1_SUCCESS)
+-		return ASN1_DER_ERROR;
+-	      if (counter + len2 > len)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
++		}
++
++	      DECR_LEN(ider_len, len2);
++
+ 	      len4 =
+ 		asn1_get_length_der (der + counter + len2,
+-				     len - counter - len2, &len3);
++				     ider_len, &len3);
+ 	      if (len4 < -1)
+-		return ASN1_DER_ERROR;
+-	      if (len4 > len - counter + len2 + len3)
+-		return ASN1_DER_ERROR;
+-	      if (len4 != -1)
++		{
++		  result = ASN1_DER_ERROR;
++                  warn();
++		  goto cleanup;
++		}
++	      if (len4 != -1) /* definite */
+ 		{
+ 		  len2 += len4;
+-		  _asn1_set_value_octet (p, der + counter, len2 + len3);
++
++	          DECR_LEN(ider_len, len4+len3);
++		  _asn1_set_value_lv (p, der + counter, len2 + len3);
+ 		  counter += len2 + len3;
+ 		}
+-	      else
++	      else /* == -1 */
+ 		{		/* indefinite length */
++		  ider_len += len2; /* undo DECR_LEN */
++
++		  if (counter == 0)
++		    {
++		      result = ASN1_DER_ERROR;
++                      warn();
++		      goto cleanup;
++		    }
++
+ 		  /* Check indefinite lenth method in an EXPLICIT TAG */
+ 		  if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+ 		    indefinite = 1;
+ 		  else
+ 		    indefinite = 0;
+ 
+-		  len2 = len - counter;
+-		  ris =
+-		    _asn1_get_indefinite_length_string (der + counter, &len2);
+-		  if (ris != ASN1_SUCCESS)
++		  result =
++		    _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
++		  if (result != ASN1_SUCCESS)
+ 		    {
+-		      asn1_delete_structure (element);
+-		      return ris;
+-		    }
++                      warn();
++  		      goto cleanup;
++  		    }
+ 
+-		  _asn1_set_value_octet (p, der + counter, len2);
++	          DECR_LEN(ider_len, len2);
++		  _asn1_set_value_lv (p, der + counter, len2);
+ 		  counter += len2;
+ 
+ 		  /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+ 		     an indefinite length method. */
+ 		  if (indefinite)
+ 		    {
++	              DECR_LEN(ider_len, 2);
+ 		      if (!der[counter] && !der[counter + 1])
+ 			{
+ 			  counter += 2;
+ 			}
+ 		      else
+ 			{
+-			  asn1_delete_structure (element);
+-			  return ASN1_DER_ERROR;
++			  result = ASN1_DER_ERROR;
++                          warn();
++			  goto cleanup;
+ 			}
+ 		    }
+ 		}
+@@ -1332,13 +1548,18 @@
+ 
+   _asn1_delete_not_used (*element);
+ 
+-  if (counter != len)
++  if (ider_len != 0)
+     {
+-      asn1_delete_structure (element);
+-      return ASN1_DER_ERROR;
++      warn();
++      result = ASN1_DER_ERROR;
++      goto cleanup;
+     }
+ 
+   return ASN1_SUCCESS;
++
++cleanup:
++  asn1_delete_structure (element);
++  return result;
+ }
+ 
+ #define FOUND        1
+@@ -1360,52 +1581,55 @@
+  * asn1_create_element().  The DER vector must contain the encoding
+  * string of the whole @STRUCTURE.  If an error occurs during the
+  * decoding procedure, the *@STRUCTURE is deleted and set equal to
+- * %ASN1_TYPE_EMPTY.
++ * %NULL.
++ *
++ * This function is deprecated and may just be an alias to asn1_der_decoding
++ * in future versions. Use asn1_der_decoding() instead.
+  *
+  * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
+- *   if ELEMENT is %ASN1_TYPE_EMPTY or @elementName == NULL, and
++ *   if ELEMENT is %NULL or @elementName == NULL, and
+  *   %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't
+  *   match the structure @structure (*ELEMENT deleted).
+  **/
+-asn1_retCode
++int
+ asn1_der_decoding_element (ASN1_TYPE * structure, const char *elementName,
+ 			   const void *ider, int len, char *errorDescription)
+ {
+-  ASN1_TYPE node, p, p2, p3, nodeFound = ASN1_TYPE_EMPTY;
++  ASN1_TYPE node, p, p2, p3, nodeFound = NULL;
+   char temp[128], currentName[ASN1_MAX_NAME_SIZE * 10], *dot_p, *char_p;
+   int nameLen = ASN1_MAX_NAME_SIZE * 10 - 1, state;
+   int counter, len2, len3, len4, move, ris, tlen;
+-  unsigned char class, *temp2;
++  unsigned char class;
+   unsigned long tag;
+   int indefinite, result;
+   const unsigned char *der = ider;
+ 
+   node = *structure;
+ 
+-  if (node == ASN1_TYPE_EMPTY)
++  if (node == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   if (elementName == NULL)
+     {
+-      asn1_delete_structure (structure);
+-      return ASN1_ELEMENT_NOT_FOUND;
++      result = ASN1_ELEMENT_NOT_FOUND;
++      goto cleanup;
+     }
+ 
+   if (node->type & CONST_OPTION)
+     {
+-      asn1_delete_structure (structure);
+-      return ASN1_GENERIC_ERROR;
++      result = ASN1_GENERIC_ERROR;
++      goto cleanup;
+     }
+ 
+-  if ((*structure)->name)
++  if ((*structure)->name[0] != 0)
+     {				/* Has *structure got a name? */
+       nameLen -= strlen ((*structure)->name);
+       if (nameLen > 0)
+ 	strcpy (currentName, (*structure)->name);
+       else
+ 	{
+-	  asn1_delete_structure (structure);
+-	  return ASN1_MEM_ERROR;
++	  result = ASN1_MEM_ERROR;
++	  goto cleanup;
+ 	}
+       if (!(strcmp (currentName, elementName)))
+ 	{
+@@ -1444,7 +1668,7 @@
+ 	  if (p->type & CONST_SET)
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
+ 	      if (counter == len2)
+ 		{
+ 		  p = p2;
+@@ -1453,31 +1677,17 @@
+ 		}
+ 	      else if (counter > len2)
+ 		{
+-		  asn1_delete_structure (structure);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
+ 		}
+ 	      p2 = p2->down;
+ 	      while (p2)
+ 		{
+ 		  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ 		    {
+-		      if (type_field (p2->type) != TYPE_CHOICE)
+-			ris =
+-			  _asn1_extract_tag_der (p2, der + counter,
++		      ris =
++			  extract_tag_der_recursive (p2, der + counter,
+ 						 len - counter, &len2);
+-		      else
+-			{
+-			  p3 = p2->down;
+-			  while (p3)
+-			    {
+-			      ris =
+-				_asn1_extract_tag_der (p3, der + counter,
+-						       len - counter, &len2);
+-			      if (ris == ASN1_SUCCESS)
+-				break;
+-			      p3 = p3->right;
+-			    }
+-			}
+ 		      if (ris == ASN1_SUCCESS)
+ 			{
+ 			  p2->type &= ~CONST_NOT_USED;
+@@ -1489,15 +1699,15 @@
+ 		}
+ 	      if (p2 == NULL)
+ 		{
+-		  asn1_delete_structure (structure);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
+ 		}
+ 	    }
+ 
+ 	  if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
+ 	      if (counter == len2)
+ 		{
+ 		  if (p->right)
+@@ -1528,17 +1738,13 @@
+ 		    ris = ASN1_DER_ERROR;
+ 		  if (ris == ASN1_SUCCESS)
+ 		    {
+-		      while (p->down->right)
+-			{
+-			  p2 = p->down->right;
+-			  asn1_delete_structure (&p2);
+-			}
++		      delete_unneeded_choice_fields(p->down);
+ 		      break;
+ 		    }
+ 		  else if (ris == ASN1_ERROR_TYPE_ANY)
+ 		    {
+-		      asn1_delete_structure (structure);
+-		      return ASN1_ERROR_TYPE_ANY;
++		      result = ASN1_ERROR_TYPE_ANY;
++		      goto cleanup;
+ 		    }
+ 		  else
+ 		    {
+@@ -1551,18 +1757,18 @@
+ 		{
+ 		  if (!(p->type & CONST_OPTION))
+ 		    {
+-		      asn1_delete_structure (structure);
+-		      return ASN1_DER_ERROR;
++		      result = ASN1_DER_ERROR;
++		      goto cleanup;
+ 		    }
+ 		}
+-	      else
++	      else if (type_field (p->type) != TYPE_CHOICE)
+ 		p = p->down;
+ 	    }
+ 
+ 	  if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT))
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
+ 	      if (counter > len2)
+ 		ris = ASN1_TAG_ERROR;
+ 	    }
+@@ -1587,8 +1793,8 @@
+ 		  if (errorDescription != NULL)
+ 		    _asn1_error_description_tag_error (p, errorDescription);
+ 
+-		  asn1_delete_structure (structure);
+-		  return ASN1_TAG_ERROR;
++		  result = ASN1_TAG_ERROR;
++		  goto cleanup;
+ 		}
+ 	    }
+ 	  else
+@@ -1602,8 +1808,8 @@
+ 	    case TYPE_NULL:
+ 	      if (der[counter])
+ 		{
+-		  asn1_delete_structure (structure);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
+ 		}
+ 
+ 	      if (p == nodeFound)
+@@ -1615,8 +1821,8 @@
+ 	    case TYPE_BOOLEAN:
+ 	      if (der[counter++] != 1)
+ 		{
+-		  asn1_delete_structure (structure);
+-		  return ASN1_DER_ERROR;
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
+ 		}
+ 
+ 	      if (state == FOUND)
+@@ -1640,11 +1846,18 @@
+ 	      len2 =
+ 		asn1_get_length_der (der + counter, len - counter, &len3);
+ 	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
++		}
++
+ 	      if (state == FOUND)
+ 		{
+ 		  if (len3 + len2 > len - counter)
+-		    return ASN1_DER_ERROR;
++		    {
++		      result = ASN1_DER_ERROR;
++		      goto cleanup;
++		    }
+ 		  _asn1_set_value (p, der + counter, len3 + len2);
+ 
+ 		  if (p == nodeFound)
+@@ -1660,9 +1873,7 @@
+ 		    _asn1_get_objectid_der (der + counter, len - counter,
+ 					    &len2, temp, sizeof (temp));
+ 		  if (result != ASN1_SUCCESS)
+-		    {
+-		      return result;
+-		    }
++		    goto cleanup;
+ 
+ 		  tlen = strlen (temp);
+ 
+@@ -1677,24 +1888,25 @@
+ 		  len2 =
+ 		    asn1_get_length_der (der + counter, len - counter, &len3);
+ 		  if (len2 < 0)
+-		    return ASN1_DER_ERROR;
++		    {
++		      result = ASN1_DER_ERROR;
++		      goto cleanup;
++		    }
+ 		  len2 += len3;
+ 		}
+ 
+ 	      counter += len2;
+ 	      move = RIGHT;
+ 	      break;
+-	    case TYPE_TIME:
++	    case TYPE_GENERALIZED_TIME:
++	    case TYPE_UTC_TIME:
+ 	      if (state == FOUND)
+ 		{
+ 		  result =
+ 		    _asn1_get_time_der (der + counter, len - counter, &len2,
+ 					temp, sizeof (temp) - 1);
+ 		  if (result != ASN1_SUCCESS)
+-		    {
+-		      asn1_delete_structure (structure);
+-		      return result;
+-		    }
++		    goto cleanup;
+ 
+ 		  tlen = strlen (temp);
+ 		  if (tlen > 0)
+@@ -1708,7 +1920,10 @@
+ 		  len2 =
+ 		    asn1_get_length_der (der + counter, len - counter, &len3);
+ 		  if (len2 < 0)
+-		    return ASN1_DER_ERROR;
++		    {
++		      result = ASN1_DER_ERROR;
++		      goto cleanup;
++		    }
+ 		  len2 += len3;
+ 		}
+ 
+@@ -1716,47 +1931,46 @@
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_OCTET_STRING:
+-	      len3 = len - counter;
+ 	      if (state == FOUND)
+ 		{
+-		  ris = _asn1_get_octet_string (der + counter, p, &len3);
++		  result = _asn1_get_octet_string (p, der + counter, len-counter, &len3);
+ 		  if (p == nodeFound)
+ 		    state = EXIT;
+ 		}
+ 	      else
+-		ris = _asn1_get_octet_string (der + counter, NULL, &len3);
++		result = _asn1_get_octet_string (NULL, der + counter, len-counter, &len3);
++
++	      if (result != ASN1_SUCCESS)
++		goto cleanup;
+ 
+-	      if (ris != ASN1_SUCCESS)
+-		return ris;
+ 	      counter += len3;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_GENERALSTRING:
++	    case TYPE_NUMERIC_STRING:
++	    case TYPE_IA5_STRING:
++	    case TYPE_TELETEX_STRING:
++	    case TYPE_PRINTABLE_STRING:
++	    case TYPE_UNIVERSAL_STRING:
++	    case TYPE_BMP_STRING:
++	    case TYPE_UTF8_STRING:
++	    case TYPE_VISIBLE_STRING:
++	    case TYPE_BIT_STRING:
+ 	      len2 =
+ 		asn1_get_length_der (der + counter, len - counter, &len3);
+ 	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      if (state == FOUND)
+ 		{
+-		  if (len3 + len2 > len - counter)
+-		    return ASN1_DER_ERROR;
+-		  _asn1_set_value (p, der + counter, len3 + len2);
+-
+-		  if (p == nodeFound)
+-		    state = EXIT;
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
+ 		}
+-	      counter += len3 + len2;
+-	      move = RIGHT;
+-	      break;
+-	    case TYPE_BIT_STRING:
+-	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
+-	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
++
+ 	      if (state == FOUND)
+ 		{
+ 		  if (len3 + len2 > len - counter)
+-		    return ASN1_DER_ERROR;
++		    {
++		      result = ASN1_DER_ERROR;
++		      goto cleanup;
++		    }
+ 		  _asn1_set_value (p, der + counter, len3 + len2);
+ 
+ 		  if (p == nodeFound)
+@@ -1769,14 +1983,14 @@
+ 	    case TYPE_SET:
+ 	      if (move == UP)
+ 		{
+-		  len2 = strtol (p->value, NULL, 10);
++		  len2 = _asn1_strtol (p->value, NULL, 10);
+ 		  _asn1_set_value (p, NULL, 0);
+ 		  if (len2 == -1)
+ 		    {		/* indefinite length method */
+ 		      if ((der[counter]) || der[counter + 1])
+ 			{
+-			  asn1_delete_structure (structure);
+-			  return ASN1_DER_ERROR;
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
+ 			}
+ 		      counter += 2;
+ 		    }
+@@ -1784,8 +1998,8 @@
+ 		    {		/* definite length method */
+ 		      if (len2 != counter)
+ 			{
+-			  asn1_delete_structure (structure);
+-			  return ASN1_DER_ERROR;
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
+ 			}
+ 		    }
+ 		  if (p == nodeFound)
+@@ -1800,7 +2014,10 @@
+ 			asn1_get_length_der (der + counter, len - counter,
+ 					     &len2);
+ 		      if (len3 < 0)
+-			return ASN1_DER_ERROR;
++			{
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
++			}
+ 		      counter += len2 + len3;
+ 		      move = RIGHT;
+ 		    }
+@@ -1810,7 +2027,10 @@
+ 			asn1_get_length_der (der + counter, len - counter,
+ 					     &len2);
+ 		      if (len3 < 0)
+-			return ASN1_DER_ERROR;
++			{
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
++			}
+ 		      counter += len2;
+ 		      if (len3 > 0)
+ 			{
+@@ -1849,7 +2069,7 @@
+ 	    case TYPE_SET_OF:
+ 	      if (move == UP)
+ 		{
+-		  len2 = strtol (p->value, NULL, 10);
++		  len2 = _asn1_strtol (p->value, NULL, 10);
+ 		  if (len2 > counter)
+ 		    {
+ 		      _asn1_append_sequence_set (p);
+@@ -1862,8 +2082,8 @@
+ 		  _asn1_set_value (p, NULL, 0);
+ 		  if (len2 != counter)
+ 		    {
+-		      asn1_delete_structure (structure);
+-		      return ASN1_DER_ERROR;
++		      result = ASN1_DER_ERROR;
++		      goto cleanup;
+ 		    }
+ 
+ 		  if (p == nodeFound)
+@@ -1877,7 +2097,10 @@
+ 			asn1_get_length_der (der + counter, len - counter,
+ 					     &len2);
+ 		      if (len3 < 0)
+-			return ASN1_DER_ERROR;
++			{
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
++			}
+ 		      counter += len2 + len3;
+ 		      move = RIGHT;
+ 		    }
+@@ -1887,7 +2110,10 @@
+ 			asn1_get_length_der (der + counter, len - counter,
+ 					     &len2);
+ 		      if (len3 < 0)
+-			return ASN1_DER_ERROR;
++			{
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
++			}
+ 		      counter += len2;
+ 		      if (len3)
+ 			{
+@@ -1898,7 +2124,8 @@
+ 			    _asn1_set_value (p, temp, tlen + 1);
+ 			  p2 = p->down;
+ 			  while ((type_field (p2->type) == TYPE_TAG)
+-				 || (type_field (p2->type) == TYPE_SIZE))
++				 || (type_field (p2->type) ==
++				     TYPE_SIZE))
+ 			    p2 = p2->right;
+ 			  if (p2->right == NULL)
+ 			    _asn1_append_sequence_set (p);
+@@ -1913,23 +2140,32 @@
+ 	      if (asn1_get_tag_der
+ 		  (der + counter, len - counter, &class, &len2,
+ 		   &tag) != ASN1_SUCCESS)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
++		}
++
+ 	      if (counter + len2 > len)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
++		}
+ 
+ 	      len4 =
+ 		asn1_get_length_der (der + counter + len2,
+ 				     len - counter - len2, &len3);
+ 	      if (len4 < -1)
+-		return ASN1_DER_ERROR;
++		{
++		  result = ASN1_DER_ERROR;
++		  goto cleanup;
++		}
+ 
+ 	      if (len4 != -1)
+ 		{
+ 		  len2 += len4;
+ 		  if (state == FOUND)
+ 		    {
+-		      _asn1_set_value_octet (p, der + counter, len2 + len3);
+-		      temp2 = NULL;
++		      _asn1_set_value_lv (p, der + counter, len2 + len3);
+ 
+ 		      if (p == nodeFound)
+ 			state = EXIT;
+@@ -1944,18 +2180,14 @@
+ 		  else
+ 		    indefinite = 0;
+ 
+-		  len2 = len - counter;
+-		  ris =
+-		    _asn1_get_indefinite_length_string (der + counter, &len2);
+-		  if (ris != ASN1_SUCCESS)
+-		    {
+-		      asn1_delete_structure (structure);
+-		      return ris;
+-		    }
++		  result =
++		    _asn1_get_indefinite_length_string (der + counter, len-counter, &len2);
++		  if (result != ASN1_SUCCESS)
++		    goto cleanup;
+ 
+ 		  if (state == FOUND)
+ 		    {
+-		      _asn1_set_value_octet (p, der + counter, len2);
++		      _asn1_set_value_lv (p, der + counter, len2);
+ 
+ 		      if (p == nodeFound)
+ 			state = EXIT;
+@@ -1973,8 +2205,8 @@
+ 			}
+ 		      else
+ 			{
+-			  asn1_delete_structure (structure);
+-			  return ASN1_DER_ERROR;
++			  result = ASN1_DER_ERROR;
++			  goto cleanup;
+ 			}
+ 		    }
+ 		}
+@@ -2007,8 +2239,8 @@
+ 		    }
+ 		  else
+ 		    {
+-		      asn1_delete_structure (structure);
+-		      return ASN1_MEM_ERROR;
++		      result = ASN1_MEM_ERROR;
++		      goto cleanup;
+ 		    }
+ 		  if (!(strcmp (currentName, elementName)))
+ 		    {
+@@ -2050,8 +2282,8 @@
+ 		    strcat (currentName, p->name);
+ 		  else
+ 		    {
+-		      asn1_delete_structure (structure);
+-		      return ASN1_MEM_ERROR;
++		      result = ASN1_MEM_ERROR;
++		      goto cleanup;
+ 		    }
+ 
+ 		  if (!(strcmp (currentName, elementName)))
+@@ -2105,18 +2337,22 @@
+ 
+   if (counter > len)
+     {
+-      asn1_delete_structure (structure);
+-      return ASN1_DER_ERROR;
++      result = ASN1_DER_ERROR;
++      goto cleanup;
+     }
+ 
+   return ASN1_SUCCESS;
++
++cleanup:
++  asn1_delete_structure (structure);
++  return result;
+ }
+ 
+ /**
+  * asn1_der_decoding_startEnd:
+  * @element: pointer to an ASN1 element
+  * @ider: vector that contains the DER encoding.
+- * @len: number of bytes of *@ider: @ider[0]..@ider[len-1]
++ * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]
+  * @name_element: an element of NAME structure.
+  * @start: the position of the first byte of NAME_ELEMENT decoding
+  *   (@ider[*start])
+@@ -2137,20 +2373,20 @@
+  *   element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding
+  *   doesn't match the structure ELEMENT.
+  **/
+-asn1_retCode
+-asn1_der_decoding_startEnd (ASN1_TYPE element, const void *ider, int len,
++int
++asn1_der_decoding_startEnd (ASN1_TYPE element, const void *ider, int ider_len,
+ 			    const char *name_element, int *start, int *end)
+ {
+-  ASN1_TYPE node, node_to_find, p, p2, p3;
++  ASN1_TYPE node, node_to_find, p, p2;
+   int counter, len2, len3, len4, move, ris;
+   unsigned char class;
+   unsigned long tag;
+-  int indefinite;
++  int indefinite, result = ASN1_DER_ERROR;
+   const unsigned char *der = ider;
+ 
+   node = element;
+ 
+-  if (node == ASN1_TYPE_EMPTY)
++  if (node == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   node_to_find = asn1_find_node (node, name_element);
+@@ -2161,7 +2397,7 @@
+   if (node_to_find == node)
+     {
+       *start = 0;
+-      *end = len - 1;
++      *end = ider_len - 1;
+       return ASN1_SUCCESS;
+     }
+ 
+@@ -2173,6 +2409,9 @@
+   p = node;
+   while (1)
+     {
++      if (p == NULL)
++	return ASN1_DER_ERROR;
++
+       ris = ASN1_SUCCESS;
+ 
+       if (move != UP)
+@@ -2180,14 +2419,21 @@
+ 	  if (p->type & CONST_SET)
+ 	    {
+ 	      p2 = _asn1_find_up (p);
+-	      len2 = strtol (p2->value, NULL, 10);
++	      if (p2 == NULL)
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
++
++	      len2 = _asn1_strtol (p2->value, NULL, 10);
+ 	      if (len2 == -1)
+ 		{
+-		  if (!der[counter] && !der[counter + 1])
++		  if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
+ 		    {
+ 		      p = p2;
+ 		      move = UP;
+ 		      counter += 2;
++		      DECR_LEN(ider_len, 2);
+ 		      continue;
+ 		    }
+ 		}
+@@ -2198,23 +2444,20 @@
+ 		  continue;
+ 		}
+ 	      else if (counter > len2)
+-		return ASN1_DER_ERROR;
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
++
+ 	      p2 = p2->down;
++
+ 	      while (p2)
+ 		{
+ 		  if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED))
+ 		    {		/* CONTROLLARE */
+-		      if (type_field (p2->type) != TYPE_CHOICE)
+-			ris =
+-			  _asn1_extract_tag_der (p2, der + counter,
+-						 len - counter, &len2);
+-		      else
+-			{
+-			  p3 = p2->down;
+-			  ris =
+-			    _asn1_extract_tag_der (p3, der + counter,
+-						   len - counter, &len2);
+-			}
++		      ris =
++			  extract_tag_der_recursive (p2, der + counter,
++						 ider_len, &len2);
+ 		      if (ris == ASN1_SUCCESS)
+ 			{
+ 			  p2->type &= ~CONST_NOT_USED;
+@@ -2225,7 +2468,10 @@
+ 		  p2 = p2->right;
+ 		}
+ 	      if (p2 == NULL)
+-		return ASN1_DER_ERROR;
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
+ 	    }
+ 
+ 	  if (p == node_to_find)
+@@ -2234,8 +2480,14 @@
+ 	  if (type_field (p->type) == TYPE_CHOICE)
+ 	    {
+ 	      p = p->down;
++	      if (p == NULL)
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
++
+ 	      ris =
+-		_asn1_extract_tag_der (p, der + counter, len - counter,
++		_asn1_extract_tag_der (p, der + counter, ider_len,
+ 				       &len2);
+ 	      if (p == node_to_find)
+ 		*start = counter;
+@@ -2243,7 +2495,7 @@
+ 
+ 	  if (ris == ASN1_SUCCESS)
+ 	    ris =
+-	      _asn1_extract_tag_der (p, der + counter, len - counter, &len2);
++	      _asn1_extract_tag_der (p, der + counter, ider_len, &len2);
+ 	  if (ris != ASN1_SUCCESS)
+ 	    {
+ 	      if (p->type & CONST_OPTION)
+@@ -2257,11 +2509,15 @@
+ 		}
+ 	      else
+ 		{
++		  warn();
+ 		  return ASN1_TAG_ERROR;
+ 		}
+ 	    }
+ 	  else
+-	    counter += len2;
++	    {
++	      DECR_LEN(ider_len, len2);
++	      counter += len2;
++	    }
+ 	}
+ 
+       if (ris == ASN1_SUCCESS)
+@@ -2269,63 +2525,63 @@
+ 	  switch (type_field (p->type))
+ 	    {
+ 	    case TYPE_NULL:
++	       DECR_LEN(ider_len, 1);
++
+ 	      if (der[counter])
+-		return ASN1_DER_ERROR;
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
+ 	      counter++;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_BOOLEAN:
+-	      if (der[counter++] != 1)
+-		return ASN1_DER_ERROR;
+-	      counter++;
+-	      move = RIGHT;
+-	      break;
+-	    case TYPE_INTEGER:
+-	    case TYPE_ENUMERATED:
+-	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
+-	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      counter += len3 + len2;
+-	      move = RIGHT;
+-	      break;
+-	    case TYPE_OBJECT_ID:
+-	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
+-	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      counter += len2 + len3;
+-	      move = RIGHT;
+-	      break;
+-	    case TYPE_TIME:
+-	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
+-	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      counter += len2 + len3;
++              DECR_LEN(ider_len, 2);
++
++	      if (der[counter] != 1)
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
++
++	      counter += 2;
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_OCTET_STRING:
+-	      len3 = len - counter;
+-	      ris = _asn1_get_octet_string (der + counter, NULL, &len3);
++	      ris = _asn1_get_octet_string (NULL, der + counter, ider_len, &len3);
+ 	      if (ris != ASN1_SUCCESS)
+-		return ris;
++	        {
++		  warn();
++		  return ris;
++		}
++              DECR_LEN(ider_len, len3);
+ 	      counter += len3;
+ 	      move = RIGHT;
+ 	      break;
++	    case TYPE_UTC_TIME:
++	    case TYPE_GENERALIZED_TIME:
++	    case TYPE_OBJECT_ID:
++	    case TYPE_INTEGER:
++	    case TYPE_ENUMERATED:
+ 	    case TYPE_GENERALSTRING:
+-	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
+-	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
+-	      counter += len3 + len2;
+-	      move = RIGHT;
+-	      break;
++	    case TYPE_NUMERIC_STRING:
++	    case TYPE_IA5_STRING:
++	    case TYPE_TELETEX_STRING:
++	    case TYPE_PRINTABLE_STRING:
++	    case TYPE_UNIVERSAL_STRING:
++	    case TYPE_BMP_STRING:
++	    case TYPE_UTF8_STRING:
++	    case TYPE_VISIBLE_STRING:
+ 	    case TYPE_BIT_STRING:
+ 	      len2 =
+-		asn1_get_length_der (der + counter, len - counter, &len3);
++		asn1_get_length_der (der + counter, ider_len, &len3);
+ 	      if (len2 < 0)
+-		return ASN1_DER_ERROR;
++	        {
++		  warn();
++		  return ASN1_DER_ERROR;
++		}
++
++              DECR_LEN(ider_len, len3 + len2);
+ 	      counter += len3 + len2;
+ 	      move = RIGHT;
+ 	      break;
+@@ -2334,10 +2590,16 @@
+ 	      if (move != UP)
+ 		{
+ 		  len3 =
+-		    asn1_get_length_der (der + counter, len - counter, &len2);
++		    asn1_get_length_der (der + counter, ider_len, &len2);
+ 		  if (len3 < -1)
+-		    return ASN1_DER_ERROR;
++		    {
++  		      warn();
++		      return ASN1_DER_ERROR;
++		    }
++
++                  DECR_LEN(ider_len, len2);
+ 		  counter += len2;
++
+ 		  if (len3 == 0)
+ 		    move = RIGHT;
+ 		  else
+@@ -2345,8 +2607,11 @@
+ 		}
+ 	      else
+ 		{
+-		  if (!der[counter] && !der[counter + 1])	/* indefinite length method */
+-		    counter += 2;
++		  if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])	/* indefinite length method */
++		    {
++		      counter += 2;
++		      DECR_LEN(ider_len, 2);
++		    }
+ 		  move = RIGHT;
+ 		}
+ 	      break;
+@@ -2355,13 +2620,26 @@
+ 	      if (move != UP)
+ 		{
+ 		  len3 =
+-		    asn1_get_length_der (der + counter, len - counter, &len2);
++		    asn1_get_length_der (der + counter, ider_len, &len2);
+ 		  if (len3 < -1)
+-		    return ASN1_DER_ERROR;
++		    {
++  		      warn();
++		      return ASN1_DER_ERROR;
++		    }
++
++                  DECR_LEN(ider_len, len2);
+ 		  counter += len2;
+-		  if ((len3 == -1) && !der[counter] && !der[counter + 1])
+-		    counter += 2;
+-		  else if (len3)
++
++		  if (len3 == -1)
++		    {
++		       if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])
++		         {
++  		           DECR_LEN(ider_len, 2);
++		           counter += 2;
++		         }
++		    }
++
++		  if (len3)
+ 		    {
+ 		      p2 = p->down;
+ 		      while ((type_field (p2->type) == TYPE_TAG) ||
+@@ -2372,52 +2650,79 @@
+ 		}
+ 	      else
+ 		{
+-		  if (!der[counter] && !der[counter + 1])	/* indefinite length method */
+-		    counter += 2;
++		  if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1])	/* indefinite length method */
++		    {
++		      DECR_LEN(ider_len, 2);
++		      counter += 2;
++		    }
+ 		}
+ 	      move = RIGHT;
+ 	      break;
+ 	    case TYPE_ANY:
+ 	      if (asn1_get_tag_der
+-		  (der + counter, len - counter, &class, &len2,
++		  (der + counter, ider_len, &class, &len2,
+ 		   &tag) != ASN1_SUCCESS)
+-		return ASN1_DER_ERROR;
+-	      if (counter + len2 > len)
+-		return ASN1_DER_ERROR;
++		 {
++  		    warn();
++		    return ASN1_DER_ERROR;
++		 }
++
++	      DECR_LEN(ider_len, len2);
+ 
+ 	      len4 =
+ 		asn1_get_length_der (der + counter + len2,
+-				     len - counter - len2, &len3);
++				     ider_len, &len3);
+ 	      if (len4 < -1)
+-		return ASN1_DER_ERROR;
++	        {
++ 	          warn();
++		  return ASN1_DER_ERROR;
++		}
+ 
+ 	      if (len4 != -1)
+ 		{
+-		  counter += len2 + len4 + len3;
++		  DECR_LEN(ider_len, len3 + len4);
++		  counter += len2 + len3 + len4;
+ 		}
+ 	      else
+ 		{		/* indefinite length */
+ 		  /* Check indefinite lenth method in an EXPLICIT TAG */
++		  ider_len += len2; /* undo DECR_LEN */
++
++		  if (counter == 0)
++		    {
++		      result = ASN1_DER_ERROR;
++                      warn();
++		      goto cleanup;
++		    }
++
+ 		  if ((p->type & CONST_TAG) && (der[counter - 1] == 0x80))
+ 		    indefinite = 1;
+ 		  else
+ 		    indefinite = 0;
+ 
+-		  len2 = len - counter;
+ 		  ris =
+-		    _asn1_get_indefinite_length_string (der + counter, &len2);
++		    _asn1_get_indefinite_length_string (der + counter, ider_len, &len2);
+ 		  if (ris != ASN1_SUCCESS)
+-		    return ris;
++		    {
++ 	              warn();
++		      return ris;
++		    }
+ 		  counter += len2;
++		  DECR_LEN(ider_len, len2);
+ 
+ 		  /* Check if a couple of 0x00 are present due to an EXPLICIT TAG with
+ 		     an indefinite length method. */
+ 		  if (indefinite)
+ 		    {
++		      DECR_LEN(ider_len, 2);
++
+ 		      if (!der[counter] && !der[counter + 1])
+ 			counter += 2;
+ 		      else
+-			return ASN1_DER_ERROR;
++		        {
++ 	                  warn();
++			  return ASN1_DER_ERROR;
++			}
+ 		    }
+ 		}
+ 	      move = RIGHT;
+@@ -2455,7 +2760,11 @@
+ 	p = _asn1_find_up (p);
+     }
+ 
++  warn();
+   return ASN1_ELEMENT_NOT_FOUND;
++
++cleanup:
++  return result;
+ }
+ 
+ /**
+@@ -2474,21 +2783,21 @@
+  *   problem in OBJECT_ID -> TYPE association, or other error codes
+  *   depending on DER decoding.
+  **/
+-asn1_retCode
++int
+ asn1_expand_any_defined_by (ASN1_TYPE definitions, ASN1_TYPE * element)
+ {
+-  char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1],
++  char name[2 * ASN1_MAX_NAME_SIZE + 1],
+     value[ASN1_MAX_NAME_SIZE];
+-  asn1_retCode retCode = ASN1_SUCCESS, result;
++  int retCode = ASN1_SUCCESS, result;
+   int len, len2, len3;
+-  ASN1_TYPE p, p2, p3, aux = ASN1_TYPE_EMPTY;
++  ASN1_TYPE p, p2, p3, aux = NULL;
+   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
++  const char *definitionsName;
+ 
+-  if ((definitions == ASN1_TYPE_EMPTY) || (*element == ASN1_TYPE_EMPTY))
++  if ((definitions == NULL) || (*element == NULL))
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+-  strcpy (definitionsName, definitions->name);
+-  strcat (definitionsName, ".");
++  definitionsName = definitions->name;
+ 
+   p = *element;
+   while (p)
+@@ -2521,7 +2830,7 @@
+ 	      p3 = p3->down;
+ 	      while (p3)
+ 		{
+-		  if ((p3->name) && !(strcmp (p3->name, p2->name)))
++		  if (!(strcmp (p3->name, p2->name)))
+ 		    break;
+ 		  p3 = p3->right;
+ 		}
+@@ -2543,13 +2852,13 @@
+ 
+ 		  while (p3)
+ 		    {
+-		      if ((p3->name) && !(strcmp (p3->name, p2->name)))
++		      if (!(strcmp (p3->name, p2->name)))
+ 			break;
+ 		      p3 = p3->right;
+ 		    }
+ 
+-		  if ((!p3) || (type_field (p3->type) != TYPE_OBJECT_ID) ||
+-		      (p3->value == NULL))
++		  if ((!p3) || (type_field (p3->type) != TYPE_OBJECT_ID)
++		      || (p3->value == NULL))
+ 		    {
+ 		      retCode = ASN1_ERROR_TYPE_ANY;
+ 		      break;
+@@ -2563,15 +2872,14 @@
+ 		  if ((type_field (p2->type) == TYPE_OBJECT_ID) &&
+ 		      (p2->type & CONST_ASSIGN))
+ 		    {
+-		      strcpy (name, definitionsName);
+-		      strcat (name, p2->name);
++		      snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name);
+ 
+ 		      len = ASN1_MAX_NAME_SIZE;
+ 		      result =
+ 			asn1_read_value (definitions, name, value, &len);
+ 
+ 		      if ((result == ASN1_SUCCESS)
+-			  && (!strcmp (p3->value, value)))
++			  && (!_asn1_strcmp (p3->value, value)))
+ 			{
+ 			  p2 = p2->right;	/* pointer to the structure to
+ 						   use for expansion */
+@@ -2580,14 +2888,13 @@
+ 
+ 			  if (p2)
+ 			    {
+-			      strcpy (name, definitionsName);
+-			      strcat (name, p2->name);
++			      snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name);
+ 
+ 			      result =
+ 				asn1_create_element (definitions, name, &aux);
+ 			      if (result == ASN1_SUCCESS)
+ 				{
+-				  _asn1_set_name (aux, p->name);
++				  _asn1_cpy_name (aux, p);
+ 				  len2 =
+ 				    asn1_get_length_der (p->value,
+ 							 p->value_len, &len3);
+@@ -2608,7 +2915,7 @@
+ 				      if (result == ASN1_SUCCESS)
+ 					{
+ 					  p = aux;
+-					  aux = ASN1_TYPE_EMPTY;
++					  aux = NULL;
+ 					  break;
+ 					}
+ 				      else
+@@ -2704,22 +3011,22 @@
+  *   %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to
+  *   use for expansion, or other errors depending on DER decoding.
+  **/
+-asn1_retCode
++int
+ asn1_expand_octet_string (ASN1_TYPE definitions, ASN1_TYPE * element,
+ 			  const char *octetName, const char *objectName)
+ {
+   char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE];
+-  asn1_retCode retCode = ASN1_SUCCESS, result;
++  int retCode = ASN1_SUCCESS, result;
+   int len, len2, len3;
+-  ASN1_TYPE p2, aux = ASN1_TYPE_EMPTY;
+-  ASN1_TYPE octetNode = ASN1_TYPE_EMPTY, objectNode = ASN1_TYPE_EMPTY;
++  ASN1_TYPE p2, aux = NULL;
++  ASN1_TYPE octetNode = NULL, objectNode = NULL;
+   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
+ 
+-  if ((definitions == ASN1_TYPE_EMPTY) || (*element == ASN1_TYPE_EMPTY))
++  if ((definitions == NULL) || (*element == NULL))
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   octetNode = asn1_find_node (*element, octetName);
+-  if (octetNode == ASN1_TYPE_EMPTY)
++  if (octetNode == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+   if (type_field (octetNode->type) != TYPE_OCTET_STRING)
+     return ASN1_ELEMENT_NOT_FOUND;
+@@ -2727,7 +3034,7 @@
+     return ASN1_VALUE_NOT_FOUND;
+ 
+   objectNode = asn1_find_node (*element, objectName);
+-  if (objectNode == ASN1_TYPE_EMPTY)
++  if (objectNode == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   if (type_field (objectNode->type) != TYPE_OBJECT_ID)
+@@ -2752,7 +3059,7 @@
+ 	  result = asn1_read_value (definitions, name, value, &len);
+ 
+ 	  if ((result == ASN1_SUCCESS)
+-	      && (!strcmp (objectNode->value, value)))
++	      && (!_asn1_strcmp (objectNode->value, value)))
+ 	    {
+ 
+ 	      p2 = p2->right;	/* pointer to the structure to
+@@ -2769,7 +3076,7 @@
+ 		  result = asn1_create_element (definitions, name, &aux);
+ 		  if (result == ASN1_SUCCESS)
+ 		    {
+-		      _asn1_set_name (aux, octetNode->name);
++		      _asn1_cpy_name (aux, octetNode);
+ 		      len2 =
+ 			asn1_get_length_der (octetNode->value,
+ 					     octetNode->value_len, &len3);
+@@ -2788,7 +3095,7 @@
+ 			  result = asn1_delete_structure (&octetNode);
+ 			  if (result == ASN1_SUCCESS)
+ 			    {
+-			      aux = ASN1_TYPE_EMPTY;
++			      aux = NULL;
+ 			      break;
+ 			    }
+ 			  else
+@@ -2827,3 +3134,61 @@
+ 
+   return retCode;
+ }
++
++/**
++ * asn1_decode_simple_der:
++ * @etype: The type of the string to be encoded (TYPE_)
++ * @der: the encoded string
++ * @der_len: the bytes of the encoded string
++ * @str: a pointer to the data
++ * @str_len: the length of the data
++ *
++ * Decodes a simple DER encoded type (e.g. a string, which is not constructed).
++ * The output is a pointer inside the @der.
++ *
++ * Returns: %ASN1_SUCCESS if successful or an error value.
++ **/
++int
++asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
++			unsigned int der_len, const unsigned char **str,
++			unsigned int *str_len)
++{
++  int tag_len, len_len;
++  const unsigned char *p;
++  unsigned char class;
++  unsigned long tag;
++  long ret;
++
++  if (der == NULL || der_len == 0)
++    return ASN1_VALUE_NOT_VALID;
++
++  if (ETYPE_OK (etype) == 0)
++    return ASN1_VALUE_NOT_VALID;
++
++  /* doesn't handle constructed classes */
++  if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
++    return ASN1_VALUE_NOT_VALID;
++
++  p = der;
++  ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
++  if (ret != ASN1_SUCCESS)
++    return ret;
++
++  if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype))
++    return ASN1_DER_ERROR;
++
++  p += tag_len;
++  der_len -= tag_len;
++
++  ret = asn1_get_length_der (p, der_len, &len_len);
++  if (ret < 0)
++    return ASN1_DER_ERROR;
++
++  p += len_len;
++  der_len -= len_len;
++
++  *str_len = ret;
++  *str = p;
++
++  return ASN1_SUCCESS;
++}
+--- ORIGINAL/./lib/structure.c	2015-07-14 18:28:22.916996471 -0700
++++ libtasn1-2.8/./lib/structure.c	2015-07-14 18:45:02.684513241 -0700
+@@ -38,7 +38,7 @@
+ 
+ 
+ /******************************************************/
+-/* Function : _asn1_add_node_only                     */
++/* Function : _asn1_add_single_node                     */
+ /* Description: creates a new NODE_ASN element.       */
+ /* Parameters:                                        */
+ /*   type: type of the new element (see TYPE_         */
+@@ -46,11 +46,11 @@
+ /* Return: pointer to the new element.                */
+ /******************************************************/
+ ASN1_TYPE
+-_asn1_add_node_only (unsigned int type)
++_asn1_add_single_node (unsigned int type)
+ {
+   ASN1_TYPE punt;
+ 
+-  punt = (ASN1_TYPE) _asn1_calloc (1, sizeof (struct node_asn_struct));
++  punt = calloc (1, sizeof (struct node_asn_struct));
+   if (punt == NULL)
+     return NULL;
+ 
+@@ -78,7 +78,7 @@
+ }
+ 
+ 
+-asn1_retCode
++int
+ _asn1_create_static_structure (ASN1_TYPE pointer, char *output_file_name,
+ 			       char *vector_name)
+ {
+@@ -105,7 +105,7 @@
+     {
+       fprintf (file, "  { ");
+ 
+-      if (p->name)
++      if (p->name[0] != 0)
+ 	fprintf (file, "\"%s\", ", p->name);
+       else
+ 	fprintf (file, "NULL, ");
+@@ -168,28 +168,24 @@
+  * Creates the structures needed to manage the ASN.1 definitions.
+  * @array is a vector created by asn1_parser2array().
+  *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Structure created correctly.
+- *
+- * %ASN1_ELEMENT_NOT_EMPTY: *@definitions not ASN1_TYPE_EMPTY.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- *   is not defined (see @errorDescription for more information).
+- *
+- * %ASN1_ARRAY_ERROR: The array pointed by @array is wrong.
++ * Returns: %ASN1_SUCCESS if structure was created correctly,
++ *   %ASN1_ELEMENT_NOT_EMPTY if *@definitions not NULL,
++ *   %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an identifier
++ *   that is not defined (see @errorDescription for more information),
++ *   %ASN1_ARRAY_ERROR if the array pointed by @array is wrong.
+  **/
+-asn1_retCode
++int
+ asn1_array2tree (const ASN1_ARRAY_TYPE * array, ASN1_TYPE * definitions,
+ 		 char *errorDescription)
+ {
+   ASN1_TYPE p, p_last = NULL;
+   unsigned long k;
+   int move;
+-  asn1_retCode result;
++  int result;
++  unsigned int type;
+ 
+ 
+-  if (*definitions != ASN1_TYPE_EMPTY)
++  if (*definitions != NULL)
+     return ASN1_ELEMENT_NOT_EMPTY;
+ 
+   move = UP;
+@@ -197,7 +193,9 @@
+   k = 0;
+   while (array[k].value || array[k].type || array[k].name)
+     {
+-      p = _asn1_add_node (array[k].type & (~CONST_DOWN));
++      type = convert_old_type (array[k].type);
++
++      p = _asn1_add_static_node (type & (~CONST_DOWN));
+       if (array[k].name)
+ 	_asn1_set_name (p, array[k].name);
+       if (array[k].value)
+@@ -213,9 +211,9 @@
+ 
+       p_last = p;
+ 
+-      if (array[k].type & CONST_DOWN)
++      if (type & CONST_DOWN)
+ 	move = DOWN;
+-      else if (array[k].type & CONST_RIGHT)
++      else if (type & CONST_RIGHT)
+ 	move = RIGHT;
+       else
+ 	{
+@@ -269,7 +267,7 @@
+   if (result != ASN1_SUCCESS)
+     {
+       _asn1_delete_list_and_nodes ();
+-      *definitions = ASN1_TYPE_EMPTY;
++      *definitions = NULL;
+     }
+   else
+     _asn1_delete_list ();
+@@ -282,20 +280,34 @@
+  * @structure: pointer to the structure that you want to delete.
+  *
+  * Deletes the structure *@structure.  At the end, *@structure is set
+- * to ASN1_TYPE_EMPTY.
++ * to NULL.
+  *
+- * Returns:
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ *   *@structure was NULL.
++ **/
++int
++asn1_delete_structure (ASN1_TYPE * structure)
++{
++  return asn1_delete_structure2(structure, 0);
++}
++
++/**
++ * asn1_delete_structure2:
++ * @structure: pointer to the structure that you want to delete.
++ * @flags: additional flags (see %ASN1_DELETE_FLAG)
+  *
+- * %ASN1_SUCCESS: Everything OK.
++ * Deletes the structure *@structure.  At the end, *@structure is set
++ * to NULL.
+  *
+- * %ASN1_ELEMENT_NOT_FOUND: *@structure was ASN1_TYPE_EMPTY.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ *   *@structure was NULL.
+  **/
+-asn1_retCode
+-asn1_delete_structure (ASN1_TYPE * structure)
++int
++asn1_delete_structure2 (ASN1_TYPE * structure, unsigned int flags)
+ {
+   ASN1_TYPE p, p2, p3;
+ 
+-  if (*structure == ASN1_TYPE_EMPTY)
++  if (*structure == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   p = *structure;
+@@ -312,7 +324,7 @@
+ 	    {
+ 	      p3 = _asn1_find_up (p);
+ 	      _asn1_set_down (p3, p2);
+-	      _asn1_remove_node (p);
++	      _asn1_remove_node (p, flags);
+ 	      p = p3;
+ 	    }
+ 	  else
+@@ -331,13 +343,13 @@
+ 		}
+ 	      else
+ 		_asn1_set_right (p3, p2);
+-	      _asn1_remove_node (p);
++	      _asn1_remove_node (p, flags);
+ 	      p = NULL;
+ 	    }
+ 	}
+     }
+ 
+-  *structure = ASN1_TYPE_EMPTY;
++  *structure = NULL;
+   return ASN1_SUCCESS;
+ }
+ 
+@@ -351,20 +363,17 @@
+  *
+  * Deletes the element named *@element_name inside *@structure.
+  *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Everything OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: The name element was not found.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ *   the @element_name was not found.
+  **/
+-asn1_retCode
++int
+ asn1_delete_element (ASN1_TYPE structure, const char *element_name)
+ {
+   ASN1_TYPE p2, p3, source_node;
+ 
+   source_node = asn1_find_node (structure, element_name);
+ 
+-  if (source_node == ASN1_TYPE_EMPTY)
++  if (source_node == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+   p2 = source_node->right;
+@@ -392,7 +401,7 @@
+   if (source_node == NULL)
+     return NULL;
+ 
+-  dest_node = _asn1_add_node_only (source_node->type);
++  dest_node = _asn1_add_single_node (source_node->type);
+ 
+   p_s = source_node;
+   p_d = dest_node;
+@@ -403,45 +412,34 @@
+     {
+       if (move != UP)
+ 	{
+-	  if (p_s->name)
+-	    _asn1_set_name (p_d, p_s->name);
++	  if (p_s->name[0] != 0)
++	    _asn1_cpy_name (p_d, p_s);
+ 	  if (p_s->value)
+ 	    _asn1_set_value (p_d, p_s->value, p_s->value_len);
+-	  move = DOWN;
+-	}
+-      else
+-	move = RIGHT;
+-
+-      if (move == DOWN)
+-	{
+ 	  if (p_s->down)
+ 	    {
+ 	      p_s = p_s->down;
+ 	      p_d_prev = p_d;
+-	      p_d = _asn1_add_node_only (p_s->type);
++	      p_d = _asn1_add_single_node (p_s->type);
+ 	      _asn1_set_down (p_d_prev, p_d);
++	      continue;
+ 	    }
+-	  else
+-	    move = RIGHT;
+ 	}
+ 
+       if (p_s == source_node)
+ 	break;
+ 
+-      if (move == RIGHT)
++      if (p_s->right)
+ 	{
+-	  if (p_s->right)
+-	    {
+-	      p_s = p_s->right;
+-	      p_d_prev = p_d;
+-	      p_d = _asn1_add_node_only (p_s->type);
+-	      _asn1_set_right (p_d_prev, p_d);
+-	    }
+-	  else
+-	    move = UP;
++	  move = RIGHT;
++	  p_s = p_s->right;
++	  p_d_prev = p_d;
++	  p_d = _asn1_add_single_node (p_s->type);
++	  _asn1_set_right (p_d_prev, p_d);
+ 	}
+-      if (move == UP)
++      else
+ 	{
++	  move = UP;
+ 	  p_s = _asn1_find_up (p_s);
+ 	  p_d = _asn1_find_up (p_d);
+ 	}
+@@ -464,7 +462,7 @@
+ }
+ 
+ 
+-static asn1_retCode
++static int
+ _asn1_type_choice_config (ASN1_TYPE node)
+ {
+   ASN1_TYPE p, p2, p3, p4;
+@@ -480,7 +478,8 @@
+     {
+       if (move != UP)
+ 	{
+-	  if ((type_field (p->type) == TYPE_CHOICE) && (p->type & CONST_TAG))
++	  if ((type_field (p->type) == TYPE_CHOICE)
++	      && (p->type & CONST_TAG))
+ 	    {
+ 	      p2 = p->down;
+ 	      while (p2)
+@@ -493,8 +492,8 @@
+ 			{
+ 			  if (type_field (p3->type) == TYPE_TAG)
+ 			    {
+-			      p4 = _asn1_add_node_only (p3->type);
+-			      tlen = strlen (p3->value);
++			      p4 = _asn1_add_single_node (p3->type);
++			      tlen = _asn1_strlen (p3->value);
+ 			      if (tlen > 0)
+ 				_asn1_set_value (p4, p3->value, tlen + 1);
+ 			      _asn1_set_right (p4, p2->down);
+@@ -549,7 +548,7 @@
+ }
+ 
+ 
+-static asn1_retCode
++static int
+ _asn1_expand_identifier (ASN1_TYPE * node, ASN1_TYPE root)
+ {
+   ASN1_TYPE p, p2, p3;
+@@ -568,15 +567,13 @@
+ 	{
+ 	  if (type_field (p->type) == TYPE_IDENTIFIER)
+ 	    {
+-	      _asn1_str_cpy (name2, sizeof (name2), root->name);
+-	      _asn1_str_cat (name2, sizeof (name2), ".");
+-	      _asn1_str_cat (name2, sizeof (name2), p->value);
++	      snprintf (name2, sizeof (name2), "%s.%s", root->name, p->value);
+ 	      p2 = _asn1_copy_structure2 (root, name2);
+ 	      if (p2 == NULL)
+ 		{
+ 		  return ASN1_IDENTIFIER_NOT_FOUND;
+ 		}
+-	      _asn1_set_name (p2, p->name);
++	      _asn1_cpy_name (p2, p);
+ 	      p2->right = p->right;
+ 	      p2->left = p->left;
+ 	      if (p->right)
+@@ -619,7 +616,7 @@
+ 
+ 	      if (p == *node)
+ 		*node = p2;
+-	      _asn1_remove_node (p);
++	      _asn1_remove_node (p, 0);
+ 	      p = p2;
+ 	      move = DOWN;
+ 	      continue;
+@@ -670,13 +667,10 @@
+  *
+  * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr);
+  *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: Creation OK.
+- *
+- * %ASN1_ELEMENT_NOT_FOUND: SOURCE_NAME isn't known
++ * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if
++ *   @source_name is not known.
+  **/
+-asn1_retCode
++int
+ asn1_create_element (ASN1_TYPE definitions, const char *source_name,
+ 		     ASN1_TYPE * element)
+ {
+@@ -734,7 +728,7 @@
+ 	  for (k = 0; k < indent; k++)
+ 	    fprintf (out, " ");
+ 	  fprintf (out, "name:");
+-	  if (p->name)
++	  if (p->name[0] != 0)
+ 	    fprintf (out, "%s  ", p->name);
+ 	  else
+ 	    fprintf (out, "NULL  ");
+@@ -751,7 +745,7 @@
+ 	      for (k = 0; k < indent; k++)
+ 		fprintf (out, " ");
+ 	      fprintf (out, "name:");
+-	      if (p->name)
++	      if (p->name[0] != 0)
+ 		fprintf (out, "%s  ", p->name);
+ 	      else
+ 		fprintf (out, "NULL  ");
+@@ -760,7 +754,8 @@
+ 
+       if (mode != ASN1_PRINT_NAME)
+ 	{
+-	  switch (type_field (p->type))
++	  unsigned type = type_field (p->type);
++	  switch (type)
+ 	    {
+ 	    case TYPE_CONSTANT:
+ 	      if (mode == ASN1_PRINT_ALL)
+@@ -777,57 +772,21 @@
+ 	    case TYPE_DEFAULT:
+ 	      fprintf (out, "type:DEFAULT");
+ 	      break;
+-	    case TYPE_NULL:
+-	      fprintf (out, "type:NULL");
+-	      break;
+ 	    case TYPE_IDENTIFIER:
+ 	      fprintf (out, "type:IDENTIFIER");
+ 	      break;
+-	    case TYPE_INTEGER:
+-	      fprintf (out, "type:INTEGER");
+-	      break;
+-	    case TYPE_ENUMERATED:
+-	      fprintf (out, "type:ENUMERATED");
+-	      break;
+-	    case TYPE_TIME:
+-	      fprintf (out, "type:TIME");
+-	      break;
+-	    case TYPE_BOOLEAN:
+-	      fprintf (out, "type:BOOLEAN");
+-	      break;
+-	    case TYPE_SEQUENCE:
+-	      fprintf (out, "type:SEQUENCE");
+-	      break;
+-	    case TYPE_BIT_STRING:
+-	      fprintf (out, "type:BIT_STR");
+-	      break;
+-	    case TYPE_OCTET_STRING:
+-	      fprintf (out, "type:OCT_STR");
+-	      break;
+-	    case TYPE_GENERALSTRING:
+-	      fprintf (out, "type:GENERALSTRING");
+-	      break;
+-	    case TYPE_SEQUENCE_OF:
+-	      fprintf (out, "type:SEQ_OF");
+-	      break;
+-	    case TYPE_OBJECT_ID:
+-	      fprintf (out, "type:OBJ_ID");
+-	      break;
+ 	    case TYPE_ANY:
+ 	      fprintf (out, "type:ANY");
+ 	      break;
+-	    case TYPE_SET:
+-	      fprintf (out, "type:SET");
+-	      break;
+-	    case TYPE_SET_OF:
+-	      fprintf (out, "type:SET_OF");
+-	      break;
+ 	    case TYPE_CHOICE:
+ 	      fprintf (out, "type:CHOICE");
+ 	      break;
+ 	    case TYPE_DEFINITIONS:
+ 	      fprintf (out, "type:DEFINITIONS");
+ 	      break;
++	    CASE_HANDLED_ETYPES:
++	      fprintf (out, "%s", _asn1_tags[type].desc);
++	      break;
+ 	    default:
+ 	      break;
+ 	    }
+@@ -886,10 +845,6 @@
+ 		      fprintf (out, "%02x", (p->value)[k + len2]);
+ 		}
+ 	      break;
+-	    case TYPE_TIME:
+-	      if (p->value)
+-		fprintf (out, "  value:%s", p->value);
+-	      break;
+ 	    case TYPE_BOOLEAN:
+ 	      if (p->value)
+ 		{
+@@ -913,7 +868,23 @@
+ 		    }
+ 		}
+ 	      break;
+-	    case TYPE_OCTET_STRING:
++	    case TYPE_GENERALIZED_TIME:
++	    case TYPE_UTC_TIME:
++	      if (p->value)
++		{
++		  fprintf (out, "  value:");
++		  for (k = 0; k < p->value_len; k++)
++		    fprintf (out, "%c", (p->value)[k]);
++		}
++	      break;
++	    case TYPE_GENERALSTRING:
++	    case TYPE_NUMERIC_STRING:
++	    case TYPE_IA5_STRING:
++	    case TYPE_TELETEX_STRING:
++	    case TYPE_PRINTABLE_STRING:
++	    case TYPE_UNIVERSAL_STRING:
++	    case TYPE_UTF8_STRING:
++	    case TYPE_VISIBLE_STRING:
+ 	      if (p->value)
+ 		{
+ 		  len2 = -1;
+@@ -921,10 +892,11 @@
+ 		  fprintf (out, "  value:");
+ 		  if (len > 0)
+ 		    for (k = 0; k < len; k++)
+-		      fprintf (out, "%02x", (p->value)[k + len2]);
++		      fprintf (out, "%c", (p->value)[k + len2]);
+ 		}
+ 	      break;
+-	    case TYPE_GENERALSTRING:
++	    case TYPE_BMP_STRING:
++	    case TYPE_OCTET_STRING:
+ 	      if (p->value)
+ 		{
+ 		  len2 = -1;
+@@ -1072,15 +1044,10 @@
+  * Counts the number of elements of a sub-structure called NAME with
+  * names equal to "?1","?2", ...
+  *
+- * Returns:
+- *
+- *  %ASN1_SUCCESS: Creation OK.
+- *
+- *  %ASN1_ELEMENT_NOT_FOUND: NAME isn't known.
+- *
+- *  %ASN1_GENERIC_ERROR: Pointer num equal to NULL.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ *   @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL.
+  **/
+-asn1_retCode
++int
+ asn1_number_of_elements (ASN1_TYPE element, const char *name, int *num)
+ {
+   ASN1_TYPE node, p;
+@@ -1098,7 +1065,7 @@
+ 
+   while (p)
+     {
+-      if ((p->name) && (p->name[0] == '?'))
++      if (p->name[0] == '?')
+ 	(*num)++;
+       p = p->right;
+     }
+@@ -1121,18 +1088,17 @@
+ const char *
+ asn1_find_structure_from_oid (ASN1_TYPE definitions, const char *oidValue)
+ {
+-  char definitionsName[ASN1_MAX_NAME_SIZE], name[2 * ASN1_MAX_NAME_SIZE + 1];
++  char name[2 * ASN1_MAX_NAME_SIZE + 1];
+   char value[ASN1_MAX_NAME_SIZE];
+   ASN1_TYPE p;
+   int len;
+-  asn1_retCode result;
++  int result;
++  const char *definitionsName;
+ 
+-  if ((definitions == ASN1_TYPE_EMPTY) || (oidValue == NULL))
++  if ((definitions == NULL) || (oidValue == NULL))
+     return NULL;		/* ASN1_ELEMENT_NOT_FOUND; */
+ 
+-
+-  strcpy (definitionsName, definitions->name);
+-  strcat (definitionsName, ".");
++  definitionsName = definitions->name;
+ 
+   /* search the OBJECT_ID into definitions */
+   p = definitions->down;
+@@ -1141,8 +1107,7 @@
+       if ((type_field (p->type) == TYPE_OBJECT_ID) &&
+ 	  (p->type & CONST_ASSIGN))
+ 	{
+-	  strcpy (name, definitionsName);
+-	  strcat (name, p->name);
++          snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name);
+ 
+ 	  len = ASN1_MAX_NAME_SIZE;
+ 	  result = asn1_read_value (definitions, name, value, &len);
+@@ -1171,9 +1136,9 @@
+  *
+  * Create a deep copy of a ASN1_TYPE variable.
+  *
+- * Return value: Return %ASN1_SUCCESS on success.
++ * Returns: Return %ASN1_SUCCESS on success.
+  **/
+-asn1_retCode
++int
+ asn1_copy_node (ASN1_TYPE dst, const char *dst_name,
+ 		ASN1_TYPE src, const char *src_name)
+ {
+@@ -1189,27 +1154,27 @@
+   if (result != ASN1_MEM_ERROR)
+     return result;
+ 
+-  data = _asn1_malloc (size);
++  data = malloc (size);
+   if (data == NULL)
+     return ASN1_MEM_ERROR;
+ 
+   result = asn1_der_coding (src, src_name, data, &size, NULL);
+   if (result != ASN1_SUCCESS)
+     {
+-      _asn1_free (data);
++      free (data);
+       return result;
+     }
+ 
+   dst_node = asn1_find_node (dst, dst_name);
+   if (dst_node == NULL)
+     {
+-      _asn1_free (data);
++      free (data);
+       return ASN1_ELEMENT_NOT_FOUND;
+     }
+ 
+   result = asn1_der_decoding (&dst_node, data, size, NULL);
+ 
+-  _asn1_free (data);
++  free (data);
+ 
+   return result;
+ }
+--- ORIGINAL/./lib/coding.c	2015-07-14 18:28:22.911826177 -0700
++++ libtasn1-2.8/./lib/coding.c	2015-07-14 18:45:02.651262664 -0700
+@@ -31,8 +31,19 @@
+ #include "parser_aux.h"
+ #include <gstr.h>
+ #include "element.h"
++/*#include "minmax.h"*/
+ #include <structure.h>
+ 
++/* MAX(a,b) returns the maximum of A and B.  */
++#ifndef MAX
++# define MAX(a,b) ((a) > (b) ? (a) : (b))
++#endif
++
++/* MIN(a,b) returns the minimum of A and B.  */
++#ifndef MIN
++# define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++
+ #define MAX_TAG_LEN 16
+ 
+ /******************************************************/
+@@ -62,24 +73,30 @@
+ /**
+  * asn1_length_der:
+  * @len: value to convert.
+- * @ans: string returned.
+- * @ans_len: number of meaningful bytes of ANS (ans[0]..ans[ans_len-1]).
++ * @der: buffer to hold the returned encoding (may be %NULL).
++ * @der_len: number of meaningful bytes of ANS (der[0]..der[der_len-1]).
++ *
++ * Creates the DER encoding of the provided length value.
++ * The @der buffer must have enough room for the output. The maximum
++ * length this function will encode is %ASN1_MAX_LENGTH_SIZE.
+  *
+- * Creates the DER coding for the LEN parameter (only the length).
+- * The @ans buffer is pre-allocated and must have room for the output.
++ * To know the size of the DER encoding use a %NULL value for @der.
+  **/
+ void
+-asn1_length_der (unsigned long int len, unsigned char *ans, int *ans_len)
++asn1_length_der (unsigned long int len, unsigned char *der, int *der_len)
+ {
+   int k;
+-  unsigned char temp[SIZEOF_UNSIGNED_LONG_INT];
++  unsigned char temp[ASN1_MAX_LENGTH_SIZE];
++#if SIZEOF_UNSIGNED_LONG_INT > 8
++  len &= 0xFFFFFFFFFFFFFFFF;
++#endif
+ 
+   if (len < 128)
+     {
+       /* short form */
+-      if (ans != NULL)
+-	ans[0] = (unsigned char) len;
+-      *ans_len = 1;
++      if (der != NULL)
++	der[0] = (unsigned char) len;
++      *der_len = 1;
+     }
+   else
+     {
+@@ -90,12 +107,12 @@
+ 	  temp[k++] = len & 0xFF;
+ 	  len = len >> 8;
+ 	}
+-      *ans_len = k + 1;
+-      if (ans != NULL)
++      *der_len = k + 1;
++      if (der != NULL)
+ 	{
+-	  ans[0] = ((unsigned char) k & 0x7F) + 128;
++	  der[0] = ((unsigned char) k & 0x7F) + 128;
+ 	  while (k--)
+-	    ans[*ans_len - 1 - k] = temp[k];
++	    der[*der_len - 1 - k] = temp[k];
+ 	}
+     }
+ }
+@@ -104,6 +121,7 @@
+ /* Function : _asn1_tag_der                           */
+ /* Description: creates the DER coding for the CLASS  */
+ /* and TAG parameters.                                */
++/* It is limited by the ASN1_MAX_TAG_SIZE variable    */
+ /* Parameters:                                        */
+ /*   class: value to convert.                         */
+ /*   tag_value: value to convert.                     */
+@@ -117,7 +135,7 @@
+ 	       unsigned char *ans, int *ans_len)
+ {
+   int k;
+-  unsigned char temp[SIZEOF_UNSIGNED_INT];
++  unsigned char temp[ASN1_MAX_TAG_SIZE];
+ 
+   if (tag_value < 31)
+     {
+@@ -130,10 +148,13 @@
+       /* Long form */
+       ans[0] = (class & 0xE0) + 31;
+       k = 0;
+-      while (tag_value)
++      while (tag_value != 0)
+ 	{
+ 	  temp[k++] = tag_value & 0x7F;
+-	  tag_value = tag_value >> 7;
++	  tag_value >>= 7;
++
++	  if (k > ASN1_MAX_TAG_SIZE - 1)
++	    break;		/* will not encode larger tags */
+ 	}
+       *ans_len = k + 1;
+       while (k--)
+@@ -144,12 +165,20 @@
+ 
+ /**
+  * asn1_octet_der:
+- * @str: OCTET string.
+- * @str_len: STR length (str[0]..str[str_len-1]).
+- * @der: string returned.
+- * @der_len: number of meaningful bytes of DER (der[0]..der[ans_len-1]).
++ * @str: the input data.
++ * @str_len: STR length (str[0]..str[*str_len-1]).
++ * @der: encoded string returned.
++ * @der_len: number of meaningful bytes of DER (der[0]..der[der_len-1]).
++ *
++ * Creates a length-value DER encoding for the input data.
++ * The DER encoding of the input data will be placed in the @der variable.
+  *
+- * Creates the DER coding for an OCTET type (length included).
++ * Note that the OCTET STRING tag is not included in the output.
++ *
++ * This function does not return any value because it is expected
++ * that @der_len will contain enough bytes to store the string
++ * plus the DER encoding. The DER encoding size can be obtained using
++ * asn1_length_der().
+  **/
+ void
+ asn1_octet_der (const unsigned char *str, int str_len,
+@@ -159,11 +188,73 @@
+ 
+   if (der == NULL || str_len < 0)
+     return;
++
+   asn1_length_der (str_len, der, &len_len);
+   memcpy (der + len_len, str, str_len);
+   *der_len = str_len + len_len;
+ }
+ 
++
++/**
++ * asn1_encode_simple_der:
++ * @etype: The type of the string to be encoded (TYPE_)
++ * @str: the string data.
++ * @str_len: the string length
++ * @tl: the encoded tag and length
++ * @tl_len: the bytes of the @tl field
++ *
++ * Creates the DER encoding for various simple ASN.1 types like strings etc.
++ * It stores the tag and length in @tl, which should have space for at least
++ * %ASN1_MAX_TL_SIZE bytes. Initially @tl_len should contain the size of @tl.
++ *
++ * The complete DER encoding should consist of the value in @tl appended
++ * with the provided @str.
++ *
++ * Returns: %ASN1_SUCCESS if successful or an error value.
++ **/
++int
++asn1_encode_simple_der (unsigned int etype, const unsigned char *str,
++			unsigned int str_len, unsigned char *tl,
++			unsigned int *tl_len)
++{
++  int tag_len, len_len;
++  unsigned tlen;
++  unsigned char der_tag[ASN1_MAX_TAG_SIZE];
++  unsigned char der_length[ASN1_MAX_LENGTH_SIZE];
++  unsigned char *p;
++
++  if (str == NULL)
++    return ASN1_VALUE_NOT_VALID;
++
++  if (ETYPE_OK (etype) == 0)
++    return ASN1_VALUE_NOT_VALID;
++
++  /* doesn't handle constructed classes */
++  if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
++    return ASN1_VALUE_NOT_VALID;
++
++  _asn1_tag_der (ETYPE_CLASS (etype), ETYPE_TAG (etype), der_tag, &tag_len);
++
++  asn1_length_der (str_len, der_length, &len_len);
++
++  if (tag_len <= 0 || len_len <= 0)
++    return ASN1_VALUE_NOT_VALID;
++
++  tlen = tag_len + len_len;
++
++  if (*tl_len < tlen)
++    return ASN1_MEM_ERROR;
++
++  p = tl;
++  memcpy (p, der_tag, tag_len);
++  p += tag_len;
++  memcpy (p, der_length, len_len);
++
++  *tl_len = tlen;
++
++  return ASN1_SUCCESS;
++}
++
+ /******************************************************/
+ /* Function : _asn1_time_der                          */
+ /* Description: creates the DER coding for a TIME     */
+@@ -178,19 +269,20 @@
+ /*   ASN1_MEM_ERROR when DER isn't big enough         */
+ /*   ASN1_SUCCESS otherwise                           */
+ /******************************************************/
+-static asn1_retCode
+-_asn1_time_der (unsigned char *str, unsigned char *der, int *der_len)
++static int
++_asn1_time_der (unsigned char *str, int str_len, unsigned char *der,
++		int *der_len)
+ {
+   int len_len;
+   int max_len;
+ 
+   max_len = *der_len;
+ 
+-  asn1_length_der (strlen (str), (max_len > 0) ? der : NULL, &len_len);
++  asn1_length_der (str_len, (max_len > 0) ? der : NULL, &len_len);
+ 
+-  if ((len_len + (int) strlen (str)) <= max_len)
+-    memcpy (der + len_len, str, strlen (str));
+-  *der_len = len_len + strlen (str);
++  if ((len_len + str_len) <= max_len)
++    memcpy (der + len_len, str, str_len);
++  *der_len = len_len + str_len;
+ 
+   if ((*der_len) > max_len)
+     return ASN1_MEM_ERROR;
+@@ -247,29 +339,27 @@
+ /*            must store the length of DER.           */
+ /* Return:                                            */
+ /*   ASN1_MEM_ERROR when DER isn't big enough         */
+-/*   ASN1_SUCCESS otherwise                           */
++/*   ASN1_SUCCESS if succesful                        */
++/*   or an error value.                               */
+ /******************************************************/
+-static asn1_retCode
++static int
+ _asn1_objectid_der (unsigned char *str, unsigned char *der, int *der_len)
+ {
+   int len_len, counter, k, first, max_len;
+-  char *temp = NULL, *n_end, *n_start;
++  char *temp, *n_end, *n_start;
+   unsigned char bit7;
+   unsigned long val, val1 = 0;
+-  size_t temp_size = str ? strlen (str) : 0;
+-
+-  temp_size += 2;
+-  if (temp_size < 2)
+-    return ASN1_MEM_ALLOC_ERROR;
++  int str_len = _asn1_strlen (str);
+ 
+   max_len = *der_len;
+ 
+-  temp = (char *) _asn1_malloc (temp_size);
++  temp = malloc (str_len + 2);
+   if (temp == NULL)
+     return ASN1_MEM_ALLOC_ERROR;
+ 
+-  strncpy (temp, str ? (const char *)str : "", temp_size);
+-  strncat (temp, ".", 1);
++  memcpy (temp, str, str_len);
++  temp[str_len] = '.';
++  temp[str_len + 1] = 0;
+ 
+   counter = 0;
+   n_start = temp;
+@@ -316,7 +406,7 @@
+     }
+   *der_len += len_len;
+ 
+-  _asn1_free (temp);
++  free (temp);
+ 
+   if (max_len < (*der_len))
+     return ASN1_MEM_ERROR;
+@@ -325,7 +415,8 @@
+ }
+ 
+ 
+-const char bit_mask[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
++static const unsigned char bit_mask[] =
++  { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
+ 
+ /**
+  * asn1_bit_der:
+@@ -335,8 +426,16 @@
+  * @der_len: number of meaningful bytes of DER
+  *   (der[0]..der[ans_len-1]).
+  *
+- * Creates the DER coding for a BIT STRING type (length and pad
+- * included).
++ * Creates a length-value DER encoding for the input data
++ * as it would have been for a BIT STRING.
++ * The DER encoded data will be copied in @der.
++ *
++ * Note that the BIT STRING tag is not included in the output.
++ *
++ * This function does not return any value because it is expected
++ * that @der_len will contain enough bytes to store the string
++ * plus the DER encoding. The DER encoding size can be obtained using
++ * asn1_length_der().
+  **/
+ void
+ asn1_bit_der (const unsigned char *str, int bit_len,
+@@ -346,6 +445,7 @@
+ 
+   if (der == NULL)
+     return;
++
+   len_byte = bit_len >> 3;
+   len_pad = 8 - (bit_len & 7);
+   if (len_pad == 8)
+@@ -374,7 +474,7 @@
+ /*   ASN1_MEM_ERROR if der vector isn't big enough,   */
+ /*   otherwise ASN1_SUCCESS.                          */
+ /******************************************************/
+-static asn1_retCode
++static int
+ _asn1_complete_explicit_tag (ASN1_TYPE node, unsigned char *der,
+ 			     int *counter, int *max_len)
+ {
+@@ -387,6 +487,8 @@
+   if (node->type & CONST_TAG)
+     {
+       p = node->down;
++      if (p == NULL)
++        return ASN1_DER_ERROR;
+       /* When there are nested tags we must complete them reverse to
+          the order they were created. This is because completing a tag
+          modifies all data within it, including the incomplete tags
+@@ -431,6 +533,56 @@
+   return ASN1_SUCCESS;
+ }
+ 
++const tag_and_class_st _asn1_tags[] = {
++  [TYPE_GENERALSTRING] =
++    {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"},
++  [TYPE_NUMERIC_STRING] =
++    {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"},
++  [TYPE_IA5_STRING] =
++    {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"},
++  [TYPE_TELETEX_STRING] =
++    {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"},
++  [TYPE_PRINTABLE_STRING] =
++    {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"},
++  [TYPE_UNIVERSAL_STRING] =
++    {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"},
++  [TYPE_BMP_STRING] =
++    {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"},
++  [TYPE_UTF8_STRING] =
++    {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"},
++  [TYPE_VISIBLE_STRING] =
++    {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"},
++  [TYPE_OCTET_STRING] =
++    {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"},
++  [TYPE_BIT_STRING] =
++    {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"},
++  [TYPE_OBJECT_ID] =
++    {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"},
++  [TYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"},
++  [TYPE_BOOLEAN] =
++    {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"},
++  [TYPE_INTEGER] =
++    {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"},
++  [TYPE_ENUMERATED] =
++    {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"},
++  [TYPE_SEQUENCE] =
++    {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
++     "type:SEQUENCE"},
++  [TYPE_SEQUENCE_OF] =
++    {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
++     "type:SEQ_OF"},
++  [TYPE_SET] =
++    {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"},
++  [TYPE_SET_OF] =
++    {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
++     "type:SET_OF"},
++  [TYPE_GENERALIZED_TIME] =
++    {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"},
++  [TYPE_UTC_TIME] =
++    {ASN1_TAG_UTCTime, ASN1_CLASS_UNIVERSAL, "type:UTC_TIME"},
++};
++
++unsigned int _asn1_tags_size = sizeof (_asn1_tags) / sizeof (_asn1_tags[0]);
+ 
+ /******************************************************/
+ /* Function : _asn1_insert_tag_der                    */
+@@ -447,15 +599,15 @@
+ /*   ASN1_MEM_ERROR if der vector isn't big enough,   */
+ /*   otherwise ASN1_SUCCESS.                          */
+ /******************************************************/
+-static asn1_retCode
++static int
+ _asn1_insert_tag_der (ASN1_TYPE node, unsigned char *der, int *counter,
+ 		      int *max_len)
+ {
+   ASN1_TYPE p;
+   int tag_len, is_tag_implicit;
+-  unsigned char class, class_implicit = 0, temp[SIZEOF_UNSIGNED_INT * 3 + 1];
++  unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)];
+   unsigned long tag_implicit = 0;
+-  char tag_der[MAX_TAG_LEN];
++  unsigned char tag_der[MAX_TAG_LEN];
+ 
+   is_tag_implicit = 0;
+ 
+@@ -482,16 +634,16 @@
+ 				   &tag_len);
+ 		  else
+ 		    _asn1_tag_der (class | ASN1_CLASS_STRUCTURED,
+-				   strtoul (p->value, NULL, 10), tag_der,
+-				   &tag_len);
++				   _asn1_strtoul (p->value, NULL, 10),
++				   tag_der, &tag_len);
+ 
+ 		  *max_len -= tag_len;
+ 		  if (*max_len >= 0)
+ 		    memcpy (der + *counter, tag_der, tag_len);
+ 		  *counter += tag_len;
+ 
+-		  _asn1_ltostr (*counter, temp);
+-		  _asn1_set_name (p, temp);
++		  _asn1_ltostr (*counter, (char *) temp);
++		  _asn1_set_name (p, (const char *) temp);
+ 
+ 		  is_tag_implicit = 0;
+ 		}
+@@ -500,12 +652,12 @@
+ 		  if (!is_tag_implicit)
+ 		    {
+ 		      if ((type_field (node->type) == TYPE_SEQUENCE) ||
+-			  (type_field (node->type) == TYPE_SEQUENCE_OF) ||
+-			  (type_field (node->type) == TYPE_SET) ||
+-			  (type_field (node->type) == TYPE_SET_OF))
++			  (type_field (node->type) == TYPE_SEQUENCE_OF)
++			  || (type_field (node->type) == TYPE_SET)
++			  || (type_field (node->type) == TYPE_SET_OF))
+ 			class |= ASN1_CLASS_STRUCTURED;
+ 		      class_implicit = class;
+-		      tag_implicit = strtoul (p->value, NULL, 10);
++		      tag_implicit = _asn1_strtoul (p->value, NULL, 10);
+ 		      is_tag_implicit = 1;
+ 		    }
+ 		}
+@@ -520,66 +672,15 @@
+     }
+   else
+     {
+-      switch (type_field (node->type))
++      unsigned type = type_field (node->type);
++      switch (type)
+ 	{
+-	case TYPE_NULL:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_NULL, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_BOOLEAN:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_BOOLEAN, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_INTEGER:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_INTEGER, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_ENUMERATED:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_ENUMERATED, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_OBJECT_ID:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_OBJECT_ID, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_TIME:
+-	  if (node->type & CONST_UTC)
+-	    {
+-	      _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_UTCTime, tag_der,
+-			     &tag_len);
+-	    }
+-	  else
+-	    _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALIZEDTime,
+-			   tag_der, &tag_len);
+-	  break;
+-	case TYPE_OCTET_STRING:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_OCTET_STRING, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_GENERALSTRING:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_GENERALSTRING,
++	CASE_HANDLED_ETYPES:
++	  _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag,
+ 			 tag_der, &tag_len);
+ 	  break;
+-	case TYPE_BIT_STRING:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL, ASN1_TAG_BIT_STRING, tag_der,
+-			 &tag_len);
+-	  break;
+-	case TYPE_SEQUENCE:
+-	case TYPE_SEQUENCE_OF:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+-			 ASN1_TAG_SEQUENCE, tag_der, &tag_len);
+-	  break;
+-	case TYPE_SET:
+-	case TYPE_SET_OF:
+-	  _asn1_tag_der (ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED,
+-			 ASN1_TAG_SET, tag_der, &tag_len);
+-	  break;
+ 	case TYPE_TAG:
+-	  tag_len = 0;
+-	  break;
+ 	case TYPE_CHOICE:
+-	  tag_len = 0;
+-	  break;
+ 	case TYPE_ANY:
+ 	  tag_len = 0;
+ 	  break;
+@@ -607,8 +708,10 @@
+ /*   der: string with the DER coding.                 */
+ /*   node: pointer to the SET element.                */
+ /* Return:                                            */
++/*    ASN1_SUCCESS if successful                      */
++/*    or an error value.                              */
+ /******************************************************/
+-static void
++static int
+ _asn1_ordering_set (unsigned char *der, int der_len, ASN1_TYPE node)
+ {
+   struct vet
+@@ -622,27 +725,31 @@
+   struct vet *first, *last, *p_vet, *p2_vet;
+   ASN1_TYPE p;
+   unsigned char class, *temp;
+-  unsigned long tag;
++  unsigned long tag, t;
++  int err;
+ 
+   counter = 0;
+ 
+   if (type_field (node->type) != TYPE_SET)
+-    return;
++    return ASN1_VALUE_NOT_VALID;
+ 
+   p = node->down;
+-  while ((type_field (p->type) == TYPE_TAG)
+-	 || (type_field (p->type) == TYPE_SIZE))
++  while (p && ((type_field (p->type) == TYPE_TAG) ||
++	 (type_field (p->type) == TYPE_SIZE)))
+     p = p->right;
+ 
+   if ((p == NULL) || (p->right == NULL))
+-    return;
++    return ASN1_SUCCESS;
+ 
+   first = last = NULL;
+   while (p)
+     {
+-      p_vet = (struct vet *) _asn1_malloc (sizeof (struct vet));
++      p_vet = malloc (sizeof (struct vet));
+       if (p_vet == NULL)
+-	return;
++        {
++	  err = ASN1_MEM_ALLOC_ERROR;
++	  goto error;
++	}
+ 
+       p_vet->next = NULL;
+       p_vet->prev = last;
+@@ -653,17 +760,22 @@
+       last = p_vet;
+ 
+       /* tag value calculation */
+-      if (asn1_get_tag_der
+-	  (der + counter, der_len - counter, &class, &len2,
+-	   &tag) != ASN1_SUCCESS)
+-	return;
+-      p_vet->value = (class << 24) | tag;
++      err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2,
++			      &tag);
++      if (err != ASN1_SUCCESS)
++	goto error;
++
++      t = class << 24;
++      p_vet->value = t | tag;
+       counter += len2;
+ 
+       /* extraction and length */
+       len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
+       if (len2 < 0)
+-	return;
++	{
++	  err = ASN1_DER_ERROR;
++	  goto error;
++	}
+       counter += len + len2;
+ 
+       p_vet->end = counter;
+@@ -681,16 +793,19 @@
+ 	  if (p_vet->value > p2_vet->value)
+ 	    {
+ 	      /* change position */
+-	      temp = (unsigned char *) _asn1_malloc (p_vet->end - counter);
++	      temp = malloc (p_vet->end - counter);
+ 	      if (temp == NULL)
+-		return;
++		{
++		  err = ASN1_MEM_ALLOC_ERROR;
++		  goto error;
++		}
+ 
+ 	      memcpy (temp, der + counter, p_vet->end - counter);
+ 	      memcpy (der + counter, der + p_vet->end,
+ 		      p2_vet->end - p_vet->end);
+ 	      memcpy (der + counter + p2_vet->end - p_vet->end, temp,
+ 		      p_vet->end - counter);
+-	      _asn1_free (temp);
++	      free (temp);
+ 
+ 	      tag = p_vet->value;
+ 	      p_vet->value = p2_vet->value;
+@@ -708,9 +823,19 @@
+ 	p_vet->prev->next = NULL;
+       else
+ 	first = NULL;
+-      _asn1_free (p_vet);
++      free (p_vet);
++      p_vet = first;
++    }
++  return ASN1_SUCCESS;
++
++error:
++  while (first != NULL)
++    {
+       p_vet = first;
++      first = first->next;
++      free(p_vet);
+     }
++  return err;
+ }
+ 
+ /******************************************************/
+@@ -721,8 +846,10 @@
+ /*   der: string with the DER coding.                 */
+ /*   node: pointer to the SET OF element.             */
+ /* Return:                                            */
++/*    ASN1_SUCCESS if successful                      */
++/*    or an error value.                              */
+ /******************************************************/
+-static void
++static int
+ _asn1_ordering_set_of (unsigned char *der, int der_len, ASN1_TYPE node)
+ {
+   struct vet
+@@ -735,28 +862,34 @@
+   struct vet *first, *last, *p_vet, *p2_vet;
+   ASN1_TYPE p;
+   unsigned char *temp, class;
+-  unsigned long k, max;
++  unsigned long k, length;
++  int err;
+ 
+   counter = 0;
+ 
+   if (type_field (node->type) != TYPE_SET_OF)
+-    return;
++    return ASN1_VALUE_NOT_VALID;
+ 
+   p = node->down;
+-  while ((type_field (p->type) == TYPE_TAG)
+-	 || (type_field (p->type) == TYPE_SIZE))
++  while (p && ((type_field (p->type) == TYPE_TAG) ||
++	 (type_field (p->type) == TYPE_SIZE)))
+     p = p->right;
++  if (p == NULL)
++    return ASN1_VALUE_NOT_VALID;
+   p = p->right;
+ 
+   if ((p == NULL) || (p->right == NULL))
+-    return;
++    return ASN1_SUCCESS;
+ 
+   first = last = NULL;
+   while (p)
+     {
+-      p_vet = (struct vet *) _asn1_malloc (sizeof (struct vet));
++      p_vet = malloc (sizeof (struct vet));
+       if (p_vet == NULL)
+-	return;
++	{
++	  err = ASN1_MEM_ALLOC_ERROR;
++	  goto error;
++	}
+ 
+       p_vet->next = NULL;
+       p_vet->prev = last;
+@@ -770,17 +903,25 @@
+       if (der_len - counter > 0)
+ 	{
+ 
+-	  if (asn1_get_tag_der
+-	      (der + counter, der_len - counter, &class, &len,
+-	       NULL) != ASN1_SUCCESS)
+-	    return;
++	  err = asn1_get_tag_der (der + counter, der_len - counter, &class,
++	                          &len, NULL);
++	  if (err != ASN1_SUCCESS)
++	    goto error;
+ 	  counter += len;
+ 
+ 	  len2 = asn1_get_length_der (der + counter, der_len - counter, &len);
+ 	  if (len2 < 0)
+-	    return;
++	    {
++	      err = ASN1_DER_ERROR;
++	      goto error;
++	    }
+ 	  counter += len + len2;
+ 	}
++      else
++	{
++	  err = ASN1_DER_ERROR;
++	  goto error;
++	}
+ 
+       p_vet->end = counter;
+       p = p->right;
+@@ -794,13 +935,9 @@
+       counter = 0;
+       while (p2_vet)
+ 	{
+-	  if ((p_vet->end - counter) > (p2_vet->end - p_vet->end))
+-	    max = p_vet->end - counter;
+-	  else
+-	    max = p2_vet->end - p_vet->end;
+-
++	  length = MIN(p_vet->end - counter, p2_vet->end - p_vet->end);
+ 	  change = -1;
+-	  for (k = 0; k < max; k++)
++	  for (k = 0; k < length; k++)
+ 	    if (der[counter + k] > der[p_vet->end + k])
+ 	      {
+ 		change = 1;
+@@ -819,16 +956,19 @@
+ 	  if (change == 1)
+ 	    {
+ 	      /* change position */
+-	      temp = (unsigned char *) _asn1_malloc (p_vet->end - counter);
++	      temp = malloc (p_vet->end - counter);
+ 	      if (temp == NULL)
+-		return;
++		{
++		  err = ASN1_MEM_ALLOC_ERROR;
++		  goto error;
++		}
+ 
+ 	      memcpy (temp, der + counter, (p_vet->end) - counter);
+ 	      memcpy (der + counter, der + (p_vet->end),
+ 		      (p2_vet->end) - (p_vet->end));
+ 	      memcpy (der + counter + (p2_vet->end) - (p_vet->end), temp,
+ 		      (p_vet->end) - counter);
+-	      _asn1_free (temp);
++	      free (temp);
+ 
+ 	      p_vet->end = counter + (p2_vet->end - p_vet->end);
+ 	    }
+@@ -842,9 +982,19 @@
+ 	p_vet->prev->next = NULL;
+       else
+ 	first = NULL;
+-      _asn1_free (p_vet);
++      free (p_vet);
++      p_vet = first;
++    }
++  return ASN1_SUCCESS;
++
++error:
++  while (first != NULL)
++    {
+       p_vet = first;
++      first = first->next;
++      free(p_vet);
+     }
++  return err;
+ }
+ 
+ /**
+@@ -856,31 +1006,26 @@
+  *   pointer to memory cells already allocated.
+  * @len: number of bytes of *@ider: @ider[0]..@ider[len-1], Initialy
+  *   holds the sizeof of der vector.
+- * @errorDescription : return the error description or an empty
++ * @ErrorDescription: return the error description or an empty
+  *   string if success.
+  *
+  * Creates the DER encoding for the NAME structure (inside *POINTER
+  * structure).
+  *
+- * Returns:
+- *
+- *   %ASN1_SUCCESS: DER encoding OK.
+- *
+- *   %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+- *
+- *   %ASN1_VALUE_NOT_FOUND: There is an element without a value.
+- *
+- *   %ASN1_MEM_ERROR: @ider vector isn't big enough. Also in this case
+- *     LEN will contain the length needed.
++ * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND
++ *   if @name is not a valid element, %ASN1_VALUE_NOT_FOUND if there
++ *   is an element without a value, %ASN1_MEM_ERROR if the @ider
++ *   vector isn't big enough and in this case @len will contain the
++ *   length needed.
+  **/
+-asn1_retCode
++int
+ asn1_der_coding (ASN1_TYPE element, const char *name, void *ider, int *len,
+ 		 char *ErrorDescription)
+ {
+   ASN1_TYPE node, p, p2;
+-  char temp[SIZEOF_UNSIGNED_LONG_INT * 3 + 1];
++  unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)];
+   int counter, counter_old, len2, len3, tlen, move, max_len, max_len_old;
+-  asn1_retCode err;
++  int err;
+   unsigned char *der = ider;
+ 
+   node = asn1_find_node (element, name);
+@@ -1003,7 +1148,8 @@
+ 	    }
+ 	  move = RIGHT;
+ 	  break;
+-	case TYPE_TIME:
++	case TYPE_GENERALIZED_TIME:
++	case TYPE_UTC_TIME:
+ 	  if (p->value == NULL)
+ 	    {
+ 	      _asn1_error_description_value_not_found (p, ErrorDescription);
+@@ -1011,7 +1157,7 @@
+ 	      goto error;
+ 	    }
+ 	  len2 = max_len;
+-	  err = _asn1_time_der (p->value, der + counter, &len2);
++	  err = _asn1_time_der (p->value, p->value_len, der + counter, &len2);
+ 	  if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR)
+ 	    goto error;
+ 
+@@ -1020,43 +1166,15 @@
+ 	  move = RIGHT;
+ 	  break;
+ 	case TYPE_OCTET_STRING:
+-	  if (p->value == NULL)
+-	    {
+-	      _asn1_error_description_value_not_found (p, ErrorDescription);
+-	      err = ASN1_VALUE_NOT_FOUND;
+-	      goto error;
+-	    }
+-	  len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+-	  if (len2 < 0)
+-	    {
+-	      err = ASN1_DER_ERROR;
+-	      goto error;
+-	    }
+-	  max_len -= len2 + len3;
+-	  if (max_len >= 0)
+-	    memcpy (der + counter, p->value, len3 + len2);
+-	  counter += len3 + len2;
+-	  move = RIGHT;
+-	  break;
+ 	case TYPE_GENERALSTRING:
+-	  if (p->value == NULL)
+-	    {
+-	      _asn1_error_description_value_not_found (p, ErrorDescription);
+-	      err = ASN1_VALUE_NOT_FOUND;
+-	      goto error;
+-	    }
+-	  len2 = asn1_get_length_der (p->value, p->value_len, &len3);
+-	  if (len2 < 0)
+-	    {
+-	      err = ASN1_DER_ERROR;
+-	      goto error;
+-	    }
+-	  max_len -= len2 + len3;
+-	  if (max_len >= 0)
+-	    memcpy (der + counter, p->value, len3 + len2);
+-	  counter += len3 + len2;
+-	  move = RIGHT;
+-	  break;
++	case TYPE_NUMERIC_STRING:
++	case TYPE_IA5_STRING:
++	case TYPE_TELETEX_STRING:
++	case TYPE_PRINTABLE_STRING:
++	case TYPE_UNIVERSAL_STRING:
++	case TYPE_BMP_STRING:
++	case TYPE_UTF8_STRING:
++	case TYPE_VISIBLE_STRING:
+ 	case TYPE_BIT_STRING:
+ 	  if (p->value == NULL)
+ 	    {
+@@ -1080,8 +1198,8 @@
+ 	case TYPE_SET:
+ 	  if (move != UP)
+ 	    {
+-	      _asn1_ltostr (counter, temp);
+-	      tlen = strlen (temp);
++	      _asn1_ltostr (counter, (char *) temp);
++	      tlen = _asn1_strlen (temp);
+ 	      if (tlen > 0)
+ 		_asn1_set_value (p, temp, tlen + 1);
+ 	      if (p->down == NULL)
+@@ -1106,10 +1224,14 @@
+ 	    }
+ 	  else
+ 	    {			/* move==UP */
+-	      len2 = strtol (p->value, NULL, 10);
++	      len2 = _asn1_strtol (p->value, NULL, 10);
+ 	      _asn1_set_value (p, NULL, 0);
+ 	      if ((type_field (p->type) == TYPE_SET) && (max_len >= 0))
+-		_asn1_ordering_set (der + len2, max_len - len2, p);
++		{
++		  err = _asn1_ordering_set (der + len2, counter - len2, p);
++		  if (err != ASN1_SUCCESS)
++		    goto error;
++		}
+ 	      asn1_length_der (counter - len2, temp, &len3);
+ 	      max_len -= len3;
+ 	      if (max_len >= 0)
+@@ -1125,8 +1247,8 @@
+ 	case TYPE_SET_OF:
+ 	  if (move != UP)
+ 	    {
+-	      _asn1_ltostr (counter, temp);
+-	      tlen = strlen (temp);
++	      _asn1_ltostr (counter, (char *) temp);
++	      tlen = _asn1_strlen (temp);
+ 
+ 	      if (tlen > 0)
+ 		_asn1_set_value (p, temp, tlen + 1);
+@@ -1146,12 +1268,14 @@
+ 	    }
+ 	  if (move == UP)
+ 	    {
+-	      len2 = strtol (p->value, NULL, 10);
++	      len2 = _asn1_strtol (p->value, NULL, 10);
+ 	      _asn1_set_value (p, NULL, 0);
+ 	      if ((type_field (p->type) == TYPE_SET_OF)
+-		  && (max_len - len2 > 0))
++		  && (counter - len2 > 0) && (max_len >= 0))
+ 		{
+-		  _asn1_ordering_set_of (der + len2, max_len - len2, p);
++		  err = _asn1_ordering_set_of (der + len2, counter - len2, p);
++		  if (err != ASN1_SUCCESS)
++		    goto error;
+ 		}
+ 	      asn1_length_der (counter - len2, temp, &len3);
+ 	      max_len -= len3;
+--- ORIGINAL/./lib/element.h	2015-07-14 18:28:22.926924377 -0700
++++ libtasn1-2.8/./lib/element.h	2015-07-14 18:45:02.724927088 -0700
+@@ -24,11 +24,11 @@
+ #define _ELEMENT_H
+ 
+ 
+-asn1_retCode _asn1_append_sequence_set (ASN1_TYPE node);
++int _asn1_append_sequence_set (ASN1_TYPE node);
+ 
+-asn1_retCode _asn1_convert_integer (const char *value,
+-				    unsigned char *value_out,
+-				    int value_out_size, int *len);
++int _asn1_convert_integer (const unsigned char *value,
++			   unsigned char *value_out,
++			   int value_out_size, int *len);
+ 
+ void _asn1_hierarchical_name (ASN1_TYPE node, char *name, int name_size);
+ 
+--- ORIGINAL/./lib/gstr.c	2015-07-14 18:28:22.922080887 -0700
++++ libtasn1-2.8/./lib/gstr.c	2015-07-14 18:45:02.700823028 -0700
+@@ -49,7 +49,8 @@
+     }
+ }
+ 
+-void
++/* Returns the bytes copied (not including the null terminator) */
++unsigned int
+ _asn1_str_cpy (char *dest, size_t dest_tot_size, const char *src)
+ {
+   size_t str_size = strlen (src);
+@@ -57,13 +58,18 @@
+   if (dest_tot_size > str_size)
+     {
+       strcpy (dest, src);
++      return str_size;
+     }
+   else
+     {
+       if (dest_tot_size > 0)
+ 	{
+-	  strncpy (dest, src, (dest_tot_size) - 1);
+-	  dest[dest_tot_size - 1] = 0;
++	  str_size = dest_tot_size - 1;
++	  memcpy (dest, src, str_size);
++	  dest[str_size] = 0;
++	  return str_size;
+ 	}
++      else
++	return 0;
+     }
+ }
+--- ORIGINAL/./lib/int.h	2015-07-14 18:28:22.934362140 -0700
++++ libtasn1-2.8/./lib/int.h	2015-07-14 18:45:02.741226703 -0700
+@@ -47,7 +47,8 @@
+ struct node_asn_struct
+ {
+   /* public fields: */
+-  char *name;			/* Node name */
++  char name[ASN1_MAX_NAME_SIZE + 1];    /* Node name */
++  unsigned int name_hash;
+   unsigned int type;		/* Node type */
+   unsigned char *value;		/* Node value */
+   int value_len;
+@@ -58,11 +59,53 @@
+   unsigned char small_value[ASN1_SMALL_VALUE_SIZE];	/* For small values */
+ };
+ 
+-#define _asn1_malloc malloc
+-#define _asn1_free free
+-#define _asn1_calloc calloc
+-#define _asn1_realloc realloc
+-#define _asn1_strdup strdup
++typedef struct tag_and_class_st
++{
++  unsigned tag;
++  unsigned class;
++  const char *desc;
++} tag_and_class_st;
++
++/* the types that are handled in _asn1_tags */
++#define CASE_HANDLED_ETYPES \
++        case TYPE_NULL: \
++        case TYPE_BOOLEAN: \
++        case TYPE_INTEGER: \
++        case TYPE_ENUMERATED: \
++        case TYPE_OBJECT_ID: \
++        case TYPE_OCTET_STRING: \
++        case TYPE_GENERALSTRING: \
++        case TYPE_NUMERIC_STRING: \
++        case TYPE_IA5_STRING: \
++        case TYPE_TELETEX_STRING: \
++        case TYPE_PRINTABLE_STRING: \
++        case TYPE_UNIVERSAL_STRING: \
++        case TYPE_BMP_STRING: \
++        case TYPE_UTF8_STRING: \
++        case TYPE_VISIBLE_STRING: \
++        case TYPE_BIT_STRING: \
++        case TYPE_SEQUENCE: \
++        case TYPE_SEQUENCE_OF: \
++        case TYPE_SET: \
++        case TYPE_UTC_TIME: \
++        case TYPE_GENERALIZED_TIME: \
++        case TYPE_SET_OF
++
++#define ETYPE_TAG(etype) (_asn1_tags[etype].tag)
++#define ETYPE_CLASS(etype) (_asn1_tags[etype].class)
++#define ETYPE_OK(etype) ((etype != TYPE_INVALID && \
++                          etype <= _asn1_tags_size && \
++                          _asn1_tags[etype].desc != NULL)?1:0)
++
++extern unsigned int _asn1_tags_size;
++extern const tag_and_class_st _asn1_tags[];
++
++#define _asn1_strlen(s) strlen((const char *) s)
++#define _asn1_strtol(n,e,b) strtol((const char *) n, e, b)
++#define _asn1_strtoul(n,e,b) strtoul((const char *) n, e, b)
++#define _asn1_strcmp(a,b) strcmp((const char *)a, (const char *)b)
++#define _asn1_strcpy(a,b) strcpy((char *)a, (const char *)b)
++#define _asn1_strcat(a,b) strcat((char *)a, (const char *)b)
+ 
+ #define MAX_LOG_SIZE 1024	/* maximum number of characters of a log message */
+ 
+@@ -78,6 +121,7 @@
+ #define type_field(x)     (x&0xFF)
+ 
+ /* List of constants for field type of typedef node_asn  */
++#define TYPE_INVALID        0
+ #define TYPE_CONSTANT       1
+ #define TYPE_IDENTIFIER     2
+ #define TYPE_INTEGER        3
+@@ -100,6 +144,16 @@
+ #define TYPE_NULL          20
+ #define TYPE_ENUMERATED    21
+ #define TYPE_GENERALSTRING 27
++#define TYPE_NUMERIC_STRING 28
++#define TYPE_IA5_STRING     29
++#define TYPE_TELETEX_STRING 30
++#define TYPE_PRINTABLE_STRING 31
++#define TYPE_UNIVERSAL_STRING 32
++#define TYPE_BMP_STRING     33
++#define TYPE_UTF8_STRING    34
++#define TYPE_VISIBLE_STRING 35
++#define TYPE_UTC_TIME       36
++#define TYPE_GENERALIZED_TIME 37
+ 
+ 
+ /***********************************************************************/
+@@ -139,4 +193,28 @@
+ #define CONST_DOWN        (1<<29)
+ #define CONST_RIGHT       (1<<30)
+ 
++#define TYPE_TIME 17
++
++/* To convert old types from a static structure */
++inline static unsigned int
++convert_old_type (unsigned int ntype)
++{
++  unsigned int type = ntype & 0xff;
++  if (type == TYPE_TIME)
++    {
++      if (ntype & CONST_UTC)
++        type = TYPE_UTC_TIME;
++      else
++        type = TYPE_GENERALIZED_TIME;
++
++      ntype &= ~(CONST_UTC | CONST_GENERALIZED);
++      ntype &= 0xffffff00;
++      ntype |= type;
++
++      return ntype;
++    }
++  else
++    return ntype;
++}
++
+ #endif /* INT_H */
+--- ORIGINAL/./lib/parser_aux.h	2015-07-14 18:28:22.924499509 -0700
++++ libtasn1-2.8/./lib/parser_aux.h	2015-07-14 18:45:02.703556709 -0700
+@@ -23,12 +23,10 @@
+ #ifndef _PARSER_AUX_H
+ #define _PARSER_AUX_H
+ 
+-#define DER_LEN 16
+-
+ /***************************************/
+ /*  Functions used by ASN.1 parser     */
+ /***************************************/
+-ASN1_TYPE _asn1_add_node (unsigned int type);
++ASN1_TYPE _asn1_add_static_node (unsigned int type);
+ 
+ ASN1_TYPE
+ _asn1_set_value (ASN1_TYPE node, const void *value, unsigned int len);
+@@ -36,47 +34,125 @@
+ ASN1_TYPE _asn1_set_value_m (ASN1_TYPE node, void *value, unsigned int len);
+ 
+ ASN1_TYPE
+-_asn1_set_value_octet (ASN1_TYPE node, const void *value, unsigned int len);
++_asn1_set_value_lv (ASN1_TYPE node, const void *value, unsigned int len);
+ 
+ ASN1_TYPE
+ _asn1_append_value (ASN1_TYPE node, const void *value, unsigned int len);
+ 
+ ASN1_TYPE _asn1_set_name (ASN1_TYPE node, const char *name);
+ 
+-ASN1_TYPE _asn1_set_right (ASN1_TYPE node, ASN1_TYPE right);
++ASN1_TYPE _asn1_cpy_name (ASN1_TYPE dst, ASN1_TYPE src);
+ 
+-ASN1_TYPE _asn1_get_right (ASN1_TYPE node);
++ASN1_TYPE _asn1_set_right (ASN1_TYPE node, ASN1_TYPE right);
+ 
+ ASN1_TYPE _asn1_get_last_right (ASN1_TYPE node);
+ 
+-ASN1_TYPE _asn1_set_down (ASN1_TYPE node, ASN1_TYPE down);
+-
+-char *_asn1_get_name (ASN1_TYPE node);
+-
+-ASN1_TYPE _asn1_get_down (ASN1_TYPE node);
+-
+-ASN1_TYPE _asn1_mod_type (ASN1_TYPE node, unsigned int value);
+-
+-void _asn1_remove_node (ASN1_TYPE node);
++void _asn1_remove_node (ASN1_TYPE node, unsigned int flags);
+ 
+ void _asn1_delete_list (void);
+ 
+ void _asn1_delete_list_and_nodes (void);
+ 
+-/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */
+-#define LTOSTR_MAX_SIZE 22
+-char *_asn1_ltostr (long v, char str[LTOSTR_MAX_SIZE]);
++#define LTOSTR_MAX_SIZE 20
++char *_asn1_ltostr (long v, char *str);
+ 
+ ASN1_TYPE _asn1_find_up (ASN1_TYPE node);
+ 
+-asn1_retCode _asn1_change_integer_value (ASN1_TYPE node);
++int _asn1_change_integer_value (ASN1_TYPE node);
+ 
+-asn1_retCode _asn1_expand_object_id (ASN1_TYPE node);
++int _asn1_expand_object_id (ASN1_TYPE node);
+ 
+-asn1_retCode _asn1_type_set_config (ASN1_TYPE node);
++int _asn1_type_set_config (ASN1_TYPE node);
+ 
+-asn1_retCode _asn1_check_identifier (ASN1_TYPE node);
++int _asn1_check_identifier (ASN1_TYPE node);
+ 
+-asn1_retCode _asn1_set_default_tag (ASN1_TYPE node);
++int _asn1_set_default_tag (ASN1_TYPE node);
++
++/******************************************************************/
++/* Function : _asn1_get_right                                     */
++/* Description: returns the element pointed by the RIGHT field of */
++/*              a NODE_ASN element.                               */
++/* Parameters:                                                    */
++/*   node: NODE_ASN element pointer.                              */
++/* Return: field RIGHT of NODE.                                   */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_get_right (ASN1_TYPE node)
++{
++  if (node == NULL)
++    return NULL;
++  return node->right;
++}
++
++/******************************************************************/
++/* Function : _asn1_set_down                                      */
++/* Description: sets the field DOWN in a NODE_ASN element.        */
++/* Parameters:                                                    */
++/*   node: element pointer.                                       */
++/*   down: pointer to a NODE_ASN element that you want be pointed */
++/*          by NODE.                                              */
++/* Return: pointer to *NODE.                                      */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_set_down (ASN1_TYPE node, ASN1_TYPE down)
++{
++  if (node == NULL)
++    return node;
++  node->down = down;
++  if (down)
++    down->left = node;
++  return node;
++}
++
++/******************************************************************/
++/* Function : _asn1_get_down                                      */
++/* Description: returns the element pointed by the DOWN field of  */
++/*              a NODE_ASN element.                               */
++/* Parameters:                                                    */
++/*   node: NODE_ASN element pointer.                              */
++/* Return: field DOWN of NODE.                                    */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_get_down (ASN1_TYPE node)
++{
++  if (node == NULL)
++    return NULL;
++  return node->down;
++}
++
++/******************************************************************/
++/* Function : _asn1_get_name                                      */
++/* Description: returns the name of a NODE_ASN element.           */
++/* Parameters:                                                    */
++/*   node: NODE_ASN element pointer.                              */
++/* Return: a null terminated string.                              */
++/******************************************************************/
++inline static char *
++_asn1_get_name (ASN1_TYPE node)
++{
++  if (node == NULL)
++    return NULL;
++  return node->name;
++}
++
++/******************************************************************/
++/* Function : _asn1_mod_type                                      */
++/* Description: change the field TYPE of an NODE_ASN element.     */
++/*              The new value is the old one | (bitwise or) the   */
++/*              paramener VALUE.                                  */
++/* Parameters:                                                    */
++/*   node: NODE_ASN element pointer.                              */
++/*   value: the integer value that must be or-ed with the current */
++/*          value of field TYPE.                                  */
++/* Return: NODE pointer.                                          */
++/******************************************************************/
++inline static ASN1_TYPE
++_asn1_mod_type (ASN1_TYPE node, unsigned int value)
++{
++  if (node == NULL)
++    return node;
++  node->type |= value;
++  return node;
++}
+ 
+ #endif
+--- ORIGINAL/./lib/ASN1.y	2015-07-14 18:28:22.939304180 -0700
++++ libtasn1-2.8/./lib/ASN1.y	2015-07-14 18:45:02.748908645 -0700
+@@ -31,28 +31,33 @@
+ #include <int.h>
+ #include <parser_aux.h>
+ #include <structure.h>
++#include <libtasn1.h>
+ 
+ static FILE *file_asn1;			/* Pointer to file to parse */
+-static asn1_retCode result_parse;	/* result of the parser
++static int result_parse = 0;	/* result of the parser
+ 					   algorithm */
+ static ASN1_TYPE p_tree;		/* pointer to the root of the
+ 					   structure created by the
+ 					   parser*/
+-static unsigned long lineNumber;	/* line number describing the
++static unsigned int line_number;	/* line number describing the
+ 					   parser position inside the
+ 					   file */
+-static char lastToken[ASN1_MAX_NAME_SIZE+1];	/* last token find in the file
++static char last_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
++static char last_error_token[ASN1_MAX_ERROR_DESCRIPTION_SIZE+1] = ""; /* used when expected errors occur */
++static char last_token[ASN1_MAX_NAME_SIZE+1] = ""; /* last token find in the file
+ 					   to parse before the 'parse
+ 					   error' */
+ extern char _asn1_identifierMissing[];
+-static const char *fileName;		/* file to parse */
++static const char *file_name;		/* file to parse */
+ 
+-static int _asn1_yyerror (const char *);
++static void _asn1_yyerror (const char *);
+ static int _asn1_yylex(void);
+ 
+ %}
+ 
+ /* Prefix symbols and functions with _asn1_ */
++/* %define parse.lac full */
++%error-verbose
+ %name-prefix="_asn1_yy"
+ 
+ %union {
+@@ -97,6 +102,15 @@
+ %token UTCTime
+ %token GeneralizedTime
+ %token GeneralString
++%token NumericString
++%token IA5String
++%token TeletexString
++%token PrintableString
++%token UniversalString
++%token BMPString
++%token UTF8String
++%token VisibleString
++
+ %token FROM
+ %token IMPORTS
+ %token ENUMERATED
+@@ -108,9 +122,12 @@
+ %type <node> constant_def type_constant type_constant_list definitions
+ %type <node> definitions_id Time bit_element bit_element_list set_def
+ %type <node> tag_type tag type_assig_right_tag generalstring_def
++%type <node> numericstring_def ia5string_def printablestring_def universalstring_def
++%type <node> bmpstring_def utf8string_def visiblestring_def teletexstring_def
+ %type <node> type_assig_right_tag_default enumerated_def
+ %type <str>  pos_num neg_num pos_neg_num pos_neg_identifier pos_neg_list
+ %type <str>  num_identifier
++%type <str>  int_identifier
+ %type <constant> class explicit_implicit
+ 
+ %%
+@@ -119,7 +136,7 @@
+ definitions:   definitions_id
+                DEFINITIONS explicit_implicit TAGS "::=" BEGIN  /* imports_def */
+                type_constant_list END
+-                   {$$=_asn1_add_node(TYPE_DEFINITIONS|$3);
++                   {$$=_asn1_add_static_node(TYPE_DEFINITIONS|$3);
+                     _asn1_set_name($$,_asn1_get_name($1));
+                     _asn1_set_name($1,"");
+                     _asn1_set_right($1,$7);
+@@ -129,29 +146,33 @@
+ 		    }
+ ;
+ 
+-pos_num :   NUM       {strcpy($$,$1);}
+-          | '+' NUM   {strcpy($$,$2);}
++pos_num :   NUM       {snprintf($$,sizeof($$),"%s",$1);}
++          | '+' NUM   {snprintf($$,sizeof($$),"%s",$2);}
++;
++
++neg_num : '-' NUM     {snprintf($$,sizeof($$),"-%s",$2);}
+ ;
+ 
+-neg_num : '-' NUM     {strcpy($$,"-");
+-                       strcat($$,$2);}
++pos_neg_num :  pos_num  {snprintf($$,sizeof($$),"%s",$1);}
++             | neg_num  {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+ 
+-pos_neg_num :  pos_num  {strcpy($$,$1);}
+-             | neg_num  {strcpy($$,$1);}
++num_identifier :  NUM            {snprintf($$,sizeof($$),"%s",$1);}
++                | IDENTIFIER     {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+ 
+-num_identifier :  NUM            {strcpy($$,$1);}
+-                | IDENTIFIER     {strcpy($$,$1);}
++int_identifier :  NUM            {snprintf($$,sizeof($$),"%s",$1);}
++                | '-' NUM        {snprintf($$,sizeof($$),"-%s",$2);}
++                | IDENTIFIER     {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+ 
+-pos_neg_identifier :  pos_neg_num    {strcpy($$,$1);}
+-                    | IDENTIFIER     {strcpy($$,$1);}
++pos_neg_identifier :  pos_neg_num    {snprintf($$,sizeof($$),"%s",$1);}
++                    | IDENTIFIER     {snprintf($$,sizeof($$),"%s",$1);}
+ ;
+ 
+-constant: '(' pos_neg_num ')'         {$$=_asn1_add_node(TYPE_CONSTANT);
++constant: '(' pos_neg_num ')'         {$$=_asn1_add_static_node(TYPE_CONSTANT);
+                                        _asn1_set_value($$,$2,strlen($2)+1);}
+-        | IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_node(TYPE_CONSTANT);
++        | IDENTIFIER'('pos_neg_num')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ 	                               _asn1_set_name($$,$1);
+                                        _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+@@ -161,9 +182,9 @@
+                                             _asn1_set_right(_asn1_get_last_right($1),$3);}
+ ;
+ 
+-obj_constant:  num_identifier     {$$=_asn1_add_node(TYPE_CONSTANT);
++obj_constant:  num_identifier     {$$=_asn1_add_static_node(TYPE_CONSTANT);
+                                    _asn1_set_value($$,$1,strlen($1)+1);}
+-             | IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT);
++             | IDENTIFIER'('NUM')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ 	                            _asn1_set_name($$,$1);
+                                     _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+@@ -178,9 +199,9 @@
+        | APPLICATION  {$$=CONST_APPLICATION;}
+ ;
+ 
+-tag_type :  '[' NUM ']'    {$$=_asn1_add_node(TYPE_TAG);
++tag_type :  '[' NUM ']'    {$$=_asn1_add_static_node(TYPE_TAG);
+                             _asn1_set_value($$,$2,strlen($2)+1);}
+-          | '[' class NUM ']'  {$$=_asn1_add_node(TYPE_TAG | $2);
++          | '[' class NUM ']'  {$$=_asn1_add_static_node(TYPE_TAG | $2);
+                                 _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+ 
+@@ -189,10 +210,10 @@
+      | tag_type IMPLICIT  {$$=_asn1_mod_type($1,CONST_IMPLICIT);}
+ ;
+ 
+-default :  DEFAULT pos_neg_identifier {$$=_asn1_add_node(TYPE_DEFAULT);
++default :  DEFAULT pos_neg_identifier {$$=_asn1_add_static_node(TYPE_DEFAULT);
+                                        _asn1_set_value($$,$2,strlen($2)+1);}
+-         | DEFAULT ASN1_TRUE           {$$=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
+-         | DEFAULT ASN1_FALSE          {$$=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
++         | DEFAULT ASN1_TRUE           {$$=_asn1_add_static_node(TYPE_DEFAULT|CONST_TRUE);}
++         | DEFAULT ASN1_FALSE          {$$=_asn1_add_static_node(TYPE_DEFAULT|CONST_FALSE);}
+ ;
+ 
+ 
+@@ -201,28 +222,28 @@
+ ;
+ 
+ 
+-integer_def: INTEGER                    {$$=_asn1_add_node(TYPE_INTEGER);}
+-           | INTEGER'{'constant_list'}' {$$=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
++integer_def: INTEGER                    {$$=_asn1_add_static_node(TYPE_INTEGER);}
++           | INTEGER'{'constant_list'}' {$$=_asn1_add_static_node(TYPE_INTEGER|CONST_LIST);
+ 	                                 _asn1_set_down($$,$3);}
+-           | integer_def'(' pos_neg_list ')' {$$=_asn1_add_node(TYPE_INTEGER);}
+-           | integer_def'('num_identifier'.''.'num_identifier')'
+-                                        {$$=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX);
+-                                         _asn1_set_down($$,_asn1_add_node(TYPE_SIZE));
++           | integer_def'(' pos_neg_list ')' {$$=_asn1_add_static_node(TYPE_INTEGER);}
++           | integer_def'('int_identifier'.''.'int_identifier')'
++                                        {$$=_asn1_add_static_node(TYPE_INTEGER|CONST_MIN_MAX);
++                                         _asn1_set_down($$,_asn1_add_static_node(TYPE_SIZE));
+                                          _asn1_set_value(_asn1_get_down($$),$6,strlen($6)+1);
+                                          _asn1_set_name(_asn1_get_down($$),$3);}
+ ;
+ 
+-boolean_def: BOOLEAN   {$$=_asn1_add_node(TYPE_BOOLEAN);}
++boolean_def: BOOLEAN   {$$=_asn1_add_static_node(TYPE_BOOLEAN);}
+ ;
+ 
+-Time:   UTCTime          {$$=_asn1_add_node(TYPE_TIME|CONST_UTC);}
+-      | GeneralizedTime  {$$=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);}
++Time:   UTCTime          {$$=_asn1_add_static_node(TYPE_UTC_TIME);}
++      | GeneralizedTime  {$$=_asn1_add_static_node(TYPE_GENERALIZED_TIME);}
+ ;
+ 
+-size_def2: SIZE'('num_identifier')'  {$$=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM);
++size_def2: SIZE'('num_identifier')'  {$$=_asn1_add_static_node(TYPE_SIZE|CONST_1_PARAM);
+ 	                              _asn1_set_value($$,$3,strlen($3)+1);}
+         | SIZE'('num_identifier'.''.'num_identifier')'
+-                                     {$$=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX);
++                                     {$$=_asn1_add_static_node(TYPE_SIZE|CONST_MIN_MAX);
+ 	                              _asn1_set_value($$,$3,strlen($3)+1);
+                                       _asn1_set_name($$,$6);}
+ ;
+@@ -231,17 +252,57 @@
+           | '(' size_def2 ')'  {$$=$2;}
+ ;
+ 
+-generalstring_def: GeneralString {$$=_asn1_add_node(TYPE_GENERALSTRING);}
+-                | GeneralString size_def {$$=_asn1_add_node(TYPE_GENERALSTRING|CONST_SIZE);
++generalstring_def: GeneralString {$$=_asn1_add_static_node(TYPE_GENERALSTRING);}
++                | GeneralString size_def {$$=_asn1_add_static_node(TYPE_GENERALSTRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++numericstring_def: NumericString {$$=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_UNIVERSAL);}
++                | NumericString size_def {$$=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++ia5string_def: IA5String {$$=_asn1_add_static_node(TYPE_IA5_STRING);}
++                | IA5String size_def {$$=_asn1_add_static_node(TYPE_IA5_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++teletexstring_def: TeletexString {$$=_asn1_add_static_node(TYPE_TELETEX_STRING);}
++                | TeletexString size_def {$$=_asn1_add_static_node(TYPE_TELETEX_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++printablestring_def: PrintableString {$$=_asn1_add_static_node(TYPE_PRINTABLE_STRING);}
++                | PrintableString size_def {$$=_asn1_add_static_node(TYPE_PRINTABLE_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++universalstring_def: UniversalString {$$=_asn1_add_static_node(TYPE_UNIVERSAL_STRING);}
++                | UniversalString size_def {$$=_asn1_add_static_node(TYPE_UNIVERSAL_STRING|CONST_SIZE);
+ 					  _asn1_set_down($$,$2);}
+ ;
+ 
+-octet_string_def : OCTET STRING           {$$=_asn1_add_node(TYPE_OCTET_STRING);}
+-                 | OCTET STRING size_def  {$$=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
++bmpstring_def: BMPString {$$=_asn1_add_static_node(TYPE_BMP_STRING);}
++                | BMPString size_def {$$=_asn1_add_static_node(TYPE_BMP_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++utf8string_def: UTF8String {$$=_asn1_add_static_node(TYPE_UTF8_STRING);}
++                | UTF8String size_def {$$=_asn1_add_static_node(TYPE_UTF8_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++visiblestring_def: VisibleString {$$=_asn1_add_static_node(TYPE_VISIBLE_STRING);}
++                | VisibleString size_def {$$=_asn1_add_static_node(TYPE_VISIBLE_STRING|CONST_SIZE);
++					  _asn1_set_down($$,$2);}
++;
++
++octet_string_def : OCTET STRING           {$$=_asn1_add_static_node(TYPE_OCTET_STRING);}
++                 | OCTET STRING size_def  {$$=_asn1_add_static_node(TYPE_OCTET_STRING|CONST_SIZE);
+                                            _asn1_set_down($$,$3);}
+ ;
+ 
+-bit_element :  IDENTIFIER'('NUM')' {$$=_asn1_add_node(TYPE_CONSTANT);
++bit_element :  IDENTIFIER'('NUM')' {$$=_asn1_add_static_node(TYPE_CONSTANT);
+ 	                           _asn1_set_name($$,$1);
+                                     _asn1_set_value($$,$3,strlen($3)+1);}
+ ;
+@@ -251,25 +312,25 @@
+                                                        _asn1_set_right(_asn1_get_last_right($1),$3);}
+ ;
+ 
+-bit_string_def : BIT STRING    {$$=_asn1_add_node(TYPE_BIT_STRING);}
+-               | BIT STRING size_def {$$=_asn1_add_node(TYPE_BIT_STRING|CONST_SIZE);}
++bit_string_def : BIT STRING    {$$=_asn1_add_static_node(TYPE_BIT_STRING);}
++               | BIT STRING size_def {$$=_asn1_add_static_node(TYPE_BIT_STRING|CONST_SIZE);}
+                | BIT STRING'{'bit_element_list'}'
+-                               {$$=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
++                               {$$=_asn1_add_static_node(TYPE_BIT_STRING|CONST_LIST);
+                                 _asn1_set_down($$,$4);}
+ ;
+ 
+ enumerated_def : ENUMERATED'{'bit_element_list'}'
+-                               {$$=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
++                               {$$=_asn1_add_static_node(TYPE_ENUMERATED|CONST_LIST);
+                                 _asn1_set_down($$,$3);}
+ ;
+ 
+ 
+-object_def :  OBJECT STR_IDENTIFIER {$$=_asn1_add_node(TYPE_OBJECT_ID);}
++object_def :  OBJECT STR_IDENTIFIER {$$=_asn1_add_static_node(TYPE_OBJECT_ID);}
+ ;
+ 
+-type_assig_right: IDENTIFIER          {$$=_asn1_add_node(TYPE_IDENTIFIER);
++type_assig_right: IDENTIFIER          {$$=_asn1_add_static_node(TYPE_IDENTIFIER);
+                                        _asn1_set_value($$,$1,strlen($1)+1);}
+-                | IDENTIFIER size_def {$$=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE);
++                | IDENTIFIER size_def {$$=_asn1_add_static_node(TYPE_IDENTIFIER|CONST_SIZE);
+                                        _asn1_set_value($$,$1,strlen($1)+1);
+                                        _asn1_set_down($$,$2);}
+                 | integer_def         {$$=$1;}
+@@ -279,12 +340,20 @@
+                 | octet_string_def    {$$=$1;}
+                 | bit_string_def      {$$=$1;}
+                 | generalstring_def   {$$=$1;}
++                | numericstring_def   {$$=$1;}
++                | ia5string_def       {$$=$1;}
++                | teletexstring_def   {$$=$1;}
++                | printablestring_def {$$=$1;}
++                | universalstring_def {$$=$1;}
++                | bmpstring_def       {$$=$1;}
++                | utf8string_def      {$$=$1;}
++                | visiblestring_def   {$$=$1;}
+                 | sequence_def        {$$=$1;}
+                 | object_def          {$$=$1;}
+                 | choise_def          {$$=$1;}
+                 | any_def             {$$=$1;}
+                 | set_def             {$$=$1;}
+-                | TOKEN_NULL          {$$=_asn1_add_node(TYPE_NULL);}
++                | TOKEN_NULL          {$$=_asn1_add_static_node(TYPE_NULL);}
+ ;
+ 
+ type_assig_right_tag :   type_assig_right     {$$=$1;}
+@@ -308,48 +377,50 @@
+                                                 _asn1_set_right(_asn1_get_last_right($1),$3);}
+ ;
+ 
+-sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SEQUENCE);
++sequence_def : SEQUENCE'{'type_assig_list'}' {$$=_asn1_add_static_node(TYPE_SEQUENCE);
+                                               _asn1_set_down($$,$3);}
+-   | SEQUENCE OF type_assig_right            {$$=_asn1_add_node(TYPE_SEQUENCE_OF);
++   | SEQUENCE OF type_assig_right            {$$=_asn1_add_static_node(TYPE_SEQUENCE_OF);
+                                               _asn1_set_down($$,$3);}
+-   | SEQUENCE size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE);
++   | SEQUENCE size_def OF type_assig_right {$$=_asn1_add_static_node(TYPE_SEQUENCE_OF|CONST_SIZE);
+                                             _asn1_set_right($2,$4);
+                                             _asn1_set_down($$,$2);}
+ ;
+ 
+-set_def :  SET'{'type_assig_list'}' {$$=_asn1_add_node(TYPE_SET);
++set_def :  SET'{'type_assig_list'}' {$$=_asn1_add_static_node(TYPE_SET);
+                                      _asn1_set_down($$,$3);}
+-   | SET OF type_assig_right        {$$=_asn1_add_node(TYPE_SET_OF);
++   | SET OF type_assig_right        {$$=_asn1_add_static_node(TYPE_SET_OF);
+                                      _asn1_set_down($$,$3);}
+-   | SET size_def OF type_assig_right {$$=_asn1_add_node(TYPE_SET_OF|CONST_SIZE);
++   | SET size_def OF type_assig_right {$$=_asn1_add_static_node(TYPE_SET_OF|CONST_SIZE);
+                                        _asn1_set_right($2,$4);
+                                        _asn1_set_down($$,$2);}
+ ;
+ 
+-choise_def :   CHOICE'{'type_assig_list'}'  {$$=_asn1_add_node(TYPE_CHOICE);
++choise_def :   CHOICE'{'type_assig_list'}'  {$$=_asn1_add_static_node(TYPE_CHOICE);
+                                              _asn1_set_down($$,$3);}
+ ;
+ 
+-any_def :  ANY                         {$$=_asn1_add_node(TYPE_ANY);}
+-         | ANY DEFINED BY IDENTIFIER   {$$=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY);
+-                                        _asn1_set_down($$,_asn1_add_node(TYPE_CONSTANT));
++any_def :  ANY                         {$$=_asn1_add_static_node(TYPE_ANY);}
++         | ANY DEFINED BY IDENTIFIER   {$$=_asn1_add_static_node(TYPE_ANY|CONST_DEFINED_BY);
++                                        _asn1_set_down($$,_asn1_add_static_node(TYPE_CONSTANT));
+ 	                                _asn1_set_name(_asn1_get_down($$),$4);}
+ ;
+ 
+ type_def : IDENTIFIER "::=" type_assig_right_tag  {$$=_asn1_set_name($3,$1);}
++              /* below should match: BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING etc*/
++              | error "::=" type_assig_right_tag {$$=_asn1_set_name($3, last_error_token);}
+ ;
+ 
+ constant_def :  IDENTIFIER OBJECT STR_IDENTIFIER "::=" '{'obj_constant_list'}'
+-                        {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN);
++                        {$$=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN);
+                          _asn1_set_name($$,$1);
+                          _asn1_set_down($$,$6);}
+               | IDENTIFIER IDENTIFIER "::=" '{' obj_constant_list '}'
+-                        {$$=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
++                        {$$=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
+                          _asn1_set_name($$,$1);
+                          _asn1_set_value($$,$2,strlen($2)+1);
+                          _asn1_set_down($$,$5);}
+               | IDENTIFIER INTEGER "::=" pos_neg_num
+-                        {$$=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN);
++                        {$$=_asn1_add_static_node(TYPE_INTEGER|CONST_ASSIGN);
+                          _asn1_set_name($$,$1);
+                          _asn1_set_value($$,$4,strlen($4)+1);}
+ ;
+@@ -363,27 +434,29 @@
+                                                           _asn1_set_right(_asn1_get_last_right($1),$2);}
+ ;
+ 
+-definitions_id  :  IDENTIFIER  '{' obj_constant_list '}' {$$=_asn1_add_node(TYPE_OBJECT_ID);
++definitions_id  :  IDENTIFIER  '{' obj_constant_list '}' {$$=_asn1_add_static_node(TYPE_OBJECT_ID);
+                                                           _asn1_set_down($$,$3);
+                                                           _asn1_set_name($$,$1);}
+-                 | IDENTIFIER  '{' '}'                   {$$=_asn1_add_node(TYPE_OBJECT_ID);
++                 | IDENTIFIER  '{' '}'                   {$$=_asn1_add_static_node(TYPE_OBJECT_ID);
++                                                          _asn1_set_name($$,$1);}
++                 | IDENTIFIER                            {$$=_asn1_add_static_node(TYPE_OBJECT_ID);
+                                                           _asn1_set_name($$,$1);}
+ ;
+ 
+ /*
+-identifier_list  :  IDENTIFIER  {$$=_asn1_add_node(TYPE_IDENTIFIER);
++identifier_list  :  IDENTIFIER  {$$=_asn1_add_static_node(TYPE_IDENTIFIER);
+                                  _asn1_set_name($$,$1);}
+                   | identifier_list IDENTIFIER
+                                 {$$=$1;
+-                                 _asn1_set_right(_asn1_get_last_right($$),_asn1_add_node(TYPE_IDENTIFIER));
++                                 _asn1_set_right(_asn1_get_last_right($$),_asn1_add_static_node(TYPE_IDENTIFIER));
+                                  _asn1_set_name(_asn1_get_last_right($$),$2);}
+ ;
+ 
+ 
+ imports_def :    empty   {$$=NULL;}
+               | IMPORTS identifier_list FROM IDENTIFIER obj_constant_list
+-                        {$$=_asn1_add_node(TYPE_IMPORTS);
+-                         _asn1_set_down($$,_asn1_add_node(TYPE_OBJECT_ID));
++                        {$$=_asn1_add_static_node(TYPE_IMPORTS);
++                         _asn1_set_down($$,_asn1_add_static_node(TYPE_OBJECT_ID));
+                          _asn1_set_name(_asn1_get_down($$),$4);
+                          _asn1_set_down(_asn1_get_down($$),$5);
+                          _asn1_set_right($$,$2);}
+@@ -400,21 +473,25 @@
+ 
+ 
+ static const char *key_word[] = {
+-  "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING"
+-  ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL"
+-  ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER"
+-  ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED"
+-  ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS"
+-  ,"BEGIN","END","UTCTime","GeneralizedTime"
+-  ,"GeneralString","FROM","IMPORTS","NULL","ENUMERATED"};
++  "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING",
++  "SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL",
++  "DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER",
++  "BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED",
++  "SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS",
++  "BEGIN","END","UTCTime","GeneralizedTime",
++  "GeneralString","FROM","IMPORTS","NULL","ENUMERATED",
++  "NumericString", "IA5String", "TeletexString", "PrintableString",
++  "UniversalString", "BMPString", "UTF8String", "VisibleString"};
++
+ static const int key_word_token[] = {
+-  ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING
+-  ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL
+-  ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER
+-  ,BOOLEAN,ASN1_TRUE,ASN1_FALSE,APPLICATION,ANY,DEFINED
+-  ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS
+-  ,BEGIN,END,UTCTime,GeneralizedTime
+-  ,GeneralString,FROM,IMPORTS,TOKEN_NULL,ENUMERATED};
++  ASSIG, OPTIONAL, INTEGER, SIZE, OCTET, STRING, SEQUENCE, BIT, UNIVERSAL,
++      PRIVATE, OPTIONAL, DEFAULT, CHOICE, OF, OBJECT, STR_IDENTIFIER,
++      BOOLEAN, ASN1_TRUE, ASN1_FALSE, APPLICATION, ANY, DEFINED, SET, BY,
++      EXPLICIT, IMPLICIT, DEFINITIONS, TAGS, BEGIN, END, UTCTime,
++      GeneralizedTime, GeneralString, FROM, IMPORTS, TOKEN_NULL,
++      ENUMERATED, NumericString, IA5String, TeletexString, PrintableString,
++      UniversalString, BMPString, UTF8String, VisibleString
++};
+ 
+ /*************************************************************/
+ /*  Function: _asn1_yylex                                    */
+@@ -423,83 +500,98 @@
+ /*    Token identifier or ASCII code or 0(zero: End Of File) */
+ /*************************************************************/
+ static int
+-_asn1_yylex()
++_asn1_yylex ()
+ {
+-  int c,counter=0,k,lastc;
+-  char string[ASN1_MAX_NAME_SIZE+1]; /* will contain the next token */
++  int c, counter = 0, k, lastc;
++  char string[ASN1_MAX_NAME_SIZE + 1];  /* will contain the next token */
+   size_t i;
+ 
+-  while(1)
++  while (1)
+     {
+-    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+-      if(c=='\n') lineNumber++;
+-
+-    if(c==EOF){
+-      strcpy(lastToken,"End Of File");
+-      return 0;
+-    }
+-
+-    if(c=='(' || c==')' || c=='[' || c==']' ||
+-       c=='{' || c=='}' || c==',' || c=='.' ||
+-       c=='+' || c=='|'){
+-      lastToken[0]=c;lastToken[1]=0;
+-      return c;
+-    }
+-    if(c=='-'){  /* Maybe the first '-' of a comment */
+-      if((c=fgetc(file_asn1))!='-'){
+-	ungetc(c,file_asn1);
+-	lastToken[0]='-';lastToken[1]=0;
+-	return '-';
+-      }
+-      else{ /* Comments */
+-	lastc=0;
+-	counter=0;
+-	/* A comment finishes at the next double hypen or the end of line */
+-	while((c=fgetc(file_asn1))!=EOF && c!='\n' &&
+-	      (lastc!='-' || (lastc=='-' && c!='-')))
+-	  lastc=c;
+-	if(c==EOF){
+-	  strcpy(lastToken,"End Of File");
+-	  return 0;
+-	}
+-	else{
+-	  if(c=='\n') lineNumber++;
+-	  continue; /* next char, please! (repeat the search) */
+-	}
+-      }
+-    }
+-    string[counter++]=c;
+-    /* Till the end of the token */
+-    while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' ||
+-	     c=='(' || c==')' || c=='[' || c==']' ||
+-	     c=='{' || c=='}' || c==',' || c=='.'))
+-      {
+-	if(counter>=ASN1_MAX_NAME_SIZE){
+-	  result_parse=ASN1_NAME_TOO_LONG;
+-	  return 0;
+-	}
+-	string[counter++]=c;
+-      }
+-    ungetc(c,file_asn1);
+-    string[counter]=0;
+-    strcpy(lastToken,string);
+-
+-    /* Is STRING a number? */
+-    for(k=0;k<counter;k++)
+-      if(!isdigit(string[k])) break;
+-    if(k>=counter)
+-      {
+-      strcpy(yylval.str,string);
+-      return NUM; /* return the number */
+-      }
+-
+-    /* Is STRING a keyword? */
+-    for(i=0;i<(sizeof(key_word)/sizeof(char*));i++)
+-      if(!strcmp(string,key_word[i])) return key_word_token[i];
+-
+-    /* STRING is an IDENTIFIER */
+-    strcpy(yylval.str,string);
+-    return IDENTIFIER;
++      while ((c = fgetc (file_asn1)) == ' ' || c == '\t' || c == '\n')
++        if (c == '\n')
++          line_number++;
++
++      if (c == EOF)
++        {
++          snprintf (last_token, sizeof(last_token), "End Of File");
++          return 0;
++        }
++
++      if (c == '(' || c == ')' || c == '[' || c == ']' ||
++          c == '{' || c == '}' || c == ',' || c == '.' ||
++          c == '+' || c == '|')
++        {
++          last_token[0] = c;
++          last_token[1] = 0;
++          return c;
++        }
++      if (c == '-')
++        {                       /* Maybe the first '-' of a comment */
++          if ((c = fgetc (file_asn1)) != '-')
++            {
++              ungetc (c, file_asn1);
++              last_token[0] = '-';
++              last_token[1] = 0;
++              return '-';
++            }
++          else
++            {                   /* Comments */
++              lastc = 0;
++              counter = 0;
++              /* A comment finishes at the next double hypen or the end of line */
++              while ((c = fgetc (file_asn1)) != EOF && c != '\n' &&
++                     (lastc != '-' || (lastc == '-' && c != '-')))
++                lastc = c;
++              if (c == EOF)
++                {
++                  snprintf (last_token, sizeof(last_token), "End Of File");
++                  return 0;
++                }
++              else
++                {
++                  if (c == '\n')
++                    line_number++;
++                  continue;     /* next char, please! (repeat the search) */
++                }
++            }
++        }
++      string[counter++] = c;
++      /* Till the end of the token */
++      while (!
++             ((c = fgetc (file_asn1)) == EOF || c == ' ' || c == '\t'
++              || c == '\n' || c == '(' || c == ')' || c == '[' || c == ']'
++              || c == '{' || c == '}' || c == ',' || c == '.'))
++        {
++          if (counter >= ASN1_MAX_NAME_SIZE)
++            {
++              result_parse = ASN1_NAME_TOO_LONG;
++              return 0;
++            }
++          string[counter++] = c;
++        }
++      ungetc (c, file_asn1);
++      string[counter] = 0;
++      snprintf (last_token, sizeof(last_token), "%s", string);
++
++      /* Is STRING a number? */
++      for (k = 0; k < counter; k++)
++        if (!isdigit (string[k]))
++          break;
++      if (k >= counter)
++        {
++          snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++          return NUM;           /* return the number */
++        }
++
++      /* Is STRING a keyword? */
++      for (i = 0; i < (sizeof (key_word) / sizeof (char *)); i++)
++        if (!strcmp (string, key_word[i]))
++          return key_word_token[i];
++
++      /* STRING is an IDENTIFIER */
++      snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++      return IDENTIFIER;
+     }
+ }
+ 
+@@ -509,136 +601,121 @@
+ /*    error.                                                 */
+ /*  Parameters:                                              */
+ /*    error : error to describe.                             */
+-/*    errorDescription: string that will contain the         */
++/*    error_desc: string that will contain the         */
+ /*                      description.                         */
+ /*************************************************************/
+ static void
+-_asn1_create_errorDescription(int error,char *errorDescription)
++_asn1_create_errorDescription (int error, char *error_desc)
+ {
+-  switch(error){
+-  case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND:
+-    if (errorDescription!=NULL) errorDescription[0]=0;
+-    break;
+-  case ASN1_SYNTAX_ERROR:
+-    if (errorDescription!=NULL) {
+-	strcpy(errorDescription,fileName);
+-	strcat(errorDescription,":");
+-	_asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+-	strcat(errorDescription,": parse error near '");
+-	strcat(errorDescription,lastToken);
+-	strcat(errorDescription,"'");
+-    }
+-    break;
+-  case ASN1_NAME_TOO_LONG:
+-    if (errorDescription!=NULL) {
+-       strcpy(errorDescription,fileName);
+-       strcat(errorDescription,":");
+-       _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+-       strcat(errorDescription,": name too long (more than ");
+-       _asn1_ltostr(ASN1_MAX_NAME_SIZE,errorDescription+strlen(errorDescription));
+-       strcat(errorDescription," characters)");
+-    }
+-    break;
+-  case ASN1_IDENTIFIER_NOT_FOUND:
+-    if (errorDescription!=NULL) {
+-       strcpy(errorDescription,fileName);
+-       strcat(errorDescription,":");
+-       strcat(errorDescription,": identifier '");
+-       strcat(errorDescription,_asn1_identifierMissing);
+-       strcat(errorDescription,"' not found");
++  if (error_desc == NULL)
++    return;
++
++
++  switch (error)
++    {
++    case ASN1_FILE_NOT_FOUND:
++      snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s file was not found", file_name);
++      break;
++    case ASN1_SYNTAX_ERROR:
++      snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_error);
++      break;
++    case ASN1_NAME_TOO_LONG:
++      snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++                "%s:%u: name too long (more than %u characters)", file_name,
++                line_number, ASN1_MAX_NAME_SIZE);
++      break;
++    case ASN1_IDENTIFIER_NOT_FOUND:
++      snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++                "%s:: identifier '%s' not found", file_name,
++                _asn1_identifierMissing);
++      break;
++    default:
++      error_desc[0] = 0;
++      break;
+     }
+-    break;
+-  default:
+-    if (errorDescription!=NULL) errorDescription[0]=0;
+-    break;
+-  }
+ 
+ }
+ 
+ /**
+  * asn1_parser2tree:
+- * @file_name: specify the path and the name of file that contains
++ * @file: specify the path and the name of file that contains
+  *   ASN.1 declarations.
+  * @definitions: return the pointer to the structure created from
+- *   "file_name" ASN.1 declarations.
+- * @errorDescription: return the error description or an empty
++ *   "file" ASN.1 declarations.
++ * @error_desc: return the error description or an empty
+  * string if success.
+  *
+  * Function used to start the parse algorithm.  Creates the structures
+- * needed to manage the definitions included in @file_name file.
+- *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- * is known.
+- *
+- * %ASN1_ELEMENT_NOT_EMPTY: @definitions not %ASN1_TYPE_EMPTY.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @file_name.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
++ * needed to manage the definitions included in @file file.
+  *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- * than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ *   identifier is known, %ASN1_ELEMENT_NOT_EMPTY if @definitions not
++ *   %NULL, %ASN1_FILE_NOT_FOUND if an error occured while
++ *   opening @file, %ASN1_SYNTAX_ERROR if the syntax is not
++ *   correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an
++ *   identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ *   file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ *   characters.
+  **/
+-asn1_retCode
+-asn1_parser2tree(const char *file_name, ASN1_TYPE *definitions,
+-		 char *errorDescription){
++int
++asn1_parser2tree (const char *file, ASN1_TYPE * definitions,
++                  char *error_desc)
++{
+ 
+-  p_tree=ASN1_TYPE_EMPTY;
++  p_tree = NULL;
+ 
+-  if(*definitions != ASN1_TYPE_EMPTY)
++  if (*definitions != NULL)
+     return ASN1_ELEMENT_NOT_EMPTY;
+ 
+-  *definitions=ASN1_TYPE_EMPTY;
++  *definitions = NULL;
+ 
+-  fileName = file_name;
++  file_name = file;
+ 
+   /* open the file to parse */
+-  file_asn1=fopen(file_name,"r");
++  file_asn1 = fopen (file, "r");
+ 
+-  if(file_asn1==NULL){
+-    result_parse=ASN1_FILE_NOT_FOUND;
+-  }
+-  else{
+-    result_parse=ASN1_SUCCESS;
+-
+-    lineNumber=1;
+-    yyparse();
+-
+-    fclose(file_asn1);
+-
+-    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+-      /* set IMPLICIT or EXPLICIT property */
+-      _asn1_set_default_tag(p_tree);
+-      /* set CONST_SET and CONST_NOT_USED */
+-      _asn1_type_set_config(p_tree);
+-      /* check the identifier definitions */
+-      result_parse=_asn1_check_identifier(p_tree);
+-      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+-	/* Delete the list and keep the ASN1 structure */
+-	_asn1_delete_list();
+-	/* Convert into DER coding the value assign to INTEGER constants */
+-	_asn1_change_integer_value(p_tree);
+-	/* Expand the IDs of OBJECT IDENTIFIER constants */
+-	_asn1_expand_object_id(p_tree);
+-
+-	*definitions=p_tree;
+-      }
+-      else /* some identifiers not defined */
+-	/* Delete the list and the ASN1 structure */
+-	_asn1_delete_list_and_nodes();
++  if (file_asn1 == NULL)
++    {
++      result_parse = ASN1_FILE_NOT_FOUND;
++    }
++  else
++    {
++      result_parse = ASN1_SUCCESS;
++
++      line_number = 1;
++      yyparse ();
++
++      fclose (file_asn1);
++
++      if (result_parse == ASN1_SUCCESS)
++        {                       /* syntax OK */
++          /* set IMPLICIT or EXPLICIT property */
++          _asn1_set_default_tag (p_tree);
++          /* set CONST_SET and CONST_NOT_USED */
++          _asn1_type_set_config (p_tree);
++          /* check the identifier definitions */
++          result_parse = _asn1_check_identifier (p_tree);
++          if (result_parse == ASN1_SUCCESS)
++            {                   /* all identifier defined */
++              /* Delete the list and keep the ASN1 structure */
++              _asn1_delete_list ();
++              /* Convert into DER coding the value assign to INTEGER constants */
++              _asn1_change_integer_value (p_tree);
++              /* Expand the IDs of OBJECT IDENTIFIER constants */
++              _asn1_expand_object_id (p_tree);
++
++              *definitions = p_tree;
++            }
++          else                  /* some identifiers not defined */
++            /* Delete the list and the ASN1 structure */
++            _asn1_delete_list_and_nodes ();
++        }
++      else                      /* syntax error */
++        /* Delete the list and the ASN1 structure */
++        _asn1_delete_list_and_nodes ();
+     }
+-    else  /* syntax error */
+-      /* Delete the list and the ASN1 structure */
+-      _asn1_delete_list_and_nodes();
+-  }
+ 
+-  if (errorDescription!=NULL)
+-	_asn1_create_errorDescription(result_parse,errorDescription);
++  _asn1_create_errorDescription (result_parse, error_desc);
+ 
+   return result_parse;
+ }
+@@ -650,7 +727,7 @@
+  * @outputFileName: specify the path and the name of file that will
+  *   contain the C vector definition.
+  * @vectorName: specify the name of the C vector.
+- * @errorDescription : return the error description or an empty
++ * @error_desc: return the error description or an empty
+  *   string if success.
+  *
+  * Function that generates a C structure from an ASN1 file.  Creates a
+@@ -660,113 +737,118 @@
+  * "/aa/bb/xx_asn1_tab.c".  If @vectorName is %NULL the vector name
+  * will be "xx_asn1_tab".
+  *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- *   is known.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @inputFileName.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- *   is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- *   than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ *   identifier is known, %ASN1_FILE_NOT_FOUND if an error occured
++ *   while opening @inputFileName, %ASN1_SYNTAX_ERROR if the syntax is
++ *   not correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is
++ *   an identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ *   file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ *   characters.
+  **/
+-int asn1_parser2array(const char *inputFileName,const char *outputFileName,
+-		      const char *vectorName,char *errorDescription){
+-  char *file_out_name=NULL;
+-  char *vector_name=NULL;
+-  const char *char_p,*slash_p,*dot_p;
++int
++asn1_parser2array (const char *inputFileName, const char *outputFileName,
++                   const char *vectorName, char *error_desc)
++{
++  char *file_out_name = NULL;
++  char *vector_name = NULL;
++  const char *char_p, *slash_p, *dot_p;
+ 
+-  p_tree=NULL;
++  p_tree = NULL;
+ 
+-  fileName = inputFileName;
++  file_name = inputFileName;
+ 
+   /* open the file to parse */
+-  file_asn1=fopen(inputFileName,"r");
++  file_asn1 = fopen (inputFileName, "r");
++
++  if (file_asn1 == NULL)
++    result_parse = ASN1_FILE_NOT_FOUND;
++  else
++    {
++      result_parse = ASN1_SUCCESS;
++
++      line_number = 1;
++      yyparse ();
+ 
+-  if(file_asn1==NULL)
+-    result_parse=ASN1_FILE_NOT_FOUND;
+-  else{
+-    result_parse=ASN1_SUCCESS;
+-
+-    lineNumber=1;
+-    yyparse();
+-
+-    fclose(file_asn1);
+-
+-    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+-      /* set IMPLICIT or EXPLICIT property */
+-      _asn1_set_default_tag(p_tree);
+-      /* set CONST_SET and CONST_NOT_USED */
+-      _asn1_type_set_config(p_tree);
+-      /* check the identifier definitions */
+-      result_parse=_asn1_check_identifier(p_tree);
+-
+-      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+-
+-	/* searching the last '/' and '.' in inputFileName */
+-	char_p=inputFileName;
+-	slash_p=inputFileName;
+-	while((char_p=strchr(char_p,'/'))){
+-	  char_p++;
+-	  slash_p=char_p;
+-	}
+-
+-	char_p=slash_p;
+-	dot_p=inputFileName+strlen(inputFileName);
+-
+-	while((char_p=strchr(char_p,'.'))){
+-	  dot_p=char_p;
+-	  char_p++;
+-	}
+-
+-	if(outputFileName == NULL){
+-	  /* file_out_name = inputFileName + _asn1_tab.c */
+-	  file_out_name=(char *)malloc(dot_p-inputFileName+1+
+-				       strlen("_asn1_tab.c"));
+-	  memcpy(file_out_name,inputFileName,dot_p-inputFileName);
+-	  file_out_name[dot_p-inputFileName]=0;
+-	  strcat(file_out_name,"_asn1_tab.c");
+-	}
+-	else{
+-	  /* file_out_name = inputFileName */
+-	  file_out_name=(char *)malloc(strlen(outputFileName)+1);
+-	  strcpy(file_out_name,outputFileName);
+-	}
+-
+-	if(vectorName == NULL){
+-	  /* vector_name = file name + _asn1_tab */
+-	  vector_name=(char *)malloc(dot_p-slash_p+1+
+-				     strlen("_asn1_tab"));
+-	  memcpy(vector_name,slash_p,dot_p-slash_p);
+-	  vector_name[dot_p-slash_p]=0;
+-	  strcat(vector_name,"_asn1_tab");
+-	}
+-	else{
+-	  /* vector_name = vectorName */
+-	  vector_name=(char *)malloc(strlen(vectorName)+1);
+-	  strcpy(vector_name,vectorName);
+-	}
+-
+-	/* Save structure in a file */
+-	_asn1_create_static_structure(p_tree,
+-				      file_out_name,vector_name);
+-
+-	free(file_out_name);
+-	free(vector_name);
+-      } /* result == OK */
+-    }   /* result == OK */
+-
+-    /* Delete the list and the ASN1 structure */
+-    _asn1_delete_list_and_nodes();
+-  } /* inputFile exist */
++      fclose (file_asn1);
+ 
+-  if (errorDescription!=NULL)
+-	_asn1_create_errorDescription(result_parse,errorDescription);
++      if (result_parse == ASN1_SUCCESS)
++        {                       /* syntax OK */
++          /* set IMPLICIT or EXPLICIT property */
++          _asn1_set_default_tag (p_tree);
++          /* set CONST_SET and CONST_NOT_USED */
++          _asn1_type_set_config (p_tree);
++          /* check the identifier definitions */
++          result_parse = _asn1_check_identifier (p_tree);
++
++          if (result_parse == ASN1_SUCCESS)
++            {                   /* all identifier defined */
++
++              /* searching the last '/' and '.' in inputFileName */
++              char_p = inputFileName;
++              slash_p = inputFileName;
++              while ((char_p = strchr (char_p, '/')))
++                {
++                  char_p++;
++                  slash_p = char_p;
++                }
++
++              char_p = slash_p;
++              dot_p = inputFileName + strlen (inputFileName);
++
++              while ((char_p = strchr (char_p, '.')))
++                {
++                  dot_p = char_p;
++                  char_p++;
++                }
++
++              if (outputFileName == NULL)
++                {
++                  /* file_out_name = inputFileName + _asn1_tab.c */
++                  file_out_name = malloc (dot_p - inputFileName + 1 +
++                                          strlen ("_asn1_tab.c"));
++                  memcpy (file_out_name, inputFileName,
++                          dot_p - inputFileName);
++                  file_out_name[dot_p - inputFileName] = 0;
++                  strcat (file_out_name, "_asn1_tab.c");
++                }
++              else
++                {
++                  /* file_out_name = inputFileName */
++                  file_out_name =
++                      (char *) malloc (strlen (outputFileName) + 1);
++                  strcpy (file_out_name, outputFileName);
++                }
++
++              if (vectorName == NULL)
++                {
++                  /* vector_name = file name + _asn1_tab */
++                  vector_name = malloc (dot_p - slash_p + 1 +
++                                        strlen ("_asn1_tab"));
++                  memcpy (vector_name, slash_p, dot_p - slash_p);
++                  vector_name[dot_p - slash_p] = 0;
++                  strcat (vector_name, "_asn1_tab");
++                }
++              else
++                {
++                  /* vector_name = vectorName */
++                  vector_name = (char *) malloc (strlen (vectorName) + 1);
++                  strcpy (vector_name, vectorName);
++                }
++
++              /* Save structure in a file */
++              _asn1_create_static_structure (p_tree,
++                                             file_out_name, vector_name);
++
++              free (file_out_name);
++              free (vector_name);
++            }                   /* result == OK */
++        }                       /* result == OK */
++
++      /* Delete the list and the ASN1 structure */
++      _asn1_delete_list_and_nodes ();
++    }                           /* inputFile exist */
++
++  _asn1_create_errorDescription (result_parse, error_desc);
+ 
+   return result_parse;
+ }
+@@ -779,17 +861,35 @@
+ /*  Return: int                                              */
+ /*                                                           */
+ /*************************************************************/
+-static int _asn1_yyerror (const char *s)
++static void
++_asn1_yyerror (const char *s)
+ {
+   /* Sends the error description to the std_out */
+ 
+-#if 0
+-  printf("_asn1_yyerror:%s:%ld: %s (Last Token:'%s')\n",fileName,
+-	 lineNumber,s,lastToken);
+-#endif
++  if (strcmp (last_token, "VisibleString") == 0 ||
++      strcmp (last_token, "PrintableString") == 0 ||
++      strcmp (last_token, "UniversalString") == 0 ||
++      strcmp (last_token, "IA5String") == 0 ||
++      strcmp (last_token, "UTF8String") == 0 ||
++      strcmp (last_token, "NumericString") == 0 ||
++      strcmp (last_token, "TeletexString") == 0 ||
++      strcmp (last_token, "BMPString") == 0)
++    {
++      snprintf (last_error_token, sizeof(last_error_token),
++                "%s", last_token);
++      fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n",
++               file_name, line_number, last_token);
++      return;
++    }
++  last_error_token[0] = 0;
+ 
+-  if(result_parse!=ASN1_NAME_TOO_LONG)
+-    result_parse=ASN1_SYNTAX_ERROR;
++  if (result_parse != ASN1_NAME_TOO_LONG)
++    {
++      snprintf (last_error, sizeof(last_error),
++                "%s:%u: Error: %s near '%s'", file_name,
++                line_number, s, last_token);
++      result_parse = ASN1_SYNTAX_ERROR;
++    }
+ 
+-  return 0;
++  return;
+ }
+--- ORIGINAL/./lib/ASN1.c	2015-07-14 18:28:22.941869639 -0700
++++ libtasn1-2.8/./lib/ASN1.c	2015-07-14 18:45:02.758734575 -0700
+@@ -1,21 +1,20 @@
+-
+ /* A Bison parser, made by GNU Bison 2.4.1.  */
+ 
+ /* Skeleton implementation for Bison's Yacc-like parsers in C
+-   
++
+       Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+    Free Software Foundation, Inc.
+-   
++
+    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 3 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, see <http://www.gnu.org/licenses/>.  */
+ 
+@@ -28,7 +27,7 @@
+    special exception, which will cause the skeleton and the resulting
+    Bison output files to be licensed under the GNU General Public
+    License without this special exception.
+-   
++
+    This special exception was added by the Free Software Foundation in
+    version 2.2 of Bison.  */
+ 
+@@ -46,7 +45,7 @@
+ #define YYBISON 1
+ 
+ /* Bison version.  */
+-#define YYBISON_VERSION "2.4.1"
++#define YYBISON_VERSION "3.0.2"
+ 
+ /* Skeleton name.  */
+ #define YYSKELETON_NAME "yacc.c"
+@@ -60,27 +59,22 @@
+ /* Pull parsers.  */
+ #define YYPULL 1
+ 
+-/* Using locations.  */
+-#define YYLSP_NEEDED 0
+ 
+ /* Substitute the variable and function names.  */
+ #define yyparse         _asn1_yyparse
+ #define yylex           _asn1_yylex
+ #define yyerror         _asn1_yyerror
+-#define yylval          _asn1_yylval
+-#define yychar          _asn1_yychar
+ #define yydebug         _asn1_yydebug
+ #define yynerrs         _asn1_yynerrs
+ 
++#define yylval          _asn1_yylval
++#define yychar          _asn1_yychar
+ 
+ /* Copy the first part of user declarations.  */
+-
+-/* Line 189 of yacc.c  */
+-#line 1 "ASN1.y"
++#line 1 "ASN1.y" /* yacc.c:339  */
+ 
+ /*
+- * Copyright (C) 2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010 Free
+- * Software Foundation, Inc.
++ * Copyright (C) 2001-2014 Free Software Foundation, Inc.
+  *
+  * This file is part of LIBTASN1.
+  *
+@@ -110,94 +104,108 @@
+ #include <int.h>
+ #include <parser_aux.h>
+ #include <structure.h>
++#include <libtasn1.h>
+ 
+ static FILE *file_asn1;			/* Pointer to file to parse */
+-static asn1_retCode result_parse;	/* result of the parser
++static int result_parse = 0;	/* result of the parser
+ 					   algorithm */
+ static ASN1_TYPE p_tree;		/* pointer to the root of the
+ 					   structure created by the
+ 					   parser*/
+-static unsigned long lineNumber;	/* line number describing the
++static unsigned int line_number;	/* line number describing the
+ 					   parser position inside the
+ 					   file */
+-static char lastToken[ASN1_MAX_NAME_SIZE+1];	/* last token find in the file
++static char last_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";
++static char last_error_token[ASN1_MAX_ERROR_DESCRIPTION_SIZE+1] = ""; /* used when expected errors occur */
++static char last_token[ASN1_MAX_NAME_SIZE+1] = ""; /* last token find in the file
+ 					   to parse before the 'parse
+ 					   error' */
+ extern char _asn1_identifierMissing[];
+-static const char *fileName;		/* file to parse */
++static const char *file_name;		/* file to parse */
+ 
+-static int _asn1_yyerror (const char *);
++static void _asn1_yyerror (const char *);
+ static int _asn1_yylex(void);
+ 
+ 
++#line 130 "ASN1.c" /* yacc.c:339  */
+ 
+-/* Line 189 of yacc.c  */
+-#line 136 "ASN1.c"
+-
+-/* Enabling traces.  */
+-#ifndef YYDEBUG
+-# define YYDEBUG 0
+-#endif
++# ifndef YY_NULLPTR
++#  if defined __cplusplus && 201103L <= __cplusplus
++#   define YY_NULLPTR nullptr
++#  else
++#   define YY_NULLPTR 0
++#  endif
++# endif
+ 
+ /* Enabling verbose error messages.  */
+ #ifdef YYERROR_VERBOSE
+ # undef YYERROR_VERBOSE
+ # define YYERROR_VERBOSE 1
+ #else
+-# define YYERROR_VERBOSE 0
++# define YYERROR_VERBOSE 1
+ #endif
+ 
+-/* Enabling the token table.  */
+-#ifndef YYTOKEN_TABLE
+-# define YYTOKEN_TABLE 0
+-#endif
+ 
++/* Debug traces.  */
++#ifndef YYDEBUG
++# define YYDEBUG 0
++#endif
++#if YYDEBUG
++extern int _asn1_yydebug;
++#endif
+ 
+-/* Tokens.  */
++/* Token type.  */
+ #ifndef YYTOKENTYPE
+ # define YYTOKENTYPE
+-   /* Put the tokens into the symbol table, so that GDB and other debuggers
+-      know about them.  */
+-   enum yytokentype {
+-     ASSIG = 258,
+-     NUM = 259,
+-     IDENTIFIER = 260,
+-     OPTIONAL = 261,
+-     INTEGER = 262,
+-     SIZE = 263,
+-     OCTET = 264,
+-     STRING = 265,
+-     SEQUENCE = 266,
+-     BIT = 267,
+-     UNIVERSAL = 268,
+-     PRIVATE = 269,
+-     APPLICATION = 270,
+-     DEFAULT = 271,
+-     CHOICE = 272,
+-     OF = 273,
+-     OBJECT = 274,
+-     STR_IDENTIFIER = 275,
+-     BOOLEAN = 276,
+-     ASN1_TRUE = 277,
+-     ASN1_FALSE = 278,
+-     TOKEN_NULL = 279,
+-     ANY = 280,
+-     DEFINED = 281,
+-     BY = 282,
+-     SET = 283,
+-     EXPLICIT = 284,
+-     IMPLICIT = 285,
+-     DEFINITIONS = 286,
+-     TAGS = 287,
+-     BEGIN = 288,
+-     END = 289,
+-     UTCTime = 290,
+-     GeneralizedTime = 291,
+-     GeneralString = 292,
+-     FROM = 293,
+-     IMPORTS = 294,
+-     ENUMERATED = 295
+-   };
++  enum yytokentype
++  {
++    ASSIG = 258,
++    NUM = 259,
++    IDENTIFIER = 260,
++    OPTIONAL = 261,
++    INTEGER = 262,
++    SIZE = 263,
++    OCTET = 264,
++    STRING = 265,
++    SEQUENCE = 266,
++    BIT = 267,
++    UNIVERSAL = 268,
++    PRIVATE = 269,
++    APPLICATION = 270,
++    DEFAULT = 271,
++    CHOICE = 272,
++    OF = 273,
++    OBJECT = 274,
++    STR_IDENTIFIER = 275,
++    BOOLEAN = 276,
++    ASN1_TRUE = 277,
++    ASN1_FALSE = 278,
++    TOKEN_NULL = 279,
++    ANY = 280,
++    DEFINED = 281,
++    BY = 282,
++    SET = 283,
++    EXPLICIT = 284,
++    IMPLICIT = 285,
++    DEFINITIONS = 286,
++    TAGS = 287,
++    BEGIN = 288,
++    END = 289,
++    UTCTime = 290,
++    GeneralizedTime = 291,
++    GeneralString = 292,
++    NumericString = 293,
++    IA5String = 294,
++    TeletexString = 295,
++    PrintableString = 296,
++    UniversalString = 297,
++    BMPString = 298,
++    UTF8String = 299,
++    VisibleString = 300,
++    FROM = 301,
++    IMPORTS = 302,
++    ENUMERATED = 303
++  };
+ #endif
+ /* Tokens.  */
+ #define ASSIG 258
+@@ -235,40 +243,45 @@
+ #define UTCTime 290
+ #define GeneralizedTime 291
+ #define GeneralString 292
+-#define FROM 293
+-#define IMPORTS 294
+-#define ENUMERATED 295
+-
+-
+-
++#define NumericString 293
++#define IA5String 294
++#define TeletexString 295
++#define PrintableString 296
++#define UniversalString 297
++#define BMPString 298
++#define UTF8String 299
++#define VisibleString 300
++#define FROM 301
++#define IMPORTS 302
++#define ENUMERATED 303
+ 
++/* Value type.  */
+ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+-typedef union YYSTYPE
++typedef union YYSTYPE YYSTYPE;
++union YYSTYPE
+ {
+-
+-/* Line 214 of yacc.c  */
+-#line 58 "ASN1.y"
++#line 62 "ASN1.y" /* yacc.c:355  */
+ 
+   unsigned int constant;
+   char str[ASN1_MAX_NAME_SIZE+1];
+   ASN1_TYPE node;
+ 
+-
+-
+-/* Line 214 of yacc.c  */
+-#line 260 "ASN1.c"
+-} YYSTYPE;
++#line 269 "ASN1.c" /* yacc.c:355  */
++};
+ # define YYSTYPE_IS_TRIVIAL 1
+-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+ # define YYSTYPE_IS_DECLARED 1
+ #endif
+ 
+ 
+-/* Copy the second part of user declarations.  */
++extern YYSTYPE _asn1_yylval;
++
++int _asn1_yyparse (void);
++
+ 
+ 
+-/* Line 264 of yacc.c  */
+-#line 272 "ASN1.c"
++/* Copy the second part of user declarations.  */
++
++#line 284 "ASN1.c" /* yacc.c:358  */
+ 
+ #ifdef short
+ # undef short
+@@ -282,11 +295,8 @@
+ 
+ #ifdef YYTYPE_INT8
+ typedef YYTYPE_INT8 yytype_int8;
+-#elif (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+-typedef signed char yytype_int8;
+ #else
+-typedef short int yytype_int8;
++typedef signed char yytype_int8;
+ #endif
+ 
+ #ifdef YYTYPE_UINT16
+@@ -306,8 +316,7 @@
+ #  define YYSIZE_T __SIZE_TYPE__
+ # elif defined size_t
+ #  define YYSIZE_T size_t
+-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
++# elif ! defined YYSIZE_T
+ #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+ #  define YYSIZE_T size_t
+ # else
+@@ -318,42 +327,71 @@
+ #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+ 
+ #ifndef YY_
+-# if YYENABLE_NLS
++# if defined YYENABLE_NLS && YYENABLE_NLS
+ #  if ENABLE_NLS
+ #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
++#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+ #  endif
+ # endif
+ # ifndef YY_
+-#  define YY_(msgid) msgid
++#  define YY_(Msgid) Msgid
++# endif
++#endif
++
++#ifndef YY_ATTRIBUTE
++# if (defined __GNUC__                                               \
++      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
++     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
++#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
++# else
++#  define YY_ATTRIBUTE(Spec) /* empty */
++# endif
++#endif
++
++#ifndef YY_ATTRIBUTE_PURE
++# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
++#endif
++
++#ifndef YY_ATTRIBUTE_UNUSED
++# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
++#endif
++
++#if !defined _Noreturn \
++     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
++# if defined _MSC_VER && 1200 <= _MSC_VER
++#  define _Noreturn __declspec (noreturn)
++# else
++#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+ # endif
+ #endif
+ 
+ /* Suppress unused-variable warnings by "using" E.  */
+ #if ! defined lint || defined __GNUC__
+-# define YYUSE(e) ((void) (e))
++# define YYUSE(E) ((void) (E))
+ #else
+-# define YYUSE(e) /* empty */
++# define YYUSE(E) /* empty */
+ #endif
+ 
+-/* Identity function, used to suppress warnings about constant conditions.  */
+-#ifndef lint
+-# define YYID(n) (n)
++#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
++/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
++# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
++    _Pragma ("GCC diagnostic push") \
++    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
++    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
++# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
++    _Pragma ("GCC diagnostic pop")
+ #else
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+-static int
+-YYID (int yyi)
+-#else
+-static int
+-YYID (yyi)
+-    int yyi;
++# define YY_INITIAL_VALUE(Value) Value
+ #endif
+-{
+-  return yyi;
+-}
++#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
++# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
++# define YY_IGNORE_MAYBE_UNINITIALIZED_END
++#endif
++#ifndef YY_INITIAL_VALUE
++# define YY_INITIAL_VALUE(Value) /* Nothing. */
+ #endif
+ 
++
+ #if ! defined yyoverflow || YYERROR_VERBOSE
+ 
+ /* The parser invokes alloca or malloc; define the necessary symbols.  */
+@@ -371,11 +409,11 @@
+ #    define alloca _alloca
+ #   else
+ #    define YYSTACK_ALLOC alloca
+-#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
++#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+ #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+-#     ifndef _STDLIB_H
+-#      define _STDLIB_H 1
++      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
++#     ifndef EXIT_SUCCESS
++#      define EXIT_SUCCESS 0
+ #     endif
+ #    endif
+ #   endif
+@@ -383,8 +421,8 @@
+ # endif
+ 
+ # ifdef YYSTACK_ALLOC
+-   /* Pacify GCC's `empty if-body' warning.  */
+-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
++   /* Pacify GCC's 'empty if-body' warning.  */
++#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+ #  ifndef YYSTACK_ALLOC_MAXIMUM
+     /* The OS might guarantee only one guard page at the bottom of the stack,
+        and a page size can be as small as 4096 bytes.  So we cannot safely
+@@ -398,25 +436,23 @@
+ #  ifndef YYSTACK_ALLOC_MAXIMUM
+ #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+ #  endif
+-#  if (defined __cplusplus && ! defined _STDLIB_H \
++#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+        && ! ((defined YYMALLOC || defined malloc) \
+-	     && (defined YYFREE || defined free)))
++             && (defined YYFREE || defined free)))
+ #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+-#   ifndef _STDLIB_H
+-#    define _STDLIB_H 1
++#   ifndef EXIT_SUCCESS
++#    define EXIT_SUCCESS 0
+ #   endif
+ #  endif
+ #  ifndef YYMALLOC
+ #   define YYMALLOC malloc
+-#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
++#   if ! defined malloc && ! defined EXIT_SUCCESS
+ void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+ #   endif
+ #  endif
+ #  ifndef YYFREE
+ #   define YYFREE free
+-#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
++#   if ! defined free && ! defined EXIT_SUCCESS
+ void free (void *); /* INFRINGES ON USER NAME SPACE */
+ #   endif
+ #  endif
+@@ -426,7 +462,7 @@
+ 
+ #if (! defined yyoverflow \
+      && (! defined __cplusplus \
+-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
++         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+ 
+ /* A type that is properly aligned for any stack member.  */
+ union yyalloc
+@@ -444,79 +480,85 @@
+      ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+       + YYSTACK_GAP_MAXIMUM)
+ 
+-/* Copy COUNT objects from FROM to TO.  The source and destination do
+-   not overlap.  */
+-# ifndef YYCOPY
+-#  if defined __GNUC__ && 1 < __GNUC__
+-#   define YYCOPY(To, From, Count) \
+-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+-#  else
+-#   define YYCOPY(To, From, Count)		\
+-      do					\
+-	{					\
+-	  YYSIZE_T yyi;				\
+-	  for (yyi = 0; yyi < (Count); yyi++)	\
+-	    (To)[yyi] = (From)[yyi];		\
+-	}					\
+-      while (YYID (0))
+-#  endif
+-# endif
++# define YYCOPY_NEEDED 1
+ 
+ /* Relocate STACK from its old location to the new one.  The
+    local variables YYSIZE and YYSTACKSIZE give the old and new number of
+    elements in the stack, and YYPTR gives the new location of the
+    stack.  Advance YYPTR to a properly aligned location for the next
+    stack.  */
+-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
+-    do									\
+-      {									\
+-	YYSIZE_T yynewbytes;						\
+-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
+-	Stack = &yyptr->Stack_alloc;					\
+-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+-	yyptr += yynewbytes / sizeof (*yyptr);				\
+-      }									\
+-    while (YYID (0))
++# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
++    do                                                                  \
++      {                                                                 \
++        YYSIZE_T yynewbytes;                                            \
++        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
++        Stack = &yyptr->Stack_alloc;                                    \
++        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
++        yyptr += yynewbytes / sizeof (*yyptr);                          \
++      }                                                                 \
++    while (0)
+ 
+ #endif
+ 
++#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
++/* Copy COUNT objects from SRC to DST.  The source and destination do
++   not overlap.  */
++# ifndef YYCOPY
++#  if defined __GNUC__ && 1 < __GNUC__
++#   define YYCOPY(Dst, Src, Count) \
++      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
++#  else
++#   define YYCOPY(Dst, Src, Count)              \
++      do                                        \
++        {                                       \
++          YYSIZE_T yyi;                         \
++          for (yyi = 0; yyi < (Count); yyi++)   \
++            (Dst)[yyi] = (Src)[yyi];            \
++        }                                       \
++      while (0)
++#  endif
++# endif
++#endif /* !YYCOPY_NEEDED */
++
+ /* YYFINAL -- State number of the termination state.  */
+ #define YYFINAL  5
+ /* YYLAST -- Last index in YYTABLE.  */
+-#define YYLAST   192
++#define YYLAST   223
+ 
+ /* YYNTOKENS -- Number of terminals.  */
+-#define YYNTOKENS  52
++#define YYNTOKENS  60
+ /* YYNNTS -- Number of nonterminals.  */
+-#define YYNNTS  43
++#define YYNNTS  52
+ /* YYNRULES -- Number of rules.  */
+-#define YYNRULES  99
+-/* YYNRULES -- Number of states.  */
+-#define YYNSTATES  190
++#define YYNRULES  128
++/* YYNSTATES -- Number of states.  */
++#define YYNSTATES  223
+ 
+-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
++/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
++   by yylex, with out-of-bounds checking.  */
+ #define YYUNDEFTOK  2
+-#define YYMAXUTOK   295
++#define YYMAXUTOK   303
+ 
+-#define YYTRANSLATE(YYX)						\
++#define YYTRANSLATE(YYX)                                                \
+   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+ 
+-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
++/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
++   as returned by yylex, without out-of-bounds checking.  */
+ static const yytype_uint8 yytranslate[] =
+ {
+        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+-      43,    44,     2,    41,    45,    42,    51,     2,     2,     2,
++      51,    52,     2,    49,    53,    50,    59,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+-       2,    46,     2,    47,     2,     2,     2,     2,     2,     2,
++       2,    54,     2,    55,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+-       2,     2,     2,    49,    48,    50,     2,     2,     2,     2,
++       2,     2,     2,    57,    56,    58,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+@@ -533,81 +575,31 @@
+        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+-      35,    36,    37,    38,    39,    40
++      35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
++      45,    46,    47,    48
+ };
+ 
+ #if YYDEBUG
+-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+-   YYRHS.  */
+-static const yytype_uint16 yyprhs[] =
+-{
+-       0,     0,     3,    12,    14,    17,    20,    22,    24,    26,
+-      28,    30,    32,    36,    41,    43,    47,    49,    54,    56,
+-      59,    61,    63,    65,    69,    74,    76,    79,    82,    85,
+-      88,    91,    93,    97,    99,   104,   109,   117,   119,   121,
+-     123,   128,   136,   138,   142,   144,   147,   150,   154,   159,
+-     161,   165,   168,   172,   178,   183,   186,   188,   191,   193,
+-     195,   197,   199,   201,   203,   205,   207,   209,   211,   213,
+-     215,   217,   219,   222,   224,   227,   230,   233,   235,   239,
+-     244,   248,   253,   258,   262,   267,   272,   274,   279,   283,
+-     291,   298,   303,   305,   307,   309,   312,   317,   321,   323
+-};
+-
+-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+-static const yytype_int8 yyrhs[] =
+-{
+-      53,     0,    -1,    93,    31,    94,    32,     3,    33,    92,
+-      34,    -1,     4,    -1,    41,     4,    -1,    42,     4,    -1,
+-      54,    -1,    55,    -1,     4,    -1,     5,    -1,    56,    -1,
+-       5,    -1,    43,    56,    44,    -1,     5,    43,    56,    44,
+-      -1,    59,    -1,    60,    45,    59,    -1,    57,    -1,     5,
+-      43,     4,    44,    -1,    61,    -1,    62,    61,    -1,    13,
+-      -1,    14,    -1,    15,    -1,    46,     4,    47,    -1,    46,
+-      63,     4,    47,    -1,    64,    -1,    64,    29,    -1,    64,
+-      30,    -1,    16,    58,    -1,    16,    22,    -1,    16,    23,
+-      -1,    56,    -1,    67,    48,    56,    -1,     7,    -1,     7,
+-      49,    60,    50,    -1,    68,    43,    67,    44,    -1,    68,
+-      43,    57,    51,    51,    57,    44,    -1,    21,    -1,    35,
+-      -1,    36,    -1,     8,    43,    57,    44,    -1,     8,    43,
+-      57,    51,    51,    57,    44,    -1,    71,    -1,    43,    71,
+-      44,    -1,    37,    -1,    37,    72,    -1,     9,    10,    -1,
+-       9,    10,    72,    -1,     5,    43,     4,    44,    -1,    75,
+-      -1,    76,    45,    75,    -1,    12,    10,    -1,    12,    10,
+-      72,    -1,    12,    10,    49,    76,    50,    -1,    40,    49,
+-      76,    50,    -1,    19,    20,    -1,     5,    -1,     5,    72,
+-      -1,    68,    -1,    78,    -1,    69,    -1,    70,    -1,    74,
+-      -1,    77,    -1,    73,    -1,    85,    -1,    79,    -1,    87,
+-      -1,    88,    -1,    86,    -1,    24,    -1,    80,    -1,    65,
+-      80,    -1,    81,    -1,    81,    66,    -1,    81,     6,    -1,
+-       5,    82,    -1,    83,    -1,    84,    45,    83,    -1,    11,
+-      49,    84,    50,    -1,    11,    18,    80,    -1,    11,    72,
+-      18,    80,    -1,    28,    49,    84,    50,    -1,    28,    18,
+-      80,    -1,    28,    72,    18,    80,    -1,    17,    49,    84,
+-      50,    -1,    25,    -1,    25,    26,    27,     5,    -1,     5,
+-       3,    81,    -1,     5,    19,    20,     3,    49,    62,    50,
+-      -1,     5,     5,     3,    49,    62,    50,    -1,     5,     7,
+-       3,    56,    -1,    89,    -1,    90,    -1,    91,    -1,    92,
+-      91,    -1,     5,    49,    62,    50,    -1,     5,    49,    50,
+-      -1,    29,    -1,    30,    -1
+-};
+-
+-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
++  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+ static const yytype_uint16 yyrline[] =
+ {
+-       0,   119,   119,   132,   133,   136,   140,   141,   144,   145,
+-     148,   149,   152,   154,   159,   160,   164,   166,   171,   172,
+-     176,   177,   178,   181,   183,   187,   188,   189,   192,   194,
+-     195,   199,   200,   204,   205,   207,   208,   215,   218,   219,
+-     222,   224,   230,   231,   234,   235,   239,   240,   244,   249,
+-     250,   254,   255,   256,   261,   267,   270,   272,   275,   276,
+-     277,   278,   279,   280,   281,   282,   283,   284,   285,   286,
+-     287,   290,   291,   296,   297,   300,   303,   306,   307,   311,
+-     313,   315,   320,   322,   324,   329,   333,   334,   339,   342,
+-     346,   351,   357,   358,   361,   362,   366,   369,   393,   394
++       0,   135,   135,   148,   149,   152,   155,   156,   159,   160,
++     163,   164,   165,   168,   169,   172,   174,   179,   180,   184,
++     186,   191,   192,   196,   197,   198,   201,   203,   207,   208,
++     209,   212,   214,   215,   219,   220,   224,   225,   227,   228,
++     235,   238,   239,   242,   244,   250,   251,   254,   255,   259,
++     260,   264,   265,   269,   270,   274,   275,   279,   280,   284,
++     285,   289,   290,   294,   295,   299,   300,   304,   309,   310,
++     314,   315,   316,   321,   327,   330,   332,   335,   336,   337,
++     338,   339,   340,   341,   342,   343,   344,   345,   346,   347,
++     348,   349,   350,   351,   352,   353,   354,   355,   358,   359,
++     364,   365,   368,   371,   374,   375,   379,   381,   383,   388,
++     390,   392,   397,   401,   402,   407,   409,   412,   416,   421,
++     427,   428,   431,   432,   436,   439,   441,   465,   466
+ };
+ #endif
+ 
+-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
++#if YYDEBUG || YYERROR_VERBOSE || 1
+ /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+ static const char *const yytname[] =
+@@ -618,305 +610,289 @@
+   "OBJECT", "STR_IDENTIFIER", "BOOLEAN", "ASN1_TRUE", "ASN1_FALSE",
+   "TOKEN_NULL", "ANY", "DEFINED", "BY", "SET", "EXPLICIT", "IMPLICIT",
+   "DEFINITIONS", "TAGS", "BEGIN", "END", "UTCTime", "GeneralizedTime",
+-  "GeneralString", "FROM", "IMPORTS", "ENUMERATED", "'+'", "'-'", "'('",
++  "GeneralString", "NumericString", "IA5String", "TeletexString",
++  "PrintableString", "UniversalString", "BMPString", "UTF8String",
++  "VisibleString", "FROM", "IMPORTS", "ENUMERATED", "'+'", "'-'", "'('",
+   "')'", "','", "'['", "']'", "'|'", "'{'", "'}'", "'.'", "$accept",
+   "definitions", "pos_num", "neg_num", "pos_neg_num", "num_identifier",
+-  "pos_neg_identifier", "constant", "constant_list", "obj_constant",
+-  "obj_constant_list", "class", "tag_type", "tag", "default",
+-  "pos_neg_list", "integer_def", "boolean_def", "Time", "size_def2",
+-  "size_def", "generalstring_def", "octet_string_def", "bit_element",
++  "int_identifier", "pos_neg_identifier", "constant", "constant_list",
++  "obj_constant", "obj_constant_list", "class", "tag_type", "tag",
++  "default", "pos_neg_list", "integer_def", "boolean_def", "Time",
++  "size_def2", "size_def", "generalstring_def", "numericstring_def",
++  "ia5string_def", "teletexstring_def", "printablestring_def",
++  "universalstring_def", "bmpstring_def", "utf8string_def",
++  "visiblestring_def", "octet_string_def", "bit_element",
+   "bit_element_list", "bit_string_def", "enumerated_def", "object_def",
+   "type_assig_right", "type_assig_right_tag",
+   "type_assig_right_tag_default", "type_assig", "type_assig_list",
+   "sequence_def", "set_def", "choise_def", "any_def", "type_def",
+   "constant_def", "type_constant", "type_constant_list", "definitions_id",
+-  "explicit_implicit", 0
++  "explicit_implicit", YY_NULLPTR
+ };
+ #endif
+ 
+ # ifdef YYPRINT
+-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+-   token YYLEX-NUM.  */
++/* YYTOKNUM[NUM] -- (External) token number corresponding to the
++   (internal) symbol number NUM (which must be that of a token).  */
+ static const yytype_uint16 yytoknum[] =
+ {
+        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
+      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+-     295,    43,    45,    40,    41,    44,    91,    93,   124,   123,
+-     125,    46
++     295,   296,   297,   298,   299,   300,   301,   302,   303,    43,
++      45,    40,    41,    44,    91,    93,   124,   123,   125,    46
+ };
+ # endif
+ 
+-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+-static const yytype_uint8 yyr1[] =
++#define YYPACT_NINF -129
++
++#define yypact_value_is_default(Yystate) \
++  (!!((Yystate) == (-129)))
++
++#define YYTABLE_NINF -12
++
++#define yytable_value_is_error(Yytable_value) \
++  0
++
++  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
++     STATE-NUM.  */
++static const yytype_int16 yypact[] =
+ {
+-       0,    52,    53,    54,    54,    55,    56,    56,    57,    57,
+-      58,    58,    59,    59,    60,    60,    61,    61,    62,    62,
+-      63,    63,    63,    64,    64,    65,    65,    65,    66,    66,
+-      66,    67,    67,    68,    68,    68,    68,    69,    70,    70,
+-      71,    71,    72,    72,    73,    73,    74,    74,    75,    76,
+-      76,    77,    77,    77,    78,    79,    80,    80,    80,    80,
+-      80,    80,    80,    80,    80,    80,    80,    80,    80,    80,
+-      80,    81,    81,    82,    82,    82,    83,    84,    84,    85,
+-      85,    85,    86,    86,    86,    87,    88,    88,    89,    90,
+-      90,    90,    91,    91,    92,    92,    93,    93,    94,    94
++      36,    -7,    74,    22,     3,  -129,    26,  -129,    34,  -129,
++    -129,  -129,     5,  -129,  -129,    55,    89,  -129,  -129,    97,
++      57,   101,  -129,   122,   141,   132,  -129,  -129,  -129,    32,
++      77,    77,   152,   165,   150,  -129,  -129,     6,   119,   167,
++      18,   168,   124,   159,  -129,  -129,   156,    21,  -129,  -129,
++       6,     6,     6,     6,     6,     6,     6,     6,     6,   126,
++      30,    38,   121,   133,  -129,  -129,  -129,  -129,  -129,  -129,
++    -129,  -129,  -129,  -129,  -129,  -129,  -129,  -129,  -129,  -129,
++    -129,  -129,  -129,  -129,  -129,  -129,   128,    58,   183,   136,
++     180,  -129,  -129,    20,     6,   121,   184,   172,    -3,   184,
++    -129,   164,   121,   184,   174,  -129,  -129,  -129,  -129,  -129,
++    -129,  -129,  -129,  -129,   188,   139,  -129,  -129,  -129,   191,
++    -129,  -129,  -129,    42,   149,  -129,   192,   193,  -129,  -129,
++    -129,   142,   169,   146,   151,    58,  -129,    53,  -129,  -129,
++      77,  -129,    71,   121,   188,  -129,    83,   195,  -129,    90,
++     121,   153,  -129,    94,  -129,   148,   147,  -129,   197,  -129,
++     154,    43,     7,  -129,  -129,   149,  -129,   -21,  -129,    58,
++     155,    20,  -129,    24,  -129,   184,  -129,  -129,   114,  -129,
++    -129,  -129,  -129,   201,   188,  -129,  -129,   157,   158,  -129,
++      58,  -129,    23,  -129,   160,   162,  -129,  -129,  -129,    54,
++    -129,  -129,  -129,   163,  -129,    47,  -129,  -129,   169,  -129,
++    -129,  -129,  -129,  -129,  -129,  -129,  -129,   204,   166,   170,
++    -129,  -129,  -129
+ };
+ 
+-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+-static const yytype_uint8 yyr2[] =
++  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
++     Performed when YYTABLE does not specify something else to do.  Zero
++     means the default is an error.  */
++static const yytype_uint8 yydefact[] =
+ {
+-       0,     2,     8,     1,     2,     2,     1,     1,     1,     1,
+-       1,     1,     3,     4,     1,     3,     1,     4,     1,     2,
+-       1,     1,     1,     3,     4,     1,     2,     2,     2,     2,
+-       2,     1,     3,     1,     4,     4,     7,     1,     1,     1,
+-       4,     7,     1,     3,     1,     2,     2,     3,     4,     1,
+-       3,     2,     3,     5,     4,     2,     1,     2,     1,     1,
+-       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
+-       1,     1,     2,     1,     2,     2,     2,     1,     3,     4,
+-       3,     4,     4,     3,     4,     4,     1,     4,     3,     7,
+-       6,     4,     1,     1,     1,     2,     4,     3,     1,     1
++       0,   126,     0,     0,     0,     1,     0,     8,     9,   125,
++      19,    21,     0,   127,   128,     0,     0,   124,    22,     0,
++       0,     0,    20,     0,     0,     0,   120,   121,   122,     0,
++       0,     0,     0,     0,     0,     2,   123,    75,    36,     0,
++       0,     0,     0,     0,    40,    97,   113,     0,    41,    42,
++      47,    49,    51,    53,    55,    57,    59,    61,    63,     0,
++       0,    28,     0,    77,    79,    80,    83,    84,    85,    86,
++      87,    88,    89,    90,    91,    81,    82,    78,    93,    98,
++     116,    92,    96,    94,    95,   115,     0,     0,     0,     0,
++       0,    45,    76,     0,    65,     0,     0,     0,    70,     0,
++      74,     0,     0,     0,     0,    48,    50,    52,    54,    56,
++      58,    60,    62,    64,     0,     0,    23,    24,    25,     0,
++      29,    30,    99,     0,     0,     3,     0,     0,     6,     7,
++     119,     0,     0,     0,     0,     0,    17,     0,    66,   107,
++       0,   104,     0,     0,     0,    71,     0,     0,   110,     0,
++       0,     0,    68,     0,    26,     0,     3,    12,     0,    34,
++       0,     0,     0,     4,     5,     0,     9,     0,    46,     0,
++       0,     0,    37,   100,   103,     0,   106,   108,     0,   112,
++     114,   109,   111,     0,     0,    73,    27,     5,     0,    38,
++       0,   118,     0,    43,     0,     0,    15,    18,   102,     0,
++     101,   105,    72,     0,    69,     0,    35,   117,     0,    16,
++      14,    32,    33,    13,    31,    67,    10,     0,     0,     0,
++      11,    39,    44
+ };
+ 
+-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+-   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+-   means the default is an error.  */
+-static const yytype_uint8 yydefact[] =
++  /* YYPGOTO[NTERM-NUM].  */
++static const yytype_int16 yypgoto[] =
+ {
+-       0,     0,     0,     0,     0,     1,     0,     8,     9,    97,
+-      16,    18,     0,    98,    99,     0,     0,    96,    19,     0,
+-       0,     0,    17,     0,     0,    92,    93,    94,     0,     0,
+-       0,     0,     0,     2,    95,    56,    33,     0,     0,     0,
+-       0,     0,    37,    70,    86,     0,    38,    39,    44,     0,
+-       0,    25,     0,    58,    60,    61,    64,    62,    63,    59,
+-      66,    71,    88,    65,    69,    67,    68,     0,     0,     0,
+-       0,     0,    42,    57,     0,    46,     0,     0,     0,    51,
+-       0,    55,     0,     0,     0,     0,    45,     0,     0,    20,
+-      21,    22,     0,    26,    27,    72,     0,     0,     3,     0,
+-       0,     6,     7,    91,     0,     0,     0,     0,     0,    14,
+-       0,    47,    80,     0,    77,     0,     0,     0,    52,     0,
+-       0,    83,     0,     0,     0,    49,     0,    23,     0,     3,
+-       9,    31,     0,     0,     0,     4,     5,     0,     0,    43,
+-       0,     0,     0,    34,    73,    76,     0,    79,    81,     0,
+-      85,    87,    82,    84,     0,     0,    54,    24,     0,    35,
+-       0,    90,     0,    40,     0,     0,    12,    15,    75,     0,
+-      74,    78,    53,     0,    50,     0,    32,    89,     0,    13,
+-      11,    29,    30,    10,    28,    48,     0,     0,    36,    41
++    -129,  -129,  -129,  -129,  -120,  -128,     4,  -129,    39,  -129,
++     -12,   -92,  -129,  -129,  -129,  -129,  -129,  -129,  -129,  -129,
++     130,   -34,  -129,  -129,  -129,  -129,  -129,  -129,  -129,  -129,
++    -129,  -129,    27,    68,  -129,  -129,  -129,   -60,   -30,  -129,
++      46,    72,  -129,  -129,  -129,  -129,  -129,  -129,   194,  -129,
++    -129,  -129
+ };
+ 
+-/* YYDEFGOTO[NTERM-NUM].  */
++  /* YYDEFGOTO[NTERM-NUM].  */
+ static const yytype_int16 yydefgoto[] =
+ {
+-      -1,     2,   101,   102,   103,    10,   184,   109,   110,    11,
+-      12,    92,    51,    52,   170,   133,    53,    54,    55,    72,
+-      73,    56,    57,   125,   126,    58,    59,    60,    61,    62,
+-     145,   114,   115,    63,    64,    65,    66,    25,    26,    27,
+-      28,     3,    15
++      -1,     2,   128,   129,   130,    10,   160,   214,   136,   137,
++      11,    12,   119,    61,    62,   200,   161,    63,    64,    65,
++      91,    92,    66,    67,    68,    69,    70,    71,    72,    73,
++      74,    75,   152,   153,    76,    77,    78,    79,    80,   174,
++     141,   142,    81,    82,    83,    84,    26,    27,    28,    29,
++       3,    15
+ };
+ 
+-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+-   STATE-NUM.  */
+-#define YYPACT_NINF -96
+-static const yytype_int16 yypact[] =
++  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
++     positive, shift that token.  If negative, reduce the rule whose
++     number is the opposite.  If YYTABLE_NINF, syntax error.  */
++static const yytype_int16 yytable[] =
+ {
+-      24,   -14,    48,    56,     0,   -96,   -10,   -96,    -2,   -96,
+-     -96,   -96,     2,   -96,   -96,    71,   111,   -96,   -96,   117,
+-      83,    96,   -96,   127,    42,   -96,   -96,   -96,    10,    77,
+-     130,   131,   115,   -96,   -96,     8,    90,   132,    13,   135,
+-      92,   126,   -96,   -96,   122,    15,   -96,   -96,     8,   100,
+-      93,    49,   119,    94,   -96,   -96,   -96,   -96,   -96,   -96,
+-     -96,   -96,   -96,   -96,   -96,   -96,   -96,   102,    28,   149,
+-     110,   150,   -96,   -96,    17,     8,   119,   152,   142,    22,
+-     152,   -96,   134,   119,   152,   144,   -96,   158,   118,   -96,
+-     -96,   -96,   160,   -96,   -96,   -96,    35,    88,   -96,   162,
+-     163,   -96,   -96,   -96,   120,   114,   124,   128,    28,   -96,
+-      -8,   -96,   -96,    77,   -96,    -7,   119,   158,   -96,    18,
+-     165,   -96,    50,   119,   129,   -96,    54,   -96,   133,   123,
+-     -96,   -96,   125,    37,     4,   -96,   -96,    88,   -27,   -96,
+-      28,   137,    17,   -96,    20,   -96,   152,   -96,   -96,    66,
+-     -96,   -96,   -96,   -96,   169,   158,   -96,   -96,   136,   -96,
+-      28,   -96,     7,   -96,   138,   139,   -96,   -96,   -96,    68,
+-     -96,   -96,   -96,   140,   -96,   114,   -96,   -96,   114,   -96,
+-     -96,   -96,   -96,   -96,   -96,   -96,   141,   146,   -96,   -96
++      18,    85,   122,   159,   167,    89,    97,     7,     8,     7,
++       8,     7,     8,   104,    89,   170,   105,   106,   107,   108,
++     109,   110,   111,   112,   113,   134,    89,     7,     8,    89,
++     198,   193,   162,    24,   115,   139,    95,    25,   194,   102,
++     199,     1,   148,   116,   117,   118,   156,   157,    90,   195,
++       4,   216,   157,     6,   144,    13,    14,    90,   125,   210,
++     138,     9,   125,    17,   145,   191,    35,   120,   121,    90,
++     206,   135,    90,   192,     5,    96,   211,   212,   103,   213,
++     219,   207,    37,   177,    38,    16,    39,    19,    40,    41,
++     182,   126,   158,    20,    42,   189,    43,   217,    44,   190,
++      21,    45,    46,   126,   127,    47,   171,   126,   127,    22,
++     173,   172,    48,    49,    50,    51,    52,    53,    54,    55,
++      56,    57,    58,    24,   175,    59,    37,    25,    38,   176,
++      39,    60,    40,    41,    23,    31,   175,    32,    42,    33,
++      43,   179,    44,   175,    30,    45,    46,   184,   181,    47,
++      18,    34,   185,     7,     8,    86,    48,    49,    50,    51,
++      52,    53,    54,    55,    56,    57,    58,   184,    87,    59,
++      88,   146,   202,     7,   166,   149,    93,    94,    98,   100,
++      18,    99,   101,   114,   123,   124,   131,   132,    89,   140,
++     143,   147,   150,   151,   154,   155,   163,   164,   168,   165,
++     180,   187,   169,   186,   183,   203,   -10,   196,   220,   218,
++     197,   204,   178,   188,   209,   215,   -11,   205,   221,   208,
++     133,   201,   222,    36
+ };
+ 
+-/* YYPGOTO[NTERM-NUM].  */
+-static const yytype_int16 yypgoto[] =
++static const yytype_uint8 yycheck[] =
+ {
+-     -96,   -96,   -96,   -96,   -94,   -95,   -96,    33,   -96,   -12,
+-     -84,   -96,   -96,   -96,   -96,   -96,   -96,   -96,   -96,   106,
+-     -20,   -96,   -96,    23,    62,   -96,   -96,   -96,   -49,    69,
+-     -96,    40,    41,   -96,   -96,   -96,   -96,   -96,   -96,   164,
+-     -96,   -96,   -96
++      12,    31,    62,   123,   132,     8,    40,     4,     5,     4,
++       5,     4,     5,    47,     8,   135,    50,    51,    52,    53,
++      54,    55,    56,    57,    58,     5,     8,     4,     5,     8,
++       6,    52,   124,     1,     4,    95,    18,     5,    59,    18,
++      16,     5,   102,    13,    14,    15,     4,     5,    51,   169,
++      57,     4,     5,    31,    57,    29,    30,    51,     4,     5,
++      94,    58,     4,    58,    98,    58,    34,    29,    30,    51,
++     190,    51,    51,   165,     0,    57,    22,    23,    57,   199,
++     208,    58,     5,   143,     7,    51,     9,    32,    11,    12,
++     150,    49,    50,     4,    17,    52,    19,    50,    21,    56,
++       3,    24,    25,    49,    50,    28,    53,    49,    50,    52,
++     140,    58,    35,    36,    37,    38,    39,    40,    41,    42,
++      43,    44,    45,     1,    53,    48,     5,     5,     7,    58,
++       9,    54,    11,    12,    33,     3,    53,     5,    17,     7,
++      19,    58,    21,    53,     3,    24,    25,    53,    58,    28,
++     162,    19,    58,     4,     5,     3,    35,    36,    37,    38,
++      39,    40,    41,    42,    43,    44,    45,    53,     3,    48,
++      20,    99,    58,     4,     5,   103,    57,    10,    10,    20,
++     192,    57,    26,    57,    51,    57,     3,    51,     8,     5,
++      18,    27,    18,     5,    55,     4,     4,     4,    52,    57,
++       5,     4,    51,    55,    51,     4,    59,    52,     4,   205,
++     171,   184,   144,    59,    52,    52,    59,    59,    52,    59,
++      90,   175,    52,    29
+ };
+ 
+-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+-   positive, shift that token.  If negative, reduce the rule which
+-   number is the opposite.  If zero, do what YYDEFACT says.
+-   If YYTABLE_NINF, syntax error.  */
+-#define YYTABLE_NINF -9
+-static const yytype_int16 yytable[] =
++  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
++     symbol of state STATE-NUM.  */
++static const yytype_uint8 yystos[] =
+ {
+-      18,   132,   131,    95,     7,     8,     7,     8,     7,     8,
+-     138,     7,     8,   134,   141,    24,    70,   163,    78,    13,
+-      14,    70,   107,    70,   164,    85,   168,   112,    86,     1,
+-      70,    76,    98,    83,   121,     4,   169,   142,   146,   129,
+-     130,    16,   143,   147,    33,    29,   165,    30,     5,    31,
+-       9,    71,    17,   162,   161,   111,    71,   177,    71,   118,
+-     108,    32,    77,   146,    84,    71,   176,   148,   150,    99,
+-     100,   117,    98,   180,   153,   183,    99,   100,    93,    94,
+-     186,   159,    35,   187,    36,   160,    37,     6,    38,    39,
+-     181,   182,     7,     8,    40,   146,    41,    88,    42,   155,
+-     152,    43,    44,    19,   156,    45,    89,    90,    91,    99,
+-     100,   155,    46,    47,    48,    20,   172,    49,     7,   130,
+-      21,   119,    18,    50,    35,   122,    36,    22,    37,    23,
+-      38,    39,    24,    67,    68,    69,    40,    96,    41,    74,
+-      42,    80,    75,    43,    44,    79,    81,    45,    82,    87,
+-      18,    97,   104,   105,    46,    47,    48,   113,    70,    49,
+-     116,   120,   123,   124,   128,   127,   135,   136,   139,   137,
+-     151,   140,   154,   173,    -8,   167,   158,   106,   174,   149,
+-     157,   166,   144,   179,   185,   188,   171,   175,     0,   178,
+-     189,     0,    34
++       0,     5,    61,   110,    57,     0,    31,     4,     5,    58,
++      65,    70,    71,    29,    30,   111,    51,    58,    70,    32,
++       4,     3,    52,    33,     1,     5,   106,   107,   108,   109,
++       3,     3,     5,     7,    19,    34,   108,     5,     7,     9,
++      11,    12,    17,    19,    21,    24,    25,    28,    35,    36,
++      37,    38,    39,    40,    41,    42,    43,    44,    45,    48,
++      54,    73,    74,    77,    78,    79,    82,    83,    84,    85,
++      86,    87,    88,    89,    90,    91,    94,    95,    96,    97,
++      98,   102,   103,   104,   105,    98,     3,     3,    20,     8,
++      51,    80,    81,    57,    10,    18,    57,    81,    10,    57,
++      20,    26,    18,    57,    81,    81,    81,    81,    81,    81,
++      81,    81,    81,    81,    57,     4,    13,    14,    15,    72,
++      29,    30,    97,    51,    57,     4,    49,    50,    62,    63,
++      64,     3,    51,    80,     5,    51,    68,    69,    81,    97,
++       5,   100,   101,    18,    57,    81,   101,    27,    97,   101,
++      18,     5,    92,    93,    55,     4,     4,     5,    50,    64,
++      66,    76,    71,     4,     4,    57,     5,    65,    52,    51,
++      64,    53,    58,    98,    99,    53,    58,    97,    93,    58,
++       5,    58,    97,    51,    53,    58,    55,     4,    59,    52,
++      56,    58,    71,    52,    59,    64,    52,    68,     6,    16,
++      75,   100,    58,     4,    92,    59,    64,    58,    59,    52,
++       5,    22,    23,    64,    67,    52,     4,    50,    66,    65,
++       4,    52,    52
+ };
+ 
+-static const yytype_int16 yycheck[] =
++  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
++static const yytype_uint8 yyr1[] =
+ {
+-      12,    96,    96,    52,     4,     5,     4,     5,     4,     5,
+-     105,     4,     5,    97,   108,     5,     8,    44,    38,    29,
+-      30,     8,     5,     8,    51,    45,     6,    76,    48,     5,
+-       8,    18,     4,    18,    83,    49,    16,    45,    45,     4,
+-       5,    43,    50,    50,    34,     3,   140,     5,     0,     7,
+-      50,    43,    50,   137,    50,    75,    43,    50,    43,    79,
+-      43,    19,    49,    45,    49,    43,   160,   116,    50,    41,
+-      42,    49,     4,     5,   123,   169,    41,    42,    29,    30,
+-     175,    44,     5,   178,     7,    48,     9,    31,    11,    12,
+-      22,    23,     4,     5,    17,    45,    19,     4,    21,    45,
+-      50,    24,    25,    32,    50,    28,    13,    14,    15,    41,
+-      42,    45,    35,    36,    37,     4,    50,    40,     4,     5,
+-       3,    80,   134,    46,     5,    84,     7,    44,     9,    33,
+-      11,    12,     5,     3,     3,    20,    17,    43,    19,    49,
+-      21,    49,    10,    24,    25,    10,    20,    28,    26,    49,
+-     162,    49,     3,    43,    35,    36,    37,     5,     8,    40,
+-      18,    27,    18,     5,     4,    47,     4,     4,    44,    49,
+-       5,    43,    43,     4,    51,   142,    51,    71,   155,   117,
+-      47,    44,   113,    44,    44,    44,   146,    51,    -1,    51,
+-      44,    -1,    28
++       0,    60,    61,    62,    62,    63,    64,    64,    65,    65,
++      66,    66,    66,    67,    67,    68,    68,    69,    69,    70,
++      70,    71,    71,    72,    72,    72,    73,    73,    74,    74,
++      74,    75,    75,    75,    76,    76,    77,    77,    77,    77,
++      78,    79,    79,    80,    80,    81,    81,    82,    82,    83,
++      83,    84,    84,    85,    85,    86,    86,    87,    87,    88,
++      88,    89,    89,    90,    90,    91,    91,    92,    93,    93,
++      94,    94,    94,    95,    96,    97,    97,    97,    97,    97,
++      97,    97,    97,    97,    97,    97,    97,    97,    97,    97,
++      97,    97,    97,    97,    97,    97,    97,    97,    98,    98,
++      99,    99,    99,   100,   101,   101,   102,   102,   102,   103,
++     103,   103,   104,   105,   105,   106,   106,   107,   107,   107,
++     108,   108,   109,   109,   110,   110,   110,   111,   111
+ };
+ 
+-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+-   symbol of state STATE-NUM.  */
+-static const yytype_uint8 yystos[] =
++  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
++static const yytype_uint8 yyr2[] =
+ {
+-       0,     5,    53,    93,    49,     0,    31,     4,     5,    50,
+-      57,    61,    62,    29,    30,    94,    43,    50,    61,    32,
+-       4,     3,    44,    33,     5,    89,    90,    91,    92,     3,
+-       5,     7,    19,    34,    91,     5,     7,     9,    11,    12,
+-      17,    19,    21,    24,    25,    28,    35,    36,    37,    40,
+-      46,    64,    65,    68,    69,    70,    73,    74,    77,    78,
+-      79,    80,    81,    85,    86,    87,    88,     3,     3,    20,
+-       8,    43,    71,    72,    49,    10,    18,    49,    72,    10,
+-      49,    20,    26,    18,    49,    72,    72,    49,     4,    13,
+-      14,    15,    63,    29,    30,    80,    43,    49,     4,    41,
+-      42,    54,    55,    56,     3,    43,    71,     5,    43,    59,
+-      60,    72,    80,     5,    83,    84,    18,    49,    72,    84,
+-      27,    80,    84,    18,     5,    75,    76,    47,     4,     4,
+-       5,    56,    57,    67,    62,     4,     4,    49,    57,    44,
+-      43,    56,    45,    50,    81,    82,    45,    50,    80,    76,
+-      50,     5,    50,    80,    43,    45,    50,    47,    51,    44,
+-      48,    50,    62,    44,    51,    56,    44,    59,     6,    16,
+-      66,    83,    50,     4,    75,    51,    56,    50,    51,    44,
+-       5,    22,    23,    56,    58,    44,    57,    57,    44,    44
++       0,     2,     8,     1,     2,     2,     1,     1,     1,     1,
++       1,     2,     1,     1,     1,     3,     4,     1,     3,     1,
++       4,     1,     2,     1,     1,     1,     3,     4,     1,     2,
++       2,     2,     2,     2,     1,     3,     1,     4,     4,     7,
++       1,     1,     1,     4,     7,     1,     3,     1,     2,     1,
++       2,     1,     2,     1,     2,     1,     2,     1,     2,     1,
++       2,     1,     2,     1,     2,     2,     3,     4,     1,     3,
++       2,     3,     5,     4,     2,     1,     2,     1,     1,     1,
++       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
++       1,     1,     1,     1,     1,     1,     1,     1,     1,     2,
++       1,     2,     2,     2,     1,     3,     4,     3,     4,     4,
++       3,     4,     4,     1,     4,     3,     3,     7,     6,     4,
++       1,     1,     1,     2,     4,     3,     1,     1,     1
+ };
+ 
+-#define yyerrok		(yyerrstatus = 0)
+-#define yyclearin	(yychar = YYEMPTY)
+-#define YYEMPTY		(-2)
+-#define YYEOF		0
+-
+-#define YYACCEPT	goto yyacceptlab
+-#define YYABORT		goto yyabortlab
+-#define YYERROR		goto yyerrorlab
+ 
++#define yyerrok         (yyerrstatus = 0)
++#define yyclearin       (yychar = YYEMPTY)
++#define YYEMPTY         (-2)
++#define YYEOF           0
++
++#define YYACCEPT        goto yyacceptlab
++#define YYABORT         goto yyabortlab
++#define YYERROR         goto yyerrorlab
+ 
+-/* Like YYERROR except do call yyerror.  This remains here temporarily
+-   to ease the transition to the new meaning of YYERROR, for GCC.
+-   Once GCC version 2 has supplanted version 1, this can go.  */
+-
+-#define YYFAIL		goto yyerrlab
+ 
+ #define YYRECOVERING()  (!!yyerrstatus)
+ 
+-#define YYBACKUP(Token, Value)					\
+-do								\
+-  if (yychar == YYEMPTY && yylen == 1)				\
+-    {								\
+-      yychar = (Token);						\
+-      yylval = (Value);						\
+-      yytoken = YYTRANSLATE (yychar);				\
+-      YYPOPSTACK (1);						\
+-      goto yybackup;						\
+-    }								\
+-  else								\
+-    {								\
++#define YYBACKUP(Token, Value)                                  \
++do                                                              \
++  if (yychar == YYEMPTY)                                        \
++    {                                                           \
++      yychar = (Token);                                         \
++      yylval = (Value);                                         \
++      YYPOPSTACK (yylen);                                       \
++      yystate = *yyssp;                                         \
++      goto yybackup;                                            \
++    }                                                           \
++  else                                                          \
++    {                                                           \
+       yyerror (YY_("syntax error: cannot back up")); \
+-      YYERROR;							\
+-    }								\
+-while (YYID (0))
+-
+-
+-#define YYTERROR	1
+-#define YYERRCODE	256
+-
+-
+-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+-   If N is 0, then set CURRENT to the empty location which ends
+-   the previous symbol: RHS[0] (always defined).  */
+-
+-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+-#ifndef YYLLOC_DEFAULT
+-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+-    do									\
+-      if (YYID (N))                                                    \
+-	{								\
+-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+-	}								\
+-      else								\
+-	{								\
+-	  (Current).first_line   = (Current).last_line   =		\
+-	    YYRHSLOC (Rhs, 0).last_line;				\
+-	  (Current).first_column = (Current).last_column =		\
+-	    YYRHSLOC (Rhs, 0).last_column;				\
+-	}								\
+-    while (YYID (0))
+-#endif
++      YYERROR;                                                  \
++    }                                                           \
++while (0)
++
++/* Error token number */
++#define YYTERROR        1
++#define YYERRCODE       256
+ 
+ 
+-/* YY_LOCATION_PRINT -- Print the location on the stream.
+-   This macro was not mandated originally: define only if we know
+-   we won't break user code: when these are the locations we know.  */
+-
+-#ifndef YY_LOCATION_PRINT
+-# if YYLTYPE_IS_TRIVIAL
+-#  define YY_LOCATION_PRINT(File, Loc)			\
+-     fprintf (File, "%d.%d-%d.%d",			\
+-	      (Loc).first_line, (Loc).first_column,	\
+-	      (Loc).last_line,  (Loc).last_column)
+-# else
+-#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+-# endif
+-#endif
+-
+-
+-/* YYLEX -- calling `yylex' with the right arguments.  */
+-
+-#ifdef YYLEX_PARAM
+-# define YYLEX yylex (YYLEX_PARAM)
+-#else
+-# define YYLEX yylex ()
+-#endif
+ 
+ /* Enable debugging if requested.  */
+ #if YYDEBUG
+@@ -926,54 +902,46 @@
+ #  define YYFPRINTF fprintf
+ # endif
+ 
+-# define YYDPRINTF(Args)			\
+-do {						\
+-  if (yydebug)					\
+-    YYFPRINTF Args;				\
+-} while (YYID (0))
+-
+-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+-do {									  \
+-  if (yydebug)								  \
+-    {									  \
+-      YYFPRINTF (stderr, "%s ", Title);					  \
+-      yy_symbol_print (stderr,						  \
+-		  Type, Value); \
+-      YYFPRINTF (stderr, "\n");						  \
+-    }									  \
+-} while (YYID (0))
++# define YYDPRINTF(Args)                        \
++do {                                            \
++  if (yydebug)                                  \
++    YYFPRINTF Args;                             \
++} while (0)
+ 
++/* This macro is provided for backward compatibility. */
++#ifndef YY_LOCATION_PRINT
++# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
++#endif
+ 
+-/*--------------------------------.
+-| Print this symbol on YYOUTPUT.  |
+-`--------------------------------*/
+ 
+-/*ARGSUSED*/
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
++# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
++do {                                                                      \
++  if (yydebug)                                                            \
++    {                                                                     \
++      YYFPRINTF (stderr, "%s ", Title);                                   \
++      yy_symbol_print (stderr,                                            \
++                  Type, Value); \
++      YYFPRINTF (stderr, "\n");                                           \
++    }                                                                     \
++} while (0)
++
++
++/*----------------------------------------.
++| Print this symbol's value on YYOUTPUT.  |
++`----------------------------------------*/
++
+ static void
+ yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+-#else
+-static void
+-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+-    FILE *yyoutput;
+-    int yytype;
+-    YYSTYPE const * const yyvaluep;
+-#endif
+ {
++  FILE *yyo = yyoutput;
++  YYUSE (yyo);
+   if (!yyvaluep)
+     return;
+ # ifdef YYPRINT
+   if (yytype < YYNTOKENS)
+     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+-# else
+-  YYUSE (yyoutput);
+ # endif
+-  switch (yytype)
+-    {
+-      default:
+-	break;
+-    }
++  YYUSE (yytype);
+ }
+ 
+ 
+@@ -981,22 +949,11 @@
+ | Print this symbol on YYOUTPUT.  |
+ `--------------------------------*/
+ 
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+ static void
+ yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+-#else
+-static void
+-yy_symbol_print (yyoutput, yytype, yyvaluep)
+-    FILE *yyoutput;
+-    int yytype;
+-    YYSTYPE const * const yyvaluep;
+-#endif
+ {
+-  if (yytype < YYNTOKENS)
+-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+-  else
+-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
++  YYFPRINTF (yyoutput, "%s %s (",
++             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+ 
+   yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+   YYFPRINTF (yyoutput, ")");
+@@ -1007,16 +964,8 @@
+ | TOP (included).                                                   |
+ `------------------------------------------------------------------*/
+ 
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+ static void
+ yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+-#else
+-static void
+-yy_stack_print (yybottom, yytop)
+-    yytype_int16 *yybottom;
+-    yytype_int16 *yytop;
+-#endif
+ {
+   YYFPRINTF (stderr, "Stack now");
+   for (; yybottom <= yytop; yybottom++)
+@@ -1027,49 +976,42 @@
+   YYFPRINTF (stderr, "\n");
+ }
+ 
+-# define YY_STACK_PRINT(Bottom, Top)				\
+-do {								\
+-  if (yydebug)							\
+-    yy_stack_print ((Bottom), (Top));				\
+-} while (YYID (0))
++# define YY_STACK_PRINT(Bottom, Top)                            \
++do {                                                            \
++  if (yydebug)                                                  \
++    yy_stack_print ((Bottom), (Top));                           \
++} while (0)
+ 
+ 
+ /*------------------------------------------------.
+ | Report that the YYRULE is going to be reduced.  |
+ `------------------------------------------------*/
+ 
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+-static void
+-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+-#else
+ static void
+-yy_reduce_print (yyvsp, yyrule)
+-    YYSTYPE *yyvsp;
+-    int yyrule;
+-#endif
++yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
+ {
++  unsigned long int yylno = yyrline[yyrule];
+   int yynrhs = yyr2[yyrule];
+   int yyi;
+-  unsigned long int yylno = yyrline[yyrule];
+   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+-	     yyrule - 1, yylno);
++             yyrule - 1, yylno);
+   /* The symbols being reduced.  */
+   for (yyi = 0; yyi < yynrhs; yyi++)
+     {
+       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+-		       &(yyvsp[(yyi + 1) - (yynrhs)])
+-		       		       );
++      yy_symbol_print (stderr,
++                       yystos[yyssp[yyi + 1 - yynrhs]],
++                       &(yyvsp[(yyi + 1) - (yynrhs)])
++                                              );
+       YYFPRINTF (stderr, "\n");
+     }
+ }
+ 
+-# define YY_REDUCE_PRINT(Rule)		\
+-do {					\
+-  if (yydebug)				\
+-    yy_reduce_print (yyvsp, Rule); \
+-} while (YYID (0))
++# define YY_REDUCE_PRINT(Rule)          \
++do {                                    \
++  if (yydebug)                          \
++    yy_reduce_print (yyssp, yyvsp, Rule); \
++} while (0)
+ 
+ /* Nonzero means print parse trace.  It is left uninitialized so that
+    multiple parsers can coexist.  */
+@@ -1083,7 +1025,7 @@
+ 
+ 
+ /* YYINITDEPTH -- initial size of the parser's stacks.  */
+-#ifndef	YYINITDEPTH
++#ifndef YYINITDEPTH
+ # define YYINITDEPTH 200
+ #endif
+ 
+@@ -1098,7 +1040,6 @@
+ # define YYMAXDEPTH 10000
+ #endif
+ 
+-
+ 
+ #if YYERROR_VERBOSE
+ 
+@@ -1107,15 +1048,8 @@
+ #   define yystrlen strlen
+ #  else
+ /* Return the length of YYSTR.  */
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+ static YYSIZE_T
+ yystrlen (const char *yystr)
+-#else
+-static YYSIZE_T
+-yystrlen (yystr)
+-    const char *yystr;
+-#endif
+ {
+   YYSIZE_T yylen;
+   for (yylen = 0; yystr[yylen]; yylen++)
+@@ -1131,16 +1065,8 @@
+ #  else
+ /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+    YYDEST.  */
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+ static char *
+ yystpcpy (char *yydest, const char *yysrc)
+-#else
+-static char *
+-yystpcpy (yydest, yysrc)
+-    char *yydest;
+-    const char *yysrc;
+-#endif
+ {
+   char *yyd = yydest;
+   const char *yys = yysrc;
+@@ -1170,27 +1096,27 @@
+       char const *yyp = yystr;
+ 
+       for (;;)
+-	switch (*++yyp)
+-	  {
+-	  case '\'':
+-	  case ',':
+-	    goto do_not_strip_quotes;
+-
+-	  case '\\':
+-	    if (*++yyp != '\\')
+-	      goto do_not_strip_quotes;
+-	    /* Fall through.  */
+-	  default:
+-	    if (yyres)
+-	      yyres[yyn] = *yyp;
+-	    yyn++;
+-	    break;
+-
+-	  case '"':
+-	    if (yyres)
+-	      yyres[yyn] = '\0';
+-	    return yyn;
+-	  }
++        switch (*++yyp)
++          {
++          case '\'':
++          case ',':
++            goto do_not_strip_quotes;
++
++          case '\\':
++            if (*++yyp != '\\')
++              goto do_not_strip_quotes;
++            /* Fall through.  */
++          default:
++            if (yyres)
++              yyres[yyn] = *yyp;
++            yyn++;
++            break;
++
++          case '"':
++            if (yyres)
++              yyres[yyn] = '\0';
++            return yyn;
++          }
+     do_not_strip_quotes: ;
+     }
+ 
+@@ -1201,161 +1127,160 @@
+ }
+ # endif
+ 
+-/* Copy into YYRESULT an error message about the unexpected token
+-   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+-   including the terminating null byte.  If YYRESULT is null, do not
+-   copy anything; just return the number of bytes that would be
+-   copied.  As a special case, return 0 if an ordinary "syntax error"
+-   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+-   size calculation.  */
+-static YYSIZE_T
+-yysyntax_error (char *yyresult, int yystate, int yychar)
++/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
++   about the unexpected token YYTOKEN for the state stack whose top is
++   YYSSP.
++
++   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
++   not large enough to hold the message.  In that case, also set
++   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
++   required number of bytes is too large to store.  */
++static int
++yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
++                yytype_int16 *yyssp, int yytoken)
+ {
+-  int yyn = yypact[yystate];
+-
+-  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+-    return 0;
+-  else
++  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
++  YYSIZE_T yysize = yysize0;
++  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
++  /* Internationalized format string. */
++  const char *yyformat = YY_NULLPTR;
++  /* Arguments of yyformat. */
++  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
++  /* Number of reported tokens (one for the "unexpected", one per
++     "expected"). */
++  int yycount = 0;
++
++  /* There are many possibilities here to consider:
++     - If this state is a consistent state with a default action, then
++       the only way this function was invoked is if the default action
++       is an error action.  In that case, don't check for expected
++       tokens because there are none.
++     - The only way there can be no lookahead present (in yychar) is if
++       this state is a consistent state with a default action.  Thus,
++       detecting the absence of a lookahead is sufficient to determine
++       that there is no unexpected or expected token to report.  In that
++       case, just report a simple "syntax error".
++     - Don't assume there isn't a lookahead just because this state is a
++       consistent state with a default action.  There might have been a
++       previous inconsistent state, consistent state with a non-default
++       action, or user semantic action that manipulated yychar.
++     - Of course, the expected token list depends on states to have
++       correct lookahead information, and it depends on the parser not
++       to perform extra reductions after fetching a lookahead from the
++       scanner and before detecting a syntax error.  Thus, state merging
++       (from LALR or IELR) and default reductions corrupt the expected
++       token list.  However, the list is correct for canonical LR with
++       one exception: it will still contain any token that will not be
++       accepted due to an error action in a later state.
++  */
++  if (yytoken != YYEMPTY)
+     {
+-      int yytype = YYTRANSLATE (yychar);
+-      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+-      YYSIZE_T yysize = yysize0;
+-      YYSIZE_T yysize1;
+-      int yysize_overflow = 0;
+-      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+-      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+-      int yyx;
+-
+-# if 0
+-      /* This is so xgettext sees the translatable formats that are
+-	 constructed on the fly.  */
+-      YY_("syntax error, unexpected %s");
+-      YY_("syntax error, unexpected %s, expecting %s");
+-      YY_("syntax error, unexpected %s, expecting %s or %s");
+-      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+-      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+-# endif
+-      char *yyfmt;
+-      char const *yyf;
+-      static char const yyunexpected[] = "syntax error, unexpected %s";
+-      static char const yyexpecting[] = ", expecting %s";
+-      static char const yyor[] = " or %s";
+-      char yyformat[sizeof yyunexpected
+-		    + sizeof yyexpecting - 1
+-		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+-		       * (sizeof yyor - 1))];
+-      char const *yyprefix = yyexpecting;
+-
+-      /* Start YYX at -YYN if negative to avoid negative indexes in
+-	 YYCHECK.  */
+-      int yyxbegin = yyn < 0 ? -yyn : 0;
+-
+-      /* Stay within bounds of both yycheck and yytname.  */
+-      int yychecklim = YYLAST - yyn + 1;
+-      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+-      int yycount = 1;
+-
+-      yyarg[0] = yytname[yytype];
+-      yyfmt = yystpcpy (yyformat, yyunexpected);
+-
+-      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+-	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+-	  {
+-	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+-	      {
+-		yycount = 1;
+-		yysize = yysize0;
+-		yyformat[sizeof yyunexpected - 1] = '\0';
+-		break;
+-	      }
+-	    yyarg[yycount++] = yytname[yyx];
+-	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+-	    yysize_overflow |= (yysize1 < yysize);
+-	    yysize = yysize1;
+-	    yyfmt = yystpcpy (yyfmt, yyprefix);
+-	    yyprefix = yyor;
+-	  }
+-
+-      yyf = YY_(yyformat);
+-      yysize1 = yysize + yystrlen (yyf);
+-      yysize_overflow |= (yysize1 < yysize);
+-      yysize = yysize1;
+-
+-      if (yysize_overflow)
+-	return YYSIZE_MAXIMUM;
+-
+-      if (yyresult)
+-	{
+-	  /* Avoid sprintf, as that infringes on the user's name space.
+-	     Don't have undefined behavior even if the translation
+-	     produced a string with the wrong number of "%s"s.  */
+-	  char *yyp = yyresult;
+-	  int yyi = 0;
+-	  while ((*yyp = *yyf) != '\0')
+-	    {
+-	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+-		{
+-		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+-		  yyf += 2;
+-		}
+-	      else
+-		{
+-		  yyp++;
+-		  yyf++;
+-		}
+-	    }
+-	}
+-      return yysize;
++      int yyn = yypact[*yyssp];
++      yyarg[yycount++] = yytname[yytoken];
++      if (!yypact_value_is_default (yyn))
++        {
++          /* Start YYX at -YYN if negative to avoid negative indexes in
++             YYCHECK.  In other words, skip the first -YYN actions for
++             this state because they are default actions.  */
++          int yyxbegin = yyn < 0 ? -yyn : 0;
++          /* Stay within bounds of both yycheck and yytname.  */
++          int yychecklim = YYLAST - yyn + 1;
++          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
++          int yyx;
++
++          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
++            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
++                && !yytable_value_is_error (yytable[yyx + yyn]))
++              {
++                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
++                  {
++                    yycount = 1;
++                    yysize = yysize0;
++                    break;
++                  }
++                yyarg[yycount++] = yytname[yyx];
++                {
++                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
++                  if (! (yysize <= yysize1
++                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
++                    return 2;
++                  yysize = yysize1;
++                }
++              }
++        }
+     }
++
++  switch (yycount)
++    {
++# define YYCASE_(N, S)                      \
++      case N:                               \
++        yyformat = S;                       \
++      break
++      YYCASE_(0, YY_("syntax error"));
++      YYCASE_(1, YY_("syntax error, unexpected %s"));
++      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
++      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
++      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
++      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
++# undef YYCASE_
++    }
++
++  {
++    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
++    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
++      return 2;
++    yysize = yysize1;
++  }
++
++  if (*yymsg_alloc < yysize)
++    {
++      *yymsg_alloc = 2 * yysize;
++      if (! (yysize <= *yymsg_alloc
++             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
++        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
++      return 1;
++    }
++
++  /* Avoid sprintf, as that infringes on the user's name space.
++     Don't have undefined behavior even if the translation
++     produced a string with the wrong number of "%s"s.  */
++  {
++    char *yyp = *yymsg;
++    int yyi = 0;
++    while ((*yyp = *yyformat) != '\0')
++      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
++        {
++          yyp += yytnamerr (yyp, yyarg[yyi++]);
++          yyformat += 2;
++        }
++      else
++        {
++          yyp++;
++          yyformat++;
++        }
++  }
++  return 0;
+ }
+ #endif /* YYERROR_VERBOSE */
+-
+ 
+ /*-----------------------------------------------.
+ | Release the memory associated to this symbol.  |
+ `-----------------------------------------------*/
+ 
+-/*ARGSUSED*/
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+ static void
+ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+-#else
+-static void
+-yydestruct (yymsg, yytype, yyvaluep)
+-    const char *yymsg;
+-    int yytype;
+-    YYSTYPE *yyvaluep;
+-#endif
+ {
+   YYUSE (yyvaluep);
+-
+   if (!yymsg)
+     yymsg = "Deleting";
+   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ 
+-  switch (yytype)
+-    {
+-
+-      default:
+-	break;
+-    }
++  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
++  YYUSE (yytype);
++  YY_IGNORE_MAYBE_UNINITIALIZED_END
+ }
+ 
+-/* Prevent warnings from -Wmissing-prototypes.  */
+-#ifdef YYPARSE_PARAM
+-#if defined __STDC__ || defined __cplusplus
+-int yyparse (void *YYPARSE_PARAM);
+-#else
+-int yyparse ();
+-#endif
+-#else /* ! YYPARSE_PARAM */
+-#if defined __STDC__ || defined __cplusplus
+-int yyparse (void);
+-#else
+-int yyparse ();
+-#endif
+-#endif /* ! YYPARSE_PARAM */
++
+ 
+ 
+ /* The lookahead symbol.  */
+@@ -1363,49 +1288,26 @@
+ 
+ /* The semantic value of the lookahead symbol.  */
+ YYSTYPE yylval;
+-
+ /* Number of syntax errors so far.  */
+ int yynerrs;
+ 
+ 
++/*----------.
++| yyparse.  |
++`----------*/
+ 
+-/*-------------------------.
+-| yyparse or yypush_parse.  |
+-`-------------------------*/
+-
+-#ifdef YYPARSE_PARAM
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+-int
+-yyparse (void *YYPARSE_PARAM)
+-#else
+-int
+-yyparse (YYPARSE_PARAM)
+-    void *YYPARSE_PARAM;
+-#endif
+-#else /* ! YYPARSE_PARAM */
+-#if (defined __STDC__ || defined __C99__FUNC__ \
+-     || defined __cplusplus || defined _MSC_VER)
+ int
+ yyparse (void)
+-#else
+-int
+-yyparse ()
+-
+-#endif
+-#endif
+ {
+-
+-
+     int yystate;
+     /* Number of tokens to shift before error messages enabled.  */
+     int yyerrstatus;
+ 
+     /* The stacks and their tools:
+-       `yyss': related to states.
+-       `yyvs': related to semantic values.
++       'yyss': related to states.
++       'yyvs': related to semantic values.
+ 
+-       Refer to the stacks thru separate pointers, to allow yyoverflow
++       Refer to the stacks through separate pointers, to allow yyoverflow
+        to reallocate them elsewhere.  */
+ 
+     /* The state stack.  */
+@@ -1423,7 +1325,7 @@
+   int yyn;
+   int yyresult;
+   /* Lookahead token as an internal (translated) token number.  */
+-  int yytoken;
++  int yytoken = 0;
+   /* The variables used to return semantic value and location from the
+      action routines.  */
+   YYSTYPE yyval;
+@@ -1441,9 +1343,8 @@
+      Keep to zero when no symbol should be popped.  */
+   int yylen = 0;
+ 
+-  yytoken = 0;
+-  yyss = yyssa;
+-  yyvs = yyvsa;
++  yyssp = yyss = yyssa;
++  yyvsp = yyvs = yyvsa;
+   yystacksize = YYINITDEPTH;
+ 
+   YYDPRINTF ((stderr, "Starting parse\n"));
+@@ -1452,14 +1353,6 @@
+   yyerrstatus = 0;
+   yynerrs = 0;
+   yychar = YYEMPTY; /* Cause a token to be read.  */
+-
+-  /* Initialize stack pointers.
+-     Waste one element of value and location stack
+-     so that they stay on the same level as the state stack.
+-     The wasted elements are never initialized.  */
+-  yyssp = yyss;
+-  yyvsp = yyvs;
+-
+   goto yysetstate;
+ 
+ /*------------------------------------------------------------.
+@@ -1480,23 +1373,23 @@
+ 
+ #ifdef yyoverflow
+       {
+-	/* Give user a chance to reallocate the stack.  Use copies of
+-	   these so that the &'s don't force the real ones into
+-	   memory.  */
+-	YYSTYPE *yyvs1 = yyvs;
+-	yytype_int16 *yyss1 = yyss;
+-
+-	/* Each stack pointer address is followed by the size of the
+-	   data in use in that stack, in bytes.  This used to be a
+-	   conditional around just the two extra args, but that might
+-	   be undefined if yyoverflow is a macro.  */
+-	yyoverflow (YY_("memory exhausted"),
+-		    &yyss1, yysize * sizeof (*yyssp),
+-		    &yyvs1, yysize * sizeof (*yyvsp),
+-		    &yystacksize);
++        /* Give user a chance to reallocate the stack.  Use copies of
++           these so that the &'s don't force the real ones into
++           memory.  */
++        YYSTYPE *yyvs1 = yyvs;
++        yytype_int16 *yyss1 = yyss;
++
++        /* Each stack pointer address is followed by the size of the
++           data in use in that stack, in bytes.  This used to be a
++           conditional around just the two extra args, but that might
++           be undefined if yyoverflow is a macro.  */
++        yyoverflow (YY_("memory exhausted"),
++                    &yyss1, yysize * sizeof (*yyssp),
++                    &yyvs1, yysize * sizeof (*yyvsp),
++                    &yystacksize);
+ 
+-	yyss = yyss1;
+-	yyvs = yyvs1;
++        yyss = yyss1;
++        yyvs = yyvs1;
+       }
+ #else /* no yyoverflow */
+ # ifndef YYSTACK_RELOCATE
+@@ -1504,22 +1397,22 @@
+ # else
+       /* Extend the stack our own way.  */
+       if (YYMAXDEPTH <= yystacksize)
+-	goto yyexhaustedlab;
++        goto yyexhaustedlab;
+       yystacksize *= 2;
+       if (YYMAXDEPTH < yystacksize)
+-	yystacksize = YYMAXDEPTH;
++        yystacksize = YYMAXDEPTH;
+ 
+       {
+-	yytype_int16 *yyss1 = yyss;
+-	union yyalloc *yyptr =
+-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+-	if (! yyptr)
+-	  goto yyexhaustedlab;
+-	YYSTACK_RELOCATE (yyss_alloc, yyss);
+-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
++        yytype_int16 *yyss1 = yyss;
++        union yyalloc *yyptr =
++          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
++        if (! yyptr)
++          goto yyexhaustedlab;
++        YYSTACK_RELOCATE (yyss_alloc, yyss);
++        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ #  undef YYSTACK_RELOCATE
+-	if (yyss1 != yyssa)
+-	  YYSTACK_FREE (yyss1);
++        if (yyss1 != yyssa)
++          YYSTACK_FREE (yyss1);
+       }
+ # endif
+ #endif /* no yyoverflow */
+@@ -1528,10 +1421,10 @@
+       yyvsp = yyvs + yysize - 1;
+ 
+       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+-		  (unsigned long int) yystacksize));
++                  (unsigned long int) yystacksize));
+ 
+       if (yyss + yystacksize - 1 <= yyssp)
+-	YYABORT;
++        YYABORT;
+     }
+ 
+   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+@@ -1551,7 +1444,7 @@
+ 
+   /* First try to decide what to do without reference to lookahead token.  */
+   yyn = yypact[yystate];
+-  if (yyn == YYPACT_NINF)
++  if (yypact_value_is_default (yyn))
+     goto yydefault;
+ 
+   /* Not known => get a lookahead token if don't already have one.  */
+@@ -1560,7 +1453,7 @@
+   if (yychar == YYEMPTY)
+     {
+       YYDPRINTF ((stderr, "Reading a token: "));
+-      yychar = YYLEX;
++      yychar = yylex ();
+     }
+ 
+   if (yychar <= YYEOF)
+@@ -1582,8 +1475,8 @@
+   yyn = yytable[yyn];
+   if (yyn <= 0)
+     {
+-      if (yyn == 0 || yyn == YYTABLE_NINF)
+-	goto yyerrlab;
++      if (yytable_value_is_error (yyn))
++        goto yyerrlab;
+       yyn = -yyn;
+       goto yyreduce;
+     }
+@@ -1600,7 +1493,9 @@
+   yychar = YYEMPTY;
+ 
+   yystate = yyn;
++  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+   *++yyvsp = yylval;
++  YY_IGNORE_MAYBE_UNINITIALIZED_END
+ 
+   goto yynewstate;
+ 
+@@ -1623,7 +1518,7 @@
+   yylen = yyr2[yyn];
+ 
+   /* If YYLEN is nonzero, implement the default value of the action:
+-     `$$ = $1'.
++     '$$ = $1'.
+ 
+      Otherwise, the following line sets YYVAL to garbage.
+      This behavior is undocumented and Bison
+@@ -1637,739 +1532,835 @@
+   switch (yyn)
+     {
+         case 2:
+-
+-/* Line 1455 of yacc.c  */
+-#line 122 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_DEFINITIONS|(yyvsp[(3) - (8)].constant));
+-                    _asn1_set_name((yyval.node),_asn1_get_name((yyvsp[(1) - (8)].node)));
+-                    _asn1_set_name((yyvsp[(1) - (8)].node),"");
+-                    _asn1_set_right((yyvsp[(1) - (8)].node),(yyvsp[(7) - (8)].node));
+-                    _asn1_set_down((yyval.node),(yyvsp[(1) - (8)].node));
++#line 138 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_DEFINITIONS|(yyvsp[-5].constant));
++                    _asn1_set_name((yyval.node),_asn1_get_name((yyvsp[-7].node)));
++                    _asn1_set_name((yyvsp[-7].node),"");
++                    _asn1_set_right((yyvsp[-7].node),(yyvsp[-1].node));
++                    _asn1_set_down((yyval.node),(yyvsp[-7].node));
+ 
+ 		    p_tree=(yyval.node);
+ 		    }
++#line 1544 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 3:
+-
+-/* Line 1455 of yacc.c  */
+-#line 132 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 148 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1550 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 4:
+-
+-/* Line 1455 of yacc.c  */
+-#line 133 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(2) - (2)].str));}
++#line 149 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1556 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 5:
+-
+-/* Line 1455 of yacc.c  */
+-#line 136 "ASN1.y"
+-    {strcpy((yyval.str),"-");
+-                       strcat((yyval.str),(yyvsp[(2) - (2)].str));}
++#line 152 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"-%s",(yyvsp[0].str));}
++#line 1562 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 6:
+-
+-/* Line 1455 of yacc.c  */
+-#line 140 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 155 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1568 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 7:
+-
+-/* Line 1455 of yacc.c  */
+-#line 141 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 156 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1574 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 8:
+-
+-/* Line 1455 of yacc.c  */
+-#line 144 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 159 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1580 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 9:
+-
+-/* Line 1455 of yacc.c  */
+-#line 145 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 160 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1586 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 10:
+-
+-/* Line 1455 of yacc.c  */
+-#line 148 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 163 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1592 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 11:
+-
+-/* Line 1455 of yacc.c  */
+-#line 149 "ASN1.y"
+-    {strcpy((yyval.str),(yyvsp[(1) - (1)].str));}
++#line 164 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"-%s",(yyvsp[0].str));}
++#line 1598 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 12:
+-
+-/* Line 1455 of yacc.c  */
+-#line 152 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+-                                       _asn1_set_value((yyval.node),(yyvsp[(2) - (3)].str),strlen((yyvsp[(2) - (3)].str))+1);}
++#line 165 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1604 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 13:
+-
+-/* Line 1455 of yacc.c  */
+-#line 154 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+-	                               _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+-                                       _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 168 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1610 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 14:
+-
+-/* Line 1455 of yacc.c  */
+-#line 159 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 169 "ASN1.y" /* yacc.c:1646  */
++    {snprintf((yyval.str),sizeof((yyval.str)),"%s",(yyvsp[0].str));}
++#line 1616 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 15:
+-
+-/* Line 1455 of yacc.c  */
+-#line 160 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (3)].node);
+-                                            _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (3)].node)),(yyvsp[(3) - (3)].node));}
++#line 172 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++                                       _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1623 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 16:
+-
+-/* Line 1455 of yacc.c  */
+-#line 164 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+-                                   _asn1_set_value((yyval.node),(yyvsp[(1) - (1)].str),strlen((yyvsp[(1) - (1)].str))+1);}
++#line 174 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++	                               _asn1_set_name((yyval.node),(yyvsp[-3].str));
++                                       _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1631 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 17:
+-
+-/* Line 1455 of yacc.c  */
+-#line 166 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+-	                            _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+-                                    _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 179 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 1637 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 18:
+-
+-/* Line 1455 of yacc.c  */
+-#line 171 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 180 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[-2].node);
++                                            _asn1_set_right(_asn1_get_last_right((yyvsp[-2].node)),(yyvsp[0].node));}
++#line 1644 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 19:
+-
+-/* Line 1455 of yacc.c  */
+-#line 172 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (2)].node);
+-                                                    _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (2)].node)),(yyvsp[(2) - (2)].node));}
++#line 184 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++                                   _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 1651 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 20:
+-
+-/* Line 1455 of yacc.c  */
+-#line 176 "ASN1.y"
+-    {(yyval.constant)=CONST_UNIVERSAL;}
++#line 186 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++	                            _asn1_set_name((yyval.node),(yyvsp[-3].str));
++                                    _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1659 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 21:
+-
+-/* Line 1455 of yacc.c  */
+-#line 177 "ASN1.y"
+-    {(yyval.constant)=CONST_PRIVATE;}
++#line 191 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 1665 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 22:
+-
+-/* Line 1455 of yacc.c  */
+-#line 178 "ASN1.y"
+-    {(yyval.constant)=CONST_APPLICATION;}
++#line 192 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[-1].node);
++                                                    _asn1_set_right(_asn1_get_last_right((yyvsp[-1].node)),(yyvsp[0].node));}
++#line 1672 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 23:
+-
+-/* Line 1455 of yacc.c  */
+-#line 181 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_TAG);
+-                            _asn1_set_value((yyval.node),(yyvsp[(2) - (3)].str),strlen((yyvsp[(2) - (3)].str))+1);}
++#line 196 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.constant)=CONST_UNIVERSAL;}
++#line 1678 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 24:
+-
+-/* Line 1455 of yacc.c  */
+-#line 183 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_TAG | (yyvsp[(2) - (4)].constant));
+-                                _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 197 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.constant)=CONST_PRIVATE;}
++#line 1684 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 25:
+-
+-/* Line 1455 of yacc.c  */
+-#line 187 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 198 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.constant)=CONST_APPLICATION;}
++#line 1690 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 26:
+-
+-/* Line 1455 of yacc.c  */
+-#line 188 "ASN1.y"
+-    {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_EXPLICIT);}
++#line 201 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_TAG);
++                            _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1697 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 27:
+-
+-/* Line 1455 of yacc.c  */
+-#line 189 "ASN1.y"
+-    {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_IMPLICIT);}
++#line 203 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_TAG | (yyvsp[-2].constant));
++                                _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1704 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 28:
+-
+-/* Line 1455 of yacc.c  */
+-#line 192 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_DEFAULT);
+-                                       _asn1_set_value((yyval.node),(yyvsp[(2) - (2)].str),strlen((yyvsp[(2) - (2)].str))+1);}
++#line 207 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 1710 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 29:
+-
+-/* Line 1455 of yacc.c  */
+-#line 194 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_DEFAULT|CONST_TRUE);}
++#line 208 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_EXPLICIT);}
++#line 1716 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 30:
+-
+-/* Line 1455 of yacc.c  */
+-#line 195 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_DEFAULT|CONST_FALSE);}
++#line 209 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_IMPLICIT);}
++#line 1722 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 31:
++#line 212 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_DEFAULT);
++                                       _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 1729 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 32:
++#line 214 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_DEFAULT|CONST_TRUE);}
++#line 1735 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 33:
+-
+-/* Line 1455 of yacc.c  */
+-#line 204 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_INTEGER);}
+-    break;
+-
+-  case 34:
+-
+-/* Line 1455 of yacc.c  */
+-#line 205 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_INTEGER|CONST_LIST);
+-	                                 _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
+-    break;
+-
+-  case 35:
+-
+-/* Line 1455 of yacc.c  */
+-#line 207 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_INTEGER);}
++#line 215 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_DEFAULT|CONST_FALSE);}
++#line 1741 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 36:
+-
+-/* Line 1455 of yacc.c  */
+-#line 209 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_INTEGER|CONST_MIN_MAX);
+-                                         _asn1_set_down((yyval.node),_asn1_add_node(TYPE_SIZE));
+-                                         _asn1_set_value(_asn1_get_down((yyval.node)),(yyvsp[(6) - (7)].str),strlen((yyvsp[(6) - (7)].str))+1);
+-                                         _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[(3) - (7)].str));}
++#line 224 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER);}
++#line 1747 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 37:
+-
+-/* Line 1455 of yacc.c  */
+-#line 215 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_BOOLEAN);}
++#line 225 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER|CONST_LIST);
++	                                 _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 1754 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 38:
+-
+-/* Line 1455 of yacc.c  */
+-#line 218 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_TIME|CONST_UTC);}
++#line 227 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER);}
++#line 1760 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 39:
+-
+-/* Line 1455 of yacc.c  */
+-#line 219 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_TIME|CONST_GENERALIZED);}
++#line 229 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER|CONST_MIN_MAX);
++                                         _asn1_set_down((yyval.node),_asn1_add_static_node(TYPE_SIZE));
++                                         _asn1_set_value(_asn1_get_down((yyval.node)),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);
++                                         _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[-4].str));}
++#line 1769 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 40:
+-
+-/* Line 1455 of yacc.c  */
+-#line 222 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SIZE|CONST_1_PARAM);
+-	                              _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 235 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_BOOLEAN);}
++#line 1775 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 41:
+-
+-/* Line 1455 of yacc.c  */
+-#line 225 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SIZE|CONST_MIN_MAX);
+-	                              _asn1_set_value((yyval.node),(yyvsp[(3) - (7)].str),strlen((yyvsp[(3) - (7)].str))+1);
+-                                      _asn1_set_name((yyval.node),(yyvsp[(6) - (7)].str));}
++#line 238 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_UTC_TIME);}
++#line 1781 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 42:
+-
+-/* Line 1455 of yacc.c  */
+-#line 230 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 239 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_GENERALIZED_TIME);}
++#line 1787 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 43:
+-
+-/* Line 1455 of yacc.c  */
+-#line 231 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(2) - (3)].node);}
++#line 242 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SIZE|CONST_1_PARAM);
++	                              _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1794 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 44:
+-
+-/* Line 1455 of yacc.c  */
+-#line 234 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_GENERALSTRING);}
++#line 245 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SIZE|CONST_MIN_MAX);
++	                              _asn1_set_value((yyval.node),(yyvsp[-4].str),strlen((yyvsp[-4].str))+1);
++                                      _asn1_set_name((yyval.node),(yyvsp[-1].str));}
++#line 1802 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 45:
+-
+-/* Line 1455 of yacc.c  */
+-#line 235 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_GENERALSTRING|CONST_SIZE);
+-					  _asn1_set_down((yyval.node),(yyvsp[(2) - (2)].node));}
++#line 250 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 1808 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 46:
+-
+-/* Line 1455 of yacc.c  */
+-#line 239 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OCTET_STRING);}
++#line 251 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[-1].node);}
++#line 1814 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 47:
+-
+-/* Line 1455 of yacc.c  */
+-#line 240 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OCTET_STRING|CONST_SIZE);
+-                                           _asn1_set_down((yyval.node),(yyvsp[(3) - (3)].node));}
++#line 254 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_GENERALSTRING);}
++#line 1820 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 48:
+-
+-/* Line 1455 of yacc.c  */
+-#line 244 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_CONSTANT);
+-	                           _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+-                                    _asn1_set_value((yyval.node),(yyvsp[(3) - (4)].str),strlen((yyvsp[(3) - (4)].str))+1);}
++#line 255 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_GENERALSTRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1827 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 49:
+-
+-/* Line 1455 of yacc.c  */
+-#line 249 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 259 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_UNIVERSAL);}
++#line 1833 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 50:
+-
+-/* Line 1455 of yacc.c  */
+-#line 250 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (3)].node);
+-                                                       _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (3)].node)),(yyvsp[(3) - (3)].node));}
++#line 260 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_NUMERIC_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1840 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 51:
+-
+-/* Line 1455 of yacc.c  */
+-#line 254 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_BIT_STRING);}
++#line 264 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_IA5_STRING);}
++#line 1846 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 52:
+-
+-/* Line 1455 of yacc.c  */
+-#line 255 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_BIT_STRING|CONST_SIZE);}
++#line 265 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_IA5_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1853 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 53:
+-
+-/* Line 1455 of yacc.c  */
+-#line 257 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_BIT_STRING|CONST_LIST);
+-                                _asn1_set_down((yyval.node),(yyvsp[(4) - (5)].node));}
++#line 269 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_TELETEX_STRING);}
++#line 1859 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 54:
+-
+-/* Line 1455 of yacc.c  */
+-#line 262 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_ENUMERATED|CONST_LIST);
+-                                _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++#line 270 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_TELETEX_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1866 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 55:
+-
+-/* Line 1455 of yacc.c  */
+-#line 267 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID);}
++#line 274 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_PRINTABLE_STRING);}
++#line 1872 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 56:
+-
+-/* Line 1455 of yacc.c  */
+-#line 270 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_IDENTIFIER);
+-                                       _asn1_set_value((yyval.node),(yyvsp[(1) - (1)].str),strlen((yyvsp[(1) - (1)].str))+1);}
++#line 275 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_PRINTABLE_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1879 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 57:
+-
+-/* Line 1455 of yacc.c  */
+-#line 272 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_IDENTIFIER|CONST_SIZE);
+-                                       _asn1_set_value((yyval.node),(yyvsp[(1) - (2)].str),strlen((yyvsp[(1) - (2)].str))+1);
+-                                       _asn1_set_down((yyval.node),(yyvsp[(2) - (2)].node));}
++#line 279 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_UNIVERSAL_STRING);}
++#line 1885 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 58:
+-
+-/* Line 1455 of yacc.c  */
+-#line 275 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 280 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_UNIVERSAL_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1892 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 59:
+-
+-/* Line 1455 of yacc.c  */
+-#line 276 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 284 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_BMP_STRING);}
++#line 1898 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 60:
++#line 285 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_BMP_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1905 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 277 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++  case 61:
++#line 289 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_UTF8_STRING);}
++#line 1911 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 62:
+-
+-/* Line 1455 of yacc.c  */
+-#line 279 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 290 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_UTF8_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1918 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 63:
+-
+-/* Line 1455 of yacc.c  */
+-#line 280 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 294 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_VISIBLE_STRING);}
++#line 1924 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 64:
+-
+-/* Line 1455 of yacc.c  */
+-#line 281 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 295 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_VISIBLE_STRING|CONST_SIZE);
++					  _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1931 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 65:
+-
+-/* Line 1455 of yacc.c  */
+-#line 282 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 299 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OCTET_STRING);}
++#line 1937 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 66:
+-
+-/* Line 1455 of yacc.c  */
+-#line 283 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 300 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OCTET_STRING|CONST_SIZE);
++                                           _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 1944 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 67:
+-
+-/* Line 1455 of yacc.c  */
+-#line 284 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 304 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_CONSTANT);
++	                           _asn1_set_name((yyval.node),(yyvsp[-3].str));
++                                    _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);}
++#line 1952 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 68:
+-
+-/* Line 1455 of yacc.c  */
+-#line 285 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 309 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 1958 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 69:
+-
+-/* Line 1455 of yacc.c  */
+-#line 286 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 310 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[-2].node);
++                                                       _asn1_set_right(_asn1_get_last_right((yyvsp[-2].node)),(yyvsp[0].node));}
++#line 1965 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 70:
+-
+-/* Line 1455 of yacc.c  */
+-#line 287 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_NULL);}
++#line 314 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_BIT_STRING);}
++#line 1971 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 71:
+-
+-/* Line 1455 of yacc.c  */
+-#line 290 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 315 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_BIT_STRING|CONST_SIZE);}
++#line 1977 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 72:
+-
+-/* Line 1455 of yacc.c  */
+-#line 291 "ASN1.y"
+-    {(yyval.node)=_asn1_mod_type((yyvsp[(2) - (2)].node),CONST_TAG);
+-                                               _asn1_set_right((yyvsp[(1) - (2)].node),_asn1_get_down((yyval.node)));
+-                                               _asn1_set_down((yyval.node),(yyvsp[(1) - (2)].node));}
++#line 317 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_BIT_STRING|CONST_LIST);
++                                _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 1984 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 73:
+-
+-/* Line 1455 of yacc.c  */
+-#line 296 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 322 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_ENUMERATED|CONST_LIST);
++                                _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 1991 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 74:
+-
+-/* Line 1455 of yacc.c  */
+-#line 297 "ASN1.y"
+-    {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_DEFAULT);
+-                                                       _asn1_set_right((yyvsp[(2) - (2)].node),_asn1_get_down((yyval.node)));
+-						       _asn1_set_down((yyval.node),(yyvsp[(2) - (2)].node));}
++#line 327 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);}
++#line 1997 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 75:
+-
+-/* Line 1455 of yacc.c  */
+-#line 300 "ASN1.y"
+-    {(yyval.node)=_asn1_mod_type((yyvsp[(1) - (2)].node),CONST_OPTION);}
++#line 330 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_IDENTIFIER);
++                                       _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 2004 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 76:
+-
+-/* Line 1455 of yacc.c  */
+-#line 303 "ASN1.y"
+-    {(yyval.node)=_asn1_set_name((yyvsp[(2) - (2)].node),(yyvsp[(1) - (2)].str));}
++#line 332 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_IDENTIFIER|CONST_SIZE);
++                                       _asn1_set_value((yyval.node),(yyvsp[-1].str),strlen((yyvsp[-1].str))+1);
++                                       _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2012 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 77:
+-
+-/* Line 1455 of yacc.c  */
+-#line 306 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++#line 335 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2018 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 78:
+-
+-/* Line 1455 of yacc.c  */
+-#line 307 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (3)].node);
+-                                                _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (3)].node)),(yyvsp[(3) - (3)].node));}
++#line 336 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2024 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+   case 79:
++#line 337 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2030 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 311 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SEQUENCE);
+-                                              _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++  case 81:
++#line 339 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2036 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 80:
+-
+-/* Line 1455 of yacc.c  */
+-#line 313 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SEQUENCE_OF);
+-                                              _asn1_set_down((yyval.node),(yyvsp[(3) - (3)].node));}
++  case 82:
++#line 340 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2042 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 81:
++  case 83:
++#line 341 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2048 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 315 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SEQUENCE_OF|CONST_SIZE);
+-                                            _asn1_set_right((yyvsp[(2) - (4)].node),(yyvsp[(4) - (4)].node));
+-                                            _asn1_set_down((yyval.node),(yyvsp[(2) - (4)].node));}
++  case 84:
++#line 342 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2054 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 82:
++  case 85:
++#line 343 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2060 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 320 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SET);
+-                                     _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++  case 86:
++#line 344 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2066 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 83:
++  case 87:
++#line 345 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2072 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 322 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SET_OF);
+-                                     _asn1_set_down((yyval.node),(yyvsp[(3) - (3)].node));}
++  case 88:
++#line 346 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2078 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 84:
++  case 89:
++#line 347 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2084 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 324 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_SET_OF|CONST_SIZE);
+-                                       _asn1_set_right((yyvsp[(2) - (4)].node),(yyvsp[(4) - (4)].node));
+-                                       _asn1_set_down((yyval.node),(yyvsp[(2) - (4)].node));}
++  case 90:
++#line 348 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2090 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 85:
++  case 91:
++#line 349 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2096 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 329 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_CHOICE);
+-                                             _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));}
++  case 92:
++#line 350 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2102 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 86:
++  case 93:
++#line 351 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2108 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 333 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_ANY);}
++  case 94:
++#line 352 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2114 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 87:
++  case 95:
++#line 353 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2120 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 334 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_ANY|CONST_DEFINED_BY);
+-                                        _asn1_set_down((yyval.node),_asn1_add_node(TYPE_CONSTANT));
+-	                                _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[(4) - (4)].str));}
++  case 96:
++#line 354 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2126 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 88:
++  case 97:
++#line 355 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_NULL);}
++#line 2132 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 339 "ASN1.y"
+-    {(yyval.node)=_asn1_set_name((yyvsp[(3) - (3)].node),(yyvsp[(1) - (3)].str));}
++  case 98:
++#line 358 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2138 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 89:
++  case 99:
++#line 359 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_mod_type((yyvsp[0].node),CONST_TAG);
++                                               _asn1_set_right((yyvsp[-1].node),_asn1_get_down((yyval.node)));
++                                               _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2146 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 343 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN);
+-                         _asn1_set_name((yyval.node),(yyvsp[(1) - (7)].str));
+-                         _asn1_set_down((yyval.node),(yyvsp[(6) - (7)].node));}
++  case 100:
++#line 364 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2152 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 90:
++  case 101:
++#line 365 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_DEFAULT);
++                                                       _asn1_set_right((yyvsp[0].node),_asn1_get_down((yyval.node)));
++						       _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2160 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 347 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
+-                         _asn1_set_name((yyval.node),(yyvsp[(1) - (6)].str));
+-                         _asn1_set_value((yyval.node),(yyvsp[(2) - (6)].str),strlen((yyvsp[(2) - (6)].str))+1);
+-                         _asn1_set_down((yyval.node),(yyvsp[(5) - (6)].node));}
++  case 102:
++#line 368 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_mod_type((yyvsp[-1].node),CONST_OPTION);}
++#line 2166 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 91:
++  case 103:
++#line 371 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_set_name((yyvsp[0].node),(yyvsp[-1].str));}
++#line 2172 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 352 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_INTEGER|CONST_ASSIGN);
+-                         _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));
+-                         _asn1_set_value((yyval.node),(yyvsp[(4) - (4)].str),strlen((yyvsp[(4) - (4)].str))+1);}
++  case 104:
++#line 374 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2178 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 92:
++  case 105:
++#line 375 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[-2].node);
++                                                _asn1_set_right(_asn1_get_last_right((yyvsp[-2].node)),(yyvsp[0].node));}
++#line 2185 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 357 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++  case 106:
++#line 379 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SEQUENCE);
++                                              _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2192 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 93:
++  case 107:
++#line 381 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SEQUENCE_OF);
++                                              _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2199 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 358 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++  case 108:
++#line 383 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SEQUENCE_OF|CONST_SIZE);
++                                            _asn1_set_right((yyvsp[-2].node),(yyvsp[0].node));
++                                            _asn1_set_down((yyval.node),(yyvsp[-2].node));}
++#line 2207 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 94:
++  case 109:
++#line 388 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SET);
++                                     _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2214 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 361 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (1)].node);}
++  case 110:
++#line 390 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SET_OF);
++                                     _asn1_set_down((yyval.node),(yyvsp[0].node));}
++#line 2221 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 95:
++  case 111:
++#line 392 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_SET_OF|CONST_SIZE);
++                                       _asn1_set_right((yyvsp[-2].node),(yyvsp[0].node));
++                                       _asn1_set_down((yyval.node),(yyvsp[-2].node));}
++#line 2229 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 362 "ASN1.y"
+-    {(yyval.node)=(yyvsp[(1) - (2)].node);
+-                                                          _asn1_set_right(_asn1_get_last_right((yyvsp[(1) - (2)].node)),(yyvsp[(2) - (2)].node));}
++  case 112:
++#line 397 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_CHOICE);
++                                             _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2236 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 96:
++  case 113:
++#line 401 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_ANY);}
++#line 2242 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 366 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID);
+-                                                          _asn1_set_down((yyval.node),(yyvsp[(3) - (4)].node));
+-                                                          _asn1_set_name((yyval.node),(yyvsp[(1) - (4)].str));}
++  case 114:
++#line 402 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_ANY|CONST_DEFINED_BY);
++                                        _asn1_set_down((yyval.node),_asn1_add_static_node(TYPE_CONSTANT));
++	                                _asn1_set_name(_asn1_get_down((yyval.node)),(yyvsp[0].str));}
++#line 2250 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 97:
++  case 115:
++#line 407 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_set_name((yyvsp[0].node),(yyvsp[-2].str));}
++#line 2256 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 369 "ASN1.y"
+-    {(yyval.node)=_asn1_add_node(TYPE_OBJECT_ID);
+-                                                          _asn1_set_name((yyval.node),(yyvsp[(1) - (3)].str));}
++  case 116:
++#line 409 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_set_name((yyvsp[0].node), last_error_token);}
++#line 2262 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 98:
++  case 117:
++#line 413 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN);
++                         _asn1_set_name((yyval.node),(yyvsp[-6].str));
++                         _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2270 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 393 "ASN1.y"
+-    {(yyval.constant)=CONST_EXPLICIT;}
++  case 118:
++#line 417 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID|CONST_ASSIGN|CONST_1_PARAM);
++                         _asn1_set_name((yyval.node),(yyvsp[-5].str));
++                         _asn1_set_value((yyval.node),(yyvsp[-4].str),strlen((yyvsp[-4].str))+1);
++                         _asn1_set_down((yyval.node),(yyvsp[-1].node));}
++#line 2279 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
+-  case 99:
++  case 119:
++#line 422 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_INTEGER|CONST_ASSIGN);
++                         _asn1_set_name((yyval.node),(yyvsp[-3].str));
++                         _asn1_set_value((yyval.node),(yyvsp[0].str),strlen((yyvsp[0].str))+1);}
++#line 2287 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 394 "ASN1.y"
+-    {(yyval.constant)=CONST_IMPLICIT;}
++  case 120:
++#line 427 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2293 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 121:
++#line 428 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2299 "ASN1.c" /* yacc.c:1646  */
+     break;
+ 
++  case 122:
++#line 431 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[0].node);}
++#line 2305 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
++  case 123:
++#line 432 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=(yyvsp[-1].node);
++                                                          _asn1_set_right(_asn1_get_last_right((yyvsp[-1].node)),(yyvsp[0].node));}
++#line 2312 "ASN1.c" /* yacc.c:1646  */
++    break;
+ 
+-/* Line 1455 of yacc.c  */
+-#line 2371 "ASN1.c"
++  case 124:
++#line 436 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);
++                                                          _asn1_set_down((yyval.node),(yyvsp[-1].node));
++                                                          _asn1_set_name((yyval.node),(yyvsp[-3].str));}
++#line 2320 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 125:
++#line 439 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);
++                                                          _asn1_set_name((yyval.node),(yyvsp[-2].str));}
++#line 2327 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 126:
++#line 441 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.node)=_asn1_add_static_node(TYPE_OBJECT_ID);
++                                                          _asn1_set_name((yyval.node),(yyvsp[0].str));}
++#line 2334 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 127:
++#line 465 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.constant)=CONST_EXPLICIT;}
++#line 2340 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++  case 128:
++#line 466 "ASN1.y" /* yacc.c:1646  */
++    {(yyval.constant)=CONST_IMPLICIT;}
++#line 2346 "ASN1.c" /* yacc.c:1646  */
++    break;
++
++
++#line 2350 "ASN1.c" /* yacc.c:1646  */
+       default: break;
+     }
++  /* User semantic actions sometimes alter yychar, and that requires
++     that yytoken be updated with the new translation.  We take the
++     approach of translating immediately before every use of yytoken.
++     One alternative is translating here after every semantic action,
++     but that translation would be missed if the semantic action invokes
++     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
++     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
++     incorrect destructor might then be invoked immediately.  In the
++     case of YYERROR or YYBACKUP, subsequent parser actions might lead
++     to an incorrect destructor call or verbose syntax error message
++     before the lookahead is translated.  */
+   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ 
+   YYPOPSTACK (yylen);
+@@ -2378,7 +2369,7 @@
+ 
+   *++yyvsp = yyval;
+ 
+-  /* Now `shift' the result of the reduction.  Determine what state
++  /* Now 'shift' the result of the reduction.  Determine what state
+      that goes to, based on the state we popped back to and the rule
+      number reduced by.  */
+ 
+@@ -2393,10 +2384,14 @@
+   goto yynewstate;
+ 
+ 
+-/*------------------------------------.
+-| yyerrlab -- here on detecting error |
+-`------------------------------------*/
++/*--------------------------------------.
++| yyerrlab -- here on detecting error.  |
++`--------------------------------------*/
+ yyerrlab:
++  /* Make sure we have latest lookahead translation.  See comments at
++     user semantic actions for why this is necessary.  */
++  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
++
+   /* If not already recovering from an error, report this error.  */
+   if (!yyerrstatus)
+     {
+@@ -2404,37 +2399,36 @@
+ #if ! YYERROR_VERBOSE
+       yyerror (YY_("syntax error"));
+ #else
++# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
++                                        yyssp, yytoken)
+       {
+-	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+-	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+-	  {
+-	    YYSIZE_T yyalloc = 2 * yysize;
+-	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+-	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+-	    if (yymsg != yymsgbuf)
+-	      YYSTACK_FREE (yymsg);
+-	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+-	    if (yymsg)
+-	      yymsg_alloc = yyalloc;
+-	    else
+-	      {
+-		yymsg = yymsgbuf;
+-		yymsg_alloc = sizeof yymsgbuf;
+-	      }
+-	  }
+-
+-	if (0 < yysize && yysize <= yymsg_alloc)
+-	  {
+-	    (void) yysyntax_error (yymsg, yystate, yychar);
+-	    yyerror (yymsg);
+-	  }
+-	else
+-	  {
+-	    yyerror (YY_("syntax error"));
+-	    if (yysize != 0)
+-	      goto yyexhaustedlab;
+-	  }
++        char const *yymsgp = YY_("syntax error");
++        int yysyntax_error_status;
++        yysyntax_error_status = YYSYNTAX_ERROR;
++        if (yysyntax_error_status == 0)
++          yymsgp = yymsg;
++        else if (yysyntax_error_status == 1)
++          {
++            if (yymsg != yymsgbuf)
++              YYSTACK_FREE (yymsg);
++            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
++            if (!yymsg)
++              {
++                yymsg = yymsgbuf;
++                yymsg_alloc = sizeof yymsgbuf;
++                yysyntax_error_status = 2;
++              }
++            else
++              {
++                yysyntax_error_status = YYSYNTAX_ERROR;
++                yymsgp = yymsg;
++              }
++          }
++        yyerror (yymsgp);
++        if (yysyntax_error_status == 2)
++          goto yyexhaustedlab;
+       }
++# undef YYSYNTAX_ERROR
+ #endif
+     }
+ 
+@@ -2443,20 +2437,20 @@
+   if (yyerrstatus == 3)
+     {
+       /* If just tried and failed to reuse lookahead token after an
+-	 error, discard it.  */
++         error, discard it.  */
+ 
+       if (yychar <= YYEOF)
+-	{
+-	  /* Return failure if at end of input.  */
+-	  if (yychar == YYEOF)
+-	    YYABORT;
+-	}
++        {
++          /* Return failure if at end of input.  */
++          if (yychar == YYEOF)
++            YYABORT;
++        }
+       else
+-	{
+-	  yydestruct ("Error: discarding",
+-		      yytoken, &yylval);
+-	  yychar = YYEMPTY;
+-	}
++        {
++          yydestruct ("Error: discarding",
++                      yytoken, &yylval);
++          yychar = YYEMPTY;
++        }
+     }
+ 
+   /* Else will try to reuse lookahead token after shifting the error
+@@ -2475,7 +2469,7 @@
+   if (/*CONSTCOND*/ 0)
+      goto yyerrorlab;
+ 
+-  /* Do not reclaim the symbols of the rule which action triggered
++  /* Do not reclaim the symbols of the rule whose action triggered
+      this YYERROR.  */
+   YYPOPSTACK (yylen);
+   yylen = 0;
+@@ -2488,35 +2482,37 @@
+ | yyerrlab1 -- common code for both syntax error and YYERROR.  |
+ `-------------------------------------------------------------*/
+ yyerrlab1:
+-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
++  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+ 
+   for (;;)
+     {
+       yyn = yypact[yystate];
+-      if (yyn != YYPACT_NINF)
+-	{
+-	  yyn += YYTERROR;
+-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+-	    {
+-	      yyn = yytable[yyn];
+-	      if (0 < yyn)
+-		break;
+-	    }
+-	}
++      if (!yypact_value_is_default (yyn))
++        {
++          yyn += YYTERROR;
++          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
++            {
++              yyn = yytable[yyn];
++              if (0 < yyn)
++                break;
++            }
++        }
+ 
+       /* Pop the current state because it cannot handle the error token.  */
+       if (yyssp == yyss)
+-	YYABORT;
++        YYABORT;
+ 
+ 
+       yydestruct ("Error: popping",
+-		  yystos[yystate], yyvsp);
++                  yystos[yystate], yyvsp);
+       YYPOPSTACK (1);
+       yystate = *yyssp;
+       YY_STACK_PRINT (yyss, yyssp);
+     }
+ 
++  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+   *++yyvsp = yylval;
++  YY_IGNORE_MAYBE_UNINITIALIZED_END
+ 
+ 
+   /* Shift the error token.  */
+@@ -2540,7 +2536,7 @@
+   yyresult = 1;
+   goto yyreturn;
+ 
+-#if !defined(yyoverflow) || YYERROR_VERBOSE
++#if !defined yyoverflow || YYERROR_VERBOSE
+ /*-------------------------------------------------.
+ | yyexhaustedlab -- memory exhaustion comes here.  |
+ `-------------------------------------------------*/
+@@ -2552,16 +2548,21 @@
+ 
+ yyreturn:
+   if (yychar != YYEMPTY)
+-     yydestruct ("Cleanup: discarding lookahead",
+-		 yytoken, &yylval);
+-  /* Do not reclaim the symbols of the rule which action triggered
++    {
++      /* Make sure we have latest lookahead translation.  See comments at
++         user semantic actions for why this is necessary.  */
++      yytoken = YYTRANSLATE (yychar);
++      yydestruct ("Cleanup: discarding lookahead",
++                  yytoken, &yylval);
++    }
++  /* Do not reclaim the symbols of the rule whose action triggered
+      this YYABORT or YYACCEPT.  */
+   YYPOPSTACK (yylen);
+   YY_STACK_PRINT (yyss, yyssp);
+   while (yyssp != yyss)
+     {
+       yydestruct ("Cleanup: popping",
+-		  yystos[*yyssp], yyvsp);
++                  yystos[*yyssp], yyvsp);
+       YYPOPSTACK (1);
+     }
+ #ifndef yyoverflow
+@@ -2572,34 +2573,33 @@
+   if (yymsg != yymsgbuf)
+     YYSTACK_FREE (yymsg);
+ #endif
+-  /* Make sure YYID is used.  */
+-  return YYID (yyresult);
++  return yyresult;
+ }
+-
+-
+-
+-/* Line 1675 of yacc.c  */
+-#line 398 "ASN1.y"
++#line 470 "ASN1.y" /* yacc.c:1906  */
+ 
+ 
+ 
+ 
+ static const char *key_word[] = {
+-  "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING"
+-  ,"SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL"
+-  ,"DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER"
+-  ,"BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED"
+-  ,"SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS"
+-  ,"BEGIN","END","UTCTime","GeneralizedTime"
+-  ,"GeneralString","FROM","IMPORTS","NULL","ENUMERATED"};
++  "::=","OPTIONAL","INTEGER","SIZE","OCTET","STRING",
++  "SEQUENCE","BIT","UNIVERSAL","PRIVATE","OPTIONAL",
++  "DEFAULT","CHOICE","OF","OBJECT","IDENTIFIER",
++  "BOOLEAN","TRUE","FALSE","APPLICATION","ANY","DEFINED",
++  "SET","BY","EXPLICIT","IMPLICIT","DEFINITIONS","TAGS",
++  "BEGIN","END","UTCTime","GeneralizedTime",
++  "GeneralString","FROM","IMPORTS","NULL","ENUMERATED",
++  "NumericString", "IA5String", "TeletexString", "PrintableString",
++  "UniversalString", "BMPString", "UTF8String", "VisibleString"};
++
+ static const int key_word_token[] = {
+-  ASSIG,OPTIONAL,INTEGER,SIZE,OCTET,STRING
+-  ,SEQUENCE,BIT,UNIVERSAL,PRIVATE,OPTIONAL
+-  ,DEFAULT,CHOICE,OF,OBJECT,STR_IDENTIFIER
+-  ,BOOLEAN,ASN1_TRUE,ASN1_FALSE,APPLICATION,ANY,DEFINED
+-  ,SET,BY,EXPLICIT,IMPLICIT,DEFINITIONS,TAGS
+-  ,BEGIN,END,UTCTime,GeneralizedTime
+-  ,GeneralString,FROM,IMPORTS,TOKEN_NULL,ENUMERATED};
++  ASSIG, OPTIONAL, INTEGER, SIZE, OCTET, STRING, SEQUENCE, BIT, UNIVERSAL,
++      PRIVATE, OPTIONAL, DEFAULT, CHOICE, OF, OBJECT, STR_IDENTIFIER,
++      BOOLEAN, ASN1_TRUE, ASN1_FALSE, APPLICATION, ANY, DEFINED, SET, BY,
++      EXPLICIT, IMPLICIT, DEFINITIONS, TAGS, BEGIN, END, UTCTime,
++      GeneralizedTime, GeneralString, FROM, IMPORTS, TOKEN_NULL,
++      ENUMERATED, NumericString, IA5String, TeletexString, PrintableString,
++      UniversalString, BMPString, UTF8String, VisibleString
++};
+ 
+ /*************************************************************/
+ /*  Function: _asn1_yylex                                    */
+@@ -2608,83 +2608,98 @@
+ /*    Token identifier or ASCII code or 0(zero: End Of File) */
+ /*************************************************************/
+ static int
+-_asn1_yylex()
++_asn1_yylex ()
+ {
+-  int c,counter=0,k,lastc;
+-  char string[ASN1_MAX_NAME_SIZE+1]; /* will contain the next token */
++  int c, counter = 0, k, lastc;
++  char string[ASN1_MAX_NAME_SIZE + 1];  /* will contain the next token */
+   size_t i;
+ 
+-  while(1)
++  while (1)
+     {
+-    while((c=fgetc(file_asn1))==' ' || c=='\t' || c=='\n')
+-      if(c=='\n') lineNumber++;
+-
+-    if(c==EOF){
+-      strcpy(lastToken,"End Of File");
+-      return 0;
+-    }
+-
+-    if(c=='(' || c==')' || c=='[' || c==']' ||
+-       c=='{' || c=='}' || c==',' || c=='.' ||
+-       c=='+' || c=='|'){
+-      lastToken[0]=c;lastToken[1]=0;
+-      return c;
+-    }
+-    if(c=='-'){  /* Maybe the first '-' of a comment */
+-      if((c=fgetc(file_asn1))!='-'){
+-	ungetc(c,file_asn1);
+-	lastToken[0]='-';lastToken[1]=0;
+-	return '-';
+-      }
+-      else{ /* Comments */
+-	lastc=0;
+-	counter=0;
+-	/* A comment finishes at the next double hypen or the end of line */
+-	while((c=fgetc(file_asn1))!=EOF && c!='\n' &&
+-	      (lastc!='-' || (lastc=='-' && c!='-')))
+-	  lastc=c;
+-	if(c==EOF){
+-	  strcpy(lastToken,"End Of File");
+-	  return 0;
+-	}
+-	else{
+-	  if(c=='\n') lineNumber++;
+-	  continue; /* next char, please! (repeat the search) */
+-	}
+-      }
+-    }
+-    string[counter++]=c;
+-    /* Till the end of the token */
+-    while(!((c=fgetc(file_asn1))==EOF || c==' '|| c=='\t' || c=='\n' ||
+-	     c=='(' || c==')' || c=='[' || c==']' ||
+-	     c=='{' || c=='}' || c==',' || c=='.'))
+-      {
+-	if(counter>=ASN1_MAX_NAME_SIZE){
+-	  result_parse=ASN1_NAME_TOO_LONG;
+-	  return 0;
+-	}
+-	string[counter++]=c;
+-      }
+-    ungetc(c,file_asn1);
+-    string[counter]=0;
+-    strcpy(lastToken,string);
+-
+-    /* Is STRING a number? */
+-    for(k=0;k<counter;k++)
+-      if(!isdigit(string[k])) break;
+-    if(k>=counter)
+-      {
+-      strcpy(yylval.str,string);
+-      return NUM; /* return the number */
+-      }
+-
+-    /* Is STRING a keyword? */
+-    for(i=0;i<(sizeof(key_word)/sizeof(char*));i++)
+-      if(!strcmp(string,key_word[i])) return key_word_token[i];
+-
+-    /* STRING is an IDENTIFIER */
+-    strcpy(yylval.str,string);
+-    return IDENTIFIER;
++      while ((c = fgetc (file_asn1)) == ' ' || c == '\t' || c == '\n')
++        if (c == '\n')
++          line_number++;
++
++      if (c == EOF)
++        {
++          snprintf (last_token, sizeof(last_token), "End Of File");
++          return 0;
++        }
++
++      if (c == '(' || c == ')' || c == '[' || c == ']' ||
++          c == '{' || c == '}' || c == ',' || c == '.' ||
++          c == '+' || c == '|')
++        {
++          last_token[0] = c;
++          last_token[1] = 0;
++          return c;
++        }
++      if (c == '-')
++        {                       /* Maybe the first '-' of a comment */
++          if ((c = fgetc (file_asn1)) != '-')
++            {
++              ungetc (c, file_asn1);
++              last_token[0] = '-';
++              last_token[1] = 0;
++              return '-';
++            }
++          else
++            {                   /* Comments */
++              lastc = 0;
++              counter = 0;
++              /* A comment finishes at the next double hypen or the end of line */
++              while ((c = fgetc (file_asn1)) != EOF && c != '\n' &&
++                     (lastc != '-' || (lastc == '-' && c != '-')))
++                lastc = c;
++              if (c == EOF)
++                {
++                  snprintf (last_token, sizeof(last_token), "End Of File");
++                  return 0;
++                }
++              else
++                {
++                  if (c == '\n')
++                    line_number++;
++                  continue;     /* next char, please! (repeat the search) */
++                }
++            }
++        }
++      string[counter++] = c;
++      /* Till the end of the token */
++      while (!
++             ((c = fgetc (file_asn1)) == EOF || c == ' ' || c == '\t'
++              || c == '\n' || c == '(' || c == ')' || c == '[' || c == ']'
++              || c == '{' || c == '}' || c == ',' || c == '.'))
++        {
++          if (counter >= ASN1_MAX_NAME_SIZE)
++            {
++              result_parse = ASN1_NAME_TOO_LONG;
++              return 0;
++            }
++          string[counter++] = c;
++        }
++      ungetc (c, file_asn1);
++      string[counter] = 0;
++      snprintf (last_token, sizeof(last_token), "%s", string);
++
++      /* Is STRING a number? */
++      for (k = 0; k < counter; k++)
++        if (!isdigit (string[k]))
++          break;
++      if (k >= counter)
++        {
++          snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++          return NUM;           /* return the number */
++        }
++
++      /* Is STRING a keyword? */
++      for (i = 0; i < (sizeof (key_word) / sizeof (char *)); i++)
++        if (!strcmp (string, key_word[i]))
++          return key_word_token[i];
++
++      /* STRING is an IDENTIFIER */
++      snprintf (yylval.str, sizeof(yylval.str), "%s", string);
++      return IDENTIFIER;
+     }
+ }
+ 
+@@ -2694,136 +2709,121 @@
+ /*    error.                                                 */
+ /*  Parameters:                                              */
+ /*    error : error to describe.                             */
+-/*    errorDescription: string that will contain the         */
++/*    error_desc: string that will contain the         */
+ /*                      description.                         */
+ /*************************************************************/
+ static void
+-_asn1_create_errorDescription(int error,char *errorDescription)
++_asn1_create_errorDescription (int error, char *error_desc)
+ {
+-  switch(error){
+-  case ASN1_SUCCESS: case ASN1_FILE_NOT_FOUND:
+-    if (errorDescription!=NULL) errorDescription[0]=0;
+-    break;
+-  case ASN1_SYNTAX_ERROR:
+-    if (errorDescription!=NULL) {
+-	strcpy(errorDescription,fileName);
+-	strcat(errorDescription,":");
+-	_asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+-	strcat(errorDescription,": parse error near '");
+-	strcat(errorDescription,lastToken);
+-	strcat(errorDescription,"'");
+-    }
+-    break;
+-  case ASN1_NAME_TOO_LONG:
+-    if (errorDescription!=NULL) {
+-       strcpy(errorDescription,fileName);
+-       strcat(errorDescription,":");
+-       _asn1_ltostr(lineNumber,errorDescription+strlen(fileName)+1);
+-       strcat(errorDescription,": name too long (more than ");
+-       _asn1_ltostr(ASN1_MAX_NAME_SIZE,errorDescription+strlen(errorDescription));
+-       strcat(errorDescription," characters)");
+-    }
+-    break;
+-  case ASN1_IDENTIFIER_NOT_FOUND:
+-    if (errorDescription!=NULL) {
+-       strcpy(errorDescription,fileName);
+-       strcat(errorDescription,":");
+-       strcat(errorDescription,": identifier '");
+-       strcat(errorDescription,_asn1_identifierMissing);
+-       strcat(errorDescription,"' not found");
++  if (error_desc == NULL)
++    return;
++
++
++  switch (error)
++    {
++    case ASN1_FILE_NOT_FOUND:
++      snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s file was not found", file_name);
++      break;
++    case ASN1_SYNTAX_ERROR:
++      snprintf(error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE, "%s", last_error);
++      break;
++    case ASN1_NAME_TOO_LONG:
++      snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++                "%s:%u: name too long (more than %u characters)", file_name,
++                line_number, ASN1_MAX_NAME_SIZE);
++      break;
++    case ASN1_IDENTIFIER_NOT_FOUND:
++      snprintf (error_desc, ASN1_MAX_ERROR_DESCRIPTION_SIZE,
++                "%s:: identifier '%s' not found", file_name,
++                _asn1_identifierMissing);
++      break;
++    default:
++      error_desc[0] = 0;
++      break;
+     }
+-    break;
+-  default:
+-    if (errorDescription!=NULL) errorDescription[0]=0;
+-    break;
+-  }
+ 
+ }
+ 
+ /**
+  * asn1_parser2tree:
+- * @file_name: specify the path and the name of file that contains
++ * @file: specify the path and the name of file that contains
+  *   ASN.1 declarations.
+  * @definitions: return the pointer to the structure created from
+- *   "file_name" ASN.1 declarations.
+- * @errorDescription: return the error description or an empty
++ *   "file" ASN.1 declarations.
++ * @error_desc: return the error description or an empty
+  * string if success.
+  *
+  * Function used to start the parse algorithm.  Creates the structures
+- * needed to manage the definitions included in @file_name file.
+- *
+- * Returns:
++ * needed to manage the definitions included in @file file.
+  *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- * is known.
+- *
+- * %ASN1_ELEMENT_NOT_EMPTY: @definitions not %ASN1_TYPE_EMPTY.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @file_name.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- * is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- * than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ *   identifier is known, %ASN1_ELEMENT_NOT_EMPTY if @definitions not
++ *   %NULL, %ASN1_FILE_NOT_FOUND if an error occured while
++ *   opening @file, %ASN1_SYNTAX_ERROR if the syntax is not
++ *   correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is an
++ *   identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ *   file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ *   characters.
+  **/
+-asn1_retCode
+-asn1_parser2tree(const char *file_name, ASN1_TYPE *definitions,
+-		 char *errorDescription){
++int
++asn1_parser2tree (const char *file, ASN1_TYPE * definitions,
++                  char *error_desc)
++{
+ 
+-  p_tree=ASN1_TYPE_EMPTY;
++  p_tree = NULL;
+ 
+-  if(*definitions != ASN1_TYPE_EMPTY)
++  if (*definitions != NULL)
+     return ASN1_ELEMENT_NOT_EMPTY;
+ 
+-  *definitions=ASN1_TYPE_EMPTY;
++  *definitions = NULL;
+ 
+-  fileName = file_name;
++  file_name = file;
+ 
+   /* open the file to parse */
+-  file_asn1=fopen(file_name,"r");
++  file_asn1 = fopen (file, "r");
+ 
+-  if(file_asn1==NULL){
+-    result_parse=ASN1_FILE_NOT_FOUND;
+-  }
+-  else{
+-    result_parse=ASN1_SUCCESS;
+-
+-    lineNumber=1;
+-    yyparse();
++  if (file_asn1 == NULL)
++    {
++      result_parse = ASN1_FILE_NOT_FOUND;
++    }
++  else
++    {
++      result_parse = ASN1_SUCCESS;
+ 
+-    fclose(file_asn1);
++      line_number = 1;
++      yyparse ();
+ 
+-    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+-      /* set IMPLICIT or EXPLICIT property */
+-      _asn1_set_default_tag(p_tree);
+-      /* set CONST_SET and CONST_NOT_USED */
+-      _asn1_type_set_config(p_tree);
+-      /* check the identifier definitions */
+-      result_parse=_asn1_check_identifier(p_tree);
+-      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+-	/* Delete the list and keep the ASN1 structure */
+-	_asn1_delete_list();
+-	/* Convert into DER coding the value assign to INTEGER constants */
+-	_asn1_change_integer_value(p_tree);
+-	/* Expand the IDs of OBJECT IDENTIFIER constants */
+-	_asn1_expand_object_id(p_tree);
++      fclose (file_asn1);
+ 
+-	*definitions=p_tree;
+-      }
+-      else /* some identifiers not defined */
+-	/* Delete the list and the ASN1 structure */
+-	_asn1_delete_list_and_nodes();
++      if (result_parse == ASN1_SUCCESS)
++        {                       /* syntax OK */
++          /* set IMPLICIT or EXPLICIT property */
++          _asn1_set_default_tag (p_tree);
++          /* set CONST_SET and CONST_NOT_USED */
++          _asn1_type_set_config (p_tree);
++          /* check the identifier definitions */
++          result_parse = _asn1_check_identifier (p_tree);
++          if (result_parse == ASN1_SUCCESS)
++            {                   /* all identifier defined */
++              /* Delete the list and keep the ASN1 structure */
++              _asn1_delete_list ();
++              /* Convert into DER coding the value assign to INTEGER constants */
++              _asn1_change_integer_value (p_tree);
++              /* Expand the IDs of OBJECT IDENTIFIER constants */
++              _asn1_expand_object_id (p_tree);
++
++              *definitions = p_tree;
++            }
++          else                  /* some identifiers not defined */
++            /* Delete the list and the ASN1 structure */
++            _asn1_delete_list_and_nodes ();
++        }
++      else                      /* syntax error */
++        /* Delete the list and the ASN1 structure */
++        _asn1_delete_list_and_nodes ();
+     }
+-    else  /* syntax error */
+-      /* Delete the list and the ASN1 structure */
+-      _asn1_delete_list_and_nodes();
+-  }
+ 
+-  if (errorDescription!=NULL)
+-	_asn1_create_errorDescription(result_parse,errorDescription);
++  _asn1_create_errorDescription (result_parse, error_desc);
+ 
+   return result_parse;
+ }
+@@ -2835,7 +2835,7 @@
+  * @outputFileName: specify the path and the name of file that will
+  *   contain the C vector definition.
+  * @vectorName: specify the name of the C vector.
+- * @errorDescription : return the error description or an empty
++ * @error_desc: return the error description or an empty
+  *   string if success.
+  *
+  * Function that generates a C structure from an ASN1 file.  Creates a
+@@ -2845,113 +2845,118 @@
+  * "/aa/bb/xx_asn1_tab.c".  If @vectorName is %NULL the vector name
+  * will be "xx_asn1_tab".
+  *
+- * Returns:
+- *
+- * %ASN1_SUCCESS: The file has a correct syntax and every identifier
+- *   is known.
+- *
+- * %ASN1_FILE_NOT_FOUND: An error occured while opening @inputFileName.
+- *
+- * %ASN1_SYNTAX_ERROR: The syntax is not correct.
+- *
+- * %ASN1_IDENTIFIER_NOT_FOUND: In the file there is an identifier that
+- *   is not defined.
+- *
+- * %ASN1_NAME_TOO_LONG: In the file there is an identifier whith more
+- *   than %ASN1_MAX_NAME_SIZE characters.
++ * Returns: %ASN1_SUCCESS if the file has a correct syntax and every
++ *   identifier is known, %ASN1_FILE_NOT_FOUND if an error occured
++ *   while opening @inputFileName, %ASN1_SYNTAX_ERROR if the syntax is
++ *   not correct, %ASN1_IDENTIFIER_NOT_FOUND if in the file there is
++ *   an identifier that is not defined, %ASN1_NAME_TOO_LONG if in the
++ *   file there is an identifier whith more than %ASN1_MAX_NAME_SIZE
++ *   characters.
+  **/
+-int asn1_parser2array(const char *inputFileName,const char *outputFileName,
+-		      const char *vectorName,char *errorDescription){
+-  char *file_out_name=NULL;
+-  char *vector_name=NULL;
+-  const char *char_p,*slash_p,*dot_p;
++int
++asn1_parser2array (const char *inputFileName, const char *outputFileName,
++                   const char *vectorName, char *error_desc)
++{
++  char *file_out_name = NULL;
++  char *vector_name = NULL;
++  const char *char_p, *slash_p, *dot_p;
+ 
+-  p_tree=NULL;
++  p_tree = NULL;
+ 
+-  fileName = inputFileName;
++  file_name = inputFileName;
+ 
+   /* open the file to parse */
+-  file_asn1=fopen(inputFileName,"r");
++  file_asn1 = fopen (inputFileName, "r");
++
++  if (file_asn1 == NULL)
++    result_parse = ASN1_FILE_NOT_FOUND;
++  else
++    {
++      result_parse = ASN1_SUCCESS;
+ 
+-  if(file_asn1==NULL)
+-    result_parse=ASN1_FILE_NOT_FOUND;
+-  else{
+-    result_parse=ASN1_SUCCESS;
+-
+-    lineNumber=1;
+-    yyparse();
+-
+-    fclose(file_asn1);
+-
+-    if(result_parse==ASN1_SUCCESS){ /* syntax OK */
+-      /* set IMPLICIT or EXPLICIT property */
+-      _asn1_set_default_tag(p_tree);
+-      /* set CONST_SET and CONST_NOT_USED */
+-      _asn1_type_set_config(p_tree);
+-      /* check the identifier definitions */
+-      result_parse=_asn1_check_identifier(p_tree);
+-
+-      if(result_parse==ASN1_SUCCESS){ /* all identifier defined */
+-
+-	/* searching the last '/' and '.' in inputFileName */
+-	char_p=inputFileName;
+-	slash_p=inputFileName;
+-	while((char_p=strchr(char_p,'/'))){
+-	  char_p++;
+-	  slash_p=char_p;
+-	}
+-
+-	char_p=slash_p;
+-	dot_p=inputFileName+strlen(inputFileName);
+-
+-	while((char_p=strchr(char_p,'.'))){
+-	  dot_p=char_p;
+-	  char_p++;
+-	}
+-
+-	if(outputFileName == NULL){
+-	  /* file_out_name = inputFileName + _asn1_tab.c */
+-	  file_out_name=(char *)malloc(dot_p-inputFileName+1+
+-				       strlen("_asn1_tab.c"));
+-	  memcpy(file_out_name,inputFileName,dot_p-inputFileName);
+-	  file_out_name[dot_p-inputFileName]=0;
+-	  strcat(file_out_name,"_asn1_tab.c");
+-	}
+-	else{
+-	  /* file_out_name = inputFileName */
+-	  file_out_name=(char *)malloc(strlen(outputFileName)+1);
+-	  strcpy(file_out_name,outputFileName);
+-	}
+-
+-	if(vectorName == NULL){
+-	  /* vector_name = file name + _asn1_tab */
+-	  vector_name=(char *)malloc(dot_p-slash_p+1+
+-				     strlen("_asn1_tab"));
+-	  memcpy(vector_name,slash_p,dot_p-slash_p);
+-	  vector_name[dot_p-slash_p]=0;
+-	  strcat(vector_name,"_asn1_tab");
+-	}
+-	else{
+-	  /* vector_name = vectorName */
+-	  vector_name=(char *)malloc(strlen(vectorName)+1);
+-	  strcpy(vector_name,vectorName);
+-	}
+-
+-	/* Save structure in a file */
+-	_asn1_create_static_structure(p_tree,
+-				      file_out_name,vector_name);
+-
+-	free(file_out_name);
+-	free(vector_name);
+-      } /* result == OK */
+-    }   /* result == OK */
+-
+-    /* Delete the list and the ASN1 structure */
+-    _asn1_delete_list_and_nodes();
+-  } /* inputFile exist */
++      line_number = 1;
++      yyparse ();
+ 
+-  if (errorDescription!=NULL)
+-	_asn1_create_errorDescription(result_parse,errorDescription);
++      fclose (file_asn1);
++
++      if (result_parse == ASN1_SUCCESS)
++        {                       /* syntax OK */
++          /* set IMPLICIT or EXPLICIT property */
++          _asn1_set_default_tag (p_tree);
++          /* set CONST_SET and CONST_NOT_USED */
++          _asn1_type_set_config (p_tree);
++          /* check the identifier definitions */
++          result_parse = _asn1_check_identifier (p_tree);
++
++          if (result_parse == ASN1_SUCCESS)
++            {                   /* all identifier defined */
++
++              /* searching the last '/' and '.' in inputFileName */
++              char_p = inputFileName;
++              slash_p = inputFileName;
++              while ((char_p = strchr (char_p, '/')))
++                {
++                  char_p++;
++                  slash_p = char_p;
++                }
++
++              char_p = slash_p;
++              dot_p = inputFileName + strlen (inputFileName);
++
++              while ((char_p = strchr (char_p, '.')))
++                {
++                  dot_p = char_p;
++                  char_p++;
++                }
++
++              if (outputFileName == NULL)
++                {
++                  /* file_out_name = inputFileName + _asn1_tab.c */
++                  file_out_name = malloc (dot_p - inputFileName + 1 +
++                                          strlen ("_asn1_tab.c"));
++                  memcpy (file_out_name, inputFileName,
++                          dot_p - inputFileName);
++                  file_out_name[dot_p - inputFileName] = 0;
++                  strcat (file_out_name, "_asn1_tab.c");
++                }
++              else
++                {
++                  /* file_out_name = inputFileName */
++                  file_out_name =
++                      (char *) malloc (strlen (outputFileName) + 1);
++                  strcpy (file_out_name, outputFileName);
++                }
++
++              if (vectorName == NULL)
++                {
++                  /* vector_name = file name + _asn1_tab */
++                  vector_name = malloc (dot_p - slash_p + 1 +
++                                        strlen ("_asn1_tab"));
++                  memcpy (vector_name, slash_p, dot_p - slash_p);
++                  vector_name[dot_p - slash_p] = 0;
++                  strcat (vector_name, "_asn1_tab");
++                }
++              else
++                {
++                  /* vector_name = vectorName */
++                  vector_name = (char *) malloc (strlen (vectorName) + 1);
++                  strcpy (vector_name, vectorName);
++                }
++
++              /* Save structure in a file */
++              _asn1_create_static_structure (p_tree,
++                                             file_out_name, vector_name);
++
++              free (file_out_name);
++              free (vector_name);
++            }                   /* result == OK */
++        }                       /* result == OK */
++
++      /* Delete the list and the ASN1 structure */
++      _asn1_delete_list_and_nodes ();
++    }                           /* inputFile exist */
++
++  _asn1_create_errorDescription (result_parse, error_desc);
+ 
+   return result_parse;
+ }
+@@ -2964,18 +2969,35 @@
+ /*  Return: int                                              */
+ /*                                                           */
+ /*************************************************************/
+-static int _asn1_yyerror (const char *s)
++static void
++_asn1_yyerror (const char *s)
+ {
+   /* Sends the error description to the std_out */
+ 
+-#if 0
+-  printf("_asn1_yyerror:%s:%ld: %s (Last Token:'%s')\n",fileName,
+-	 lineNumber,s,lastToken);
+-#endif
++  if (strcmp (last_token, "VisibleString") == 0 ||
++      strcmp (last_token, "PrintableString") == 0 ||
++      strcmp (last_token, "UniversalString") == 0 ||
++      strcmp (last_token, "IA5String") == 0 ||
++      strcmp (last_token, "UTF8String") == 0 ||
++      strcmp (last_token, "NumericString") == 0 ||
++      strcmp (last_token, "TeletexString") == 0 ||
++      strcmp (last_token, "BMPString") == 0)
++    {
++      snprintf (last_error_token, sizeof(last_error_token),
++                "%s", last_token);
++      fprintf(stderr, "%s:%u: Warning: %s is a built-in ASN.1 type.\n",
++               file_name, line_number, last_token);
++      return;
++    }
++  last_error_token[0] = 0;
+ 
+-  if(result_parse!=ASN1_NAME_TOO_LONG)
+-    result_parse=ASN1_SYNTAX_ERROR;
++  if (result_parse != ASN1_NAME_TOO_LONG)
++    {
++      snprintf (last_error, sizeof(last_error),
++                "%s:%u: Error: %s near '%s'", file_name,
++                line_number, s, last_token);
++      result_parse = ASN1_SYNTAX_ERROR;
++    }
+ 
+-  return 0;
++  return;
+ }
+-
+--- ORIGINAL/./lib/element.c	2015-07-14 18:28:22.914356512 -0700
++++ libtasn1-2.8/./lib/element.c	2015-07-14 18:45:02.664963151 -0700
+@@ -46,7 +46,7 @@
+ 
+   while (p != NULL)
+     {
+-      if (p->name != NULL)
++      if (p->name[0] != 0)
+ 	{
+ 	  _asn1_str_cpy (tmp_name, sizeof (tmp_name), name),
+ 	    _asn1_str_cpy (name, name_size, p->name);
+@@ -75,8 +75,8 @@
+ /*   len: number of significant byte of value_out.                */
+ /* Return: ASN1_MEM_ERROR or ASN1_SUCCESS                         */
+ /******************************************************************/
+-asn1_retCode
+-_asn1_convert_integer (const char *value, unsigned char *value_out,
++int
++_asn1_convert_integer (const unsigned char *value, unsigned char *value_out,
+ 		       int value_out_size, int *len)
+ {
+   char negative;
+@@ -84,7 +84,7 @@
+   long valtmp;
+   int k, k2;
+ 
+-  valtmp = strtol (value, NULL, 10);
++  valtmp = _asn1_strtol (value, NULL, 10);
+ 
+   for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++)
+     {
+@@ -114,10 +114,10 @@
+     return ASN1_MEM_ERROR;
+ 
+   if (value_out != NULL)
+-  {
+-    for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
+-    value_out[k2 - k] = val[k2];
+-  }
++    {
++      for (k2 = k; k2 < SIZEOF_UNSIGNED_LONG_INT; k2++)
++        value_out[k2 - k] = val[k2];
++    }
+ 
+ #if 0
+   printf ("_asn1_convert_integer: valueIn=%s, lenOut=%d", value, *len);
+@@ -134,7 +134,7 @@
+ _asn1_append_sequence_set (ASN1_TYPE node)
+ {
+   ASN1_TYPE p, p2;
+-  char temp[10];
++  char temp[LTOSTR_MAX_SIZE];
+   long n;
+ 
+   if (!node || !(node->down))
+@@ -149,7 +149,7 @@
+     p = p->right;
+   _asn1_set_right (p, p2);
+ 
+-  if (p->name == NULL)
++  if (p->name[0] == 0)
+     _asn1_str_cpy (temp, sizeof (temp), "?1");
+   else
+     {
+@@ -267,15 +267,11 @@
+  *           result=asn1_write_value(cert,
+  *           "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1);
+  *
+- * Returns:
+- *
+- *   %ASN1_SUCCESS: Set value OK.
+- *
+- *   %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
+- *
+- *   %ASN1_VALUE_NOT_VALID: VALUE has a wrong format.
++ * Returns: %ASN1_SUCCESS if the value was set,
++ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element, and
++ *   %ASN1_VALUE_NOT_VALID if @ivalue has a wrong format.
+  **/
+-asn1_retCode
++int
+ asn1_write_value (ASN1_TYPE node_root, const char *name,
+ 		  const void *ivalue, int len)
+ {
+@@ -284,6 +280,7 @@
+   int len2, k, k2, negative;
+   size_t i;
+   const unsigned char *value = ivalue;
++  unsigned int type;
+ 
+   node = asn1_find_node (node_root, name);
+   if (node == NULL)
+@@ -295,8 +292,9 @@
+       return ASN1_SUCCESS;
+     }
+ 
+-  if ((type_field (node->type) == TYPE_SEQUENCE_OF) && (value == NULL)
+-      && (len == 0))
++  type = type_field (node->type);
++
++  if ((type == TYPE_SEQUENCE_OF || type == TYPE_SET_OF) && (value == NULL) && (len == 0))
+     {
+       p = node->down;
+       while ((type_field (p->type) == TYPE_TAG)
+@@ -309,10 +307,16 @@
+       return ASN1_SUCCESS;
+     }
+ 
+-  switch (type_field (node->type))
++  /* Don't allow element deletion for other types */
++  if (value == NULL)
++    {
++      return ASN1_VALUE_NOT_VALID;
++    }
++
++  switch (type)
+     {
+     case TYPE_BOOLEAN:
+-      if (!strcmp (value, "TRUE"))
++      if (!_asn1_strcmp (value, "TRUE"))
+ 	{
+ 	  if (node->type & CONST_DEFAULT)
+ 	    {
+@@ -327,7 +331,7 @@
+ 	  else
+ 	    _asn1_set_value (node, "T", 1);
+ 	}
+-      else if (!strcmp (value, "FALSE"))
++      else if (!_asn1_strcmp (value, "FALSE"))
+ 	{
+ 	  if (node->type & CONST_DEFAULT)
+ 	    {
+@@ -351,8 +355,7 @@
+ 	{
+ 	  if ((isdigit (value[0])) || (value[0] == '-'))
+ 	    {
+-	      value_temp =
+-		(unsigned char *) _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++	      value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ 	      if (value_temp == NULL)
+ 		return ASN1_MEM_ALLOC_ERROR;
+ 
+@@ -368,11 +371,9 @@
+ 		{
+ 		  if (type_field (p->type) == TYPE_CONSTANT)
+ 		    {
+-		      if ((p->name) && (!strcmp (p->name, value)))
++		      if (!_asn1_strcmp (p->name, value))
+ 			{
+-			  value_temp =
+-			    (unsigned char *)
+-			    _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++			  value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ 			  if (value_temp == NULL)
+ 			    return ASN1_MEM_ALLOC_ERROR;
+ 
+@@ -391,13 +392,12 @@
+ 	}
+       else
+ 	{			/* len != 0 */
+-	  value_temp = (unsigned char *) _asn1_malloc (len);
++	  value_temp = malloc (len);
+ 	  if (value_temp == NULL)
+ 	    return ASN1_MEM_ALLOC_ERROR;
+ 	  memcpy (value_temp, value, len);
+ 	}
+ 
+-
+       if (value_temp[0] & 0x80)
+ 	negative = 1;
+       else
+@@ -405,7 +405,7 @@
+ 
+       if (negative && (type_field (node->type) == TYPE_ENUMERATED))
+ 	{
+-	  _asn1_free (value_temp);
++	  free (value_temp);
+ 	  return ASN1_VALUE_NOT_VALID;
+ 	}
+ 
+@@ -419,7 +419,7 @@
+ 	  (!negative && (value_temp[k] & 0x80)))
+ 	k--;
+ 
+-      _asn1_set_value_octet (node, value_temp + k, len - k);
++      _asn1_set_value_lv (node, value_temp + k, len - k);
+ 
+       if (node->type & CONST_DEFAULT)
+ 	{
+@@ -428,11 +428,10 @@
+ 	    p = p->right;
+ 	  if ((isdigit (p->value[0])) || (p->value[0] == '-'))
+ 	    {
+-	      default_temp =
+-		(unsigned char *) _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++	      default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ 	      if (default_temp == NULL)
+ 		{
+-		  _asn1_free (value_temp);
++		  free (value_temp);
+ 		  return ASN1_MEM_ALLOC_ERROR;
+ 		}
+ 
+@@ -443,7 +442,7 @@
+ 	    {			/* is an identifier like v1 */
+ 	      if (!(node->type & CONST_LIST))
+ 		{
+-		  _asn1_free (value_temp);
++		  free (value_temp);
+ 		  return ASN1_VALUE_NOT_VALID;
+ 		}
+ 	      p2 = node->down;
+@@ -451,14 +450,12 @@
+ 		{
+ 		  if (type_field (p2->type) == TYPE_CONSTANT)
+ 		    {
+-		      if ((p2->name) && (!strcmp (p2->name, p->value)))
++		      if (!_asn1_strcmp (p2->name, p->value))
+ 			{
+-			  default_temp =
+-			    (unsigned char *)
+-			    _asn1_malloc (SIZEOF_UNSIGNED_LONG_INT);
++			  default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT);
+ 			  if (default_temp == NULL)
+ 			    {
+-			      _asn1_free (value_temp);
++			      free (value_temp);
+ 			      return ASN1_MEM_ALLOC_ERROR;
+ 			    }
+ 
+@@ -473,7 +470,7 @@
+ 		}
+ 	      if (p2 == NULL)
+ 		{
+-		  _asn1_free (value_temp);
++		  free (value_temp);
+ 		  return ASN1_VALUE_NOT_VALID;
+ 		}
+ 	    }
+@@ -489,12 +486,12 @@
+ 	      if (k2 == len2)
+ 		_asn1_set_value (node, NULL, 0);
+ 	    }
+-	  _asn1_free (default_temp);
++	  free (default_temp);
+ 	}
+-      _asn1_free (value_temp);
++      free (value_temp);
+       break;
+     case TYPE_OBJECT_ID:
+-      for (i = 0; i < strlen (value); i++)
++      for (i = 0; i < _asn1_strlen (value); i++)
+ 	if ((!isdigit (value[i])) && (value[i] != '.') && (value[i] != '+'))
+ 	  return ASN1_VALUE_NOT_VALID;
+       if (node->type & CONST_DEFAULT)
+@@ -502,75 +499,78 @@
+ 	  p = node->down;
+ 	  while (type_field (p->type) != TYPE_DEFAULT)
+ 	    p = p->right;
+-	  if (!strcmp (value, p->value))
++	  if (!_asn1_strcmp (value, p->value))
+ 	    {
+ 	      _asn1_set_value (node, NULL, 0);
+ 	      break;
+ 	    }
+ 	}
+-      _asn1_set_value (node, value, strlen (value) + 1);
++      _asn1_set_value (node, value, _asn1_strlen (value) + 1);
+       break;
+-    case TYPE_TIME:
+-      if (node->type & CONST_UTC)
+-	{
+-	  if (strlen (value) < 11)
++    case TYPE_UTC_TIME:
++      {
++	len = _asn1_strlen (value);
++	if (len < 11)
++	  return ASN1_VALUE_NOT_VALID;
++	for (k = 0; k < 10; k++)
++	  if (!isdigit (value[k]))
+ 	    return ASN1_VALUE_NOT_VALID;
+-	  for (k = 0; k < 10; k++)
+-	    if (!isdigit (value[k]))
++	switch (len)
++	  {
++	  case 11:
++	    if (value[10] != 'Z')
+ 	      return ASN1_VALUE_NOT_VALID;
+-	  switch (strlen (value))
+-	    {
+-	    case 11:
+-	      if (value[10] != 'Z')
+-		return ASN1_VALUE_NOT_VALID;
+-	      break;
+-	    case 13:
+-	      if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
+-		  (value[12] != 'Z'))
+-		return ASN1_VALUE_NOT_VALID;
+-	      break;
+-	    case 15:
+-	      if ((value[10] != '+') && (value[10] != '-'))
+-		return ASN1_VALUE_NOT_VALID;
+-	      for (k = 11; k < 15; k++)
+-		if (!isdigit (value[k]))
+-		  return ASN1_VALUE_NOT_VALID;
+-	      break;
+-	    case 17:
+-	      if ((!isdigit (value[10])) || (!isdigit (value[11])))
++	    break;
++	  case 13:
++	    if ((!isdigit (value[10])) || (!isdigit (value[11])) ||
++		(value[12] != 'Z'))
++	      return ASN1_VALUE_NOT_VALID;
++	    break;
++	  case 15:
++	    if ((value[10] != '+') && (value[10] != '-'))
++	      return ASN1_VALUE_NOT_VALID;
++	    for (k = 11; k < 15; k++)
++	      if (!isdigit (value[k]))
+ 		return ASN1_VALUE_NOT_VALID;
+-	      if ((value[12] != '+') && (value[12] != '-'))
++	    break;
++	  case 17:
++	    if ((!isdigit (value[10])) || (!isdigit (value[11])))
++	      return ASN1_VALUE_NOT_VALID;
++	    if ((value[12] != '+') && (value[12] != '-'))
++	      return ASN1_VALUE_NOT_VALID;
++	    for (k = 13; k < 17; k++)
++	      if (!isdigit (value[k]))
+ 		return ASN1_VALUE_NOT_VALID;
+-	      for (k = 13; k < 17; k++)
+-		if (!isdigit (value[k]))
+-		  return ASN1_VALUE_NOT_VALID;
+-	      break;
+-	    default:
+-	      return ASN1_VALUE_NOT_FOUND;
+-	    }
+-	  _asn1_set_value (node, value, strlen (value) + 1);
+-	}
+-      else
+-	{			/* GENERALIZED TIME */
+-	  if (value)
+-	    _asn1_set_value (node, value, strlen (value) + 1);
+-	}
++	    break;
++	  default:
++	    return ASN1_VALUE_NOT_FOUND;
++	  }
++	_asn1_set_value (node, value, len);
++      }
++      break;
++    case TYPE_GENERALIZED_TIME:
++      len = _asn1_strlen (value);
++      _asn1_set_value (node, value, len);
+       break;
+     case TYPE_OCTET_STRING:
+-      if (len == 0)
+-	len = strlen (value);
+-      _asn1_set_value_octet (node, value, len);
+-      break;
+     case TYPE_GENERALSTRING:
++    case TYPE_NUMERIC_STRING:
++    case TYPE_IA5_STRING:
++    case TYPE_TELETEX_STRING:
++    case TYPE_PRINTABLE_STRING:
++    case TYPE_UNIVERSAL_STRING:
++    case TYPE_BMP_STRING:
++    case TYPE_UTF8_STRING:
++    case TYPE_VISIBLE_STRING:
+       if (len == 0)
+-	len = strlen (value);
+-      _asn1_set_value_octet (node, value, len);
++	len = _asn1_strlen (value);
++      _asn1_set_value_lv (node, value, len);
+       break;
+     case TYPE_BIT_STRING:
+       if (len == 0)
+-	len = strlen (value);
++	len = _asn1_strlen (value);
+       asn1_length_der ((len >> 3) + 2, NULL, &len2);
+-      temp = (unsigned char *) _asn1_malloc ((len >> 3) + 2 + len2);
++      temp = malloc ((len >> 3) + 2 + len2);
+       if (temp == NULL)
+ 	return ASN1_MEM_ALLOC_ERROR;
+ 
+@@ -582,7 +582,7 @@
+       p = node->down;
+       while (p)
+ 	{
+-	  if (!strcmp (p->name, value))
++	  if (!_asn1_strcmp (p->name, value))
+ 	    {
+ 	      p2 = node->down;
+ 	      while (p2)
+@@ -603,11 +603,11 @@
+ 	return ASN1_ELEMENT_NOT_FOUND;
+       break;
+     case TYPE_ANY:
+-      _asn1_set_value_octet (node, value, len);
++      _asn1_set_value_lv (node, value, len);
+       break;
+     case TYPE_SEQUENCE_OF:
+     case TYPE_SET_OF:
+-      if (strcmp (value, "NEW"))
++      if (_asn1_strcmp (value, "NEW"))
+ 	return ASN1_VALUE_NOT_VALID;
+       _asn1_append_sequence_set (node);
+       break;
+@@ -626,29 +626,43 @@
+ 		return ASN1_MEM_ERROR; \
+ 	} else { \
+ 		if (ptr && data_size > 0) \
+-			memcpy( ptr, data, data_size); \
++		  memcpy (ptr, data, data_size); \
+ 	}
+ 
+ #define PUT_STR_VALUE( ptr, ptr_size, data) \
+-	*len = strlen(data) + 1; \
++	*len = _asn1_strlen (data) + 1; \
+ 	if (ptr_size < *len) { \
+ 		return ASN1_MEM_ERROR; \
+ 	} else { \
+ 		/* this strcpy is checked */ \
+ 		if (ptr) { \
+-			strcpy(ptr, data); \
++		  _asn1_strcpy (ptr, data); \
+ 		} \
+ 	}
+ 
+-#define ADD_STR_VALUE( ptr, ptr_size, data) \
+-	*len += strlen(data); \
+-	if (ptr_size < (int) *len) { \
+-		(*len)++; \
++#define PUT_AS_STR_VALUE( ptr, ptr_size, data, data_size) \
++	*len = data_size + 1; \
++	if (ptr_size < *len) { \
+ 		return ASN1_MEM_ERROR; \
+ 	} else { \
+-		/* this strcat is checked */ \
+-		if (ptr) strcat (ptr, data); \
++		/* this strcpy is checked */ \
++		if (ptr) { \
++		  if (data_size > 0) \
++		    memcpy (ptr, data, data_size); \
++		  ptr[data_size] = 0; \
++		} \
+ 	}
++
++#define ADD_STR_VALUE( ptr, ptr_size, data) \
++        *len += _asn1_strlen(data); \
++        if (ptr_size < (int) *len) { \
++                (*len)++; \
++                return ASN1_MEM_ERROR; \
++        } else { \
++                /* this strcat is checked */ \
++                if (ptr) _asn1_strcat (ptr, data); \
++        }
++
+ /**
+  * asn1_read_value:
+  * @root: pointer to a structure.
+@@ -658,7 +672,7 @@
+  * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
+  *   holds the sizeof value.
+  *
+- * Returns the value of one element inside a structure.
++ * Returns the value of one element inside a structure. 
+  * If an element is OPTIONAL and this returns
+  * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
+  * in the der encoding that created the structure.  The first element
+@@ -668,6 +682,7 @@
+  * Note that there can be valid values with length zero. In these case
+  * this function will succeed and @len will be zero.
+  *
++ * INTEGER: VALUE will contain a two's complement form integer.
+  *
+  *            integer=-1  -> value[0]=0xFF , len=1.
+  *            integer=1   -> value[0]=0x01 , len=1.
+@@ -704,36 +719,109 @@
+  * ANY: If NAME indicates an any type, VALUE will indicate the DER
+  *   encoding of the structure actually used.
+  *
+- * Returns:
++ * Returns: %ASN1_SUCCESS if value is returned,
++ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
++ *   %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
++ *   selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
++ *   to store the result, and in this case @len will contain the number of
++ *   bytes needed.
++ **/
++int
++asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
++{
++  return asn1_read_value_type (root, name, ivalue, len, NULL);
++}
++
++/**
++ * asn1_read_value_type:
++ * @root: pointer to a structure.
++ * @name: the name of the element inside a structure that you want to read.
++ * @ivalue: vector that will contain the element's content, must be a
++ *   pointer to memory cells already allocated (may be %NULL).
++ * @len: number of bytes of *value: value[0]..value[len-1]. Initialy
++ *   holds the sizeof value.
++ * @etype: The type of the value read (TYPE)
++ *
++ * Returns the value of one element inside a structure. 
++ * If an element is OPTIONAL and this returns
++ * %ASN1_ELEMENT_NOT_FOUND, it means that this element wasn't present
++ * in the der encoding that created the structure.  The first element
++ * of a SEQUENCE_OF or SET_OF is named "?1". The second one "?2" and
++ * so on.
++ *
++ * Note that there can be valid values with length zero. In these case
++ * this function will succeed and @len will be zero.
++ *
+  *
+- *   %ASN1_SUCCESS: Set value OK.
++ * INTEGER: VALUE will contain a two's complement form integer.
+  *
+- *   %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
++ *            integer=-1  -> value[0]=0xFF , len=1.
++ *            integer=1   -> value[0]=0x01 , len=1.
+  *
+- *   %ASN1_VALUE_NOT_FOUND: There isn't any value for the element selected.
++ * ENUMERATED: As INTEGER (but only with not negative numbers).
++ *
++ * BOOLEAN: VALUE will be the null terminated string "TRUE" or
++ *   "FALSE" and LEN=5 or LEN=6.
++ *
++ * OBJECT IDENTIFIER: VALUE will be a null terminated string with
++ *   each number separated by a dot (i.e. "1.2.3.543.1").
++ *
++ *                      LEN = strlen(VALUE)+1
++ *
++ * UTCTime: VALUE will be a null terminated string in one of these
++ *   formats: "YYMMDDhhmmss+hh'mm'" or "YYMMDDhhmmss-hh'mm'".
++ *   LEN=strlen(VALUE)+1.
++ *
++ * GeneralizedTime: VALUE will be a null terminated string in the
++ *   same format used to set the value.
++ *
++ * OCTET STRING: VALUE will contain the octet string and LEN will be
++ *   the number of octets.
++ *
++ * GeneralString: VALUE will contain the generalstring and LEN will
++ *   be the number of octets.
++ *
++ * BIT STRING: VALUE will contain the bit string organized by bytes
++ *   and LEN will be the number of bits.
++ *
++ * CHOICE: If NAME indicates a choice type, VALUE will specify the
++ *   alternative selected.
++ *
++ * ANY: If NAME indicates an any type, VALUE will indicate the DER
++ *   encoding of the structure actually used.
+  *
+- *   %ASN1_MEM_ERROR: The value vector isn't big enough to store the result.
+- *   In this case LEN will contain the number of bytes needed.
++ * Returns: %ASN1_SUCCESS if value is returned,
++ *   %ASN1_ELEMENT_NOT_FOUND if @name is not a valid element,
++ *   %ASN1_VALUE_NOT_FOUND if there isn't any value for the element
++ *   selected, and %ASN1_MEM_ERROR if The value vector isn't big enough
++ *   to store the result, and in this case @len will contain the number of
++ *   bytes needed.
+  **/
+-asn1_retCode
+-asn1_read_value (ASN1_TYPE root, const char *name, void *ivalue, int *len)
++int
++asn1_read_value_type (ASN1_TYPE root, const char *name, void *ivalue,
++		      int *len, unsigned int *etype)
+ {
+   ASN1_TYPE node, p, p2;
+-  int len2, len3;
++  int len2, len3, result;
+   int value_size = *len;
+   unsigned char *value = ivalue;
++  unsigned type;
+ 
+   node = asn1_find_node (root, name);
+   if (node == NULL)
+     return ASN1_ELEMENT_NOT_FOUND;
+ 
+-  if ((type_field (node->type) != TYPE_NULL) &&
+-      (type_field (node->type) != TYPE_CHOICE) &&
++  type = type_field (node->type);
++
++  if ((type != TYPE_NULL) &&
++      (type != TYPE_CHOICE) &&
+       !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) &&
+       (node->value == NULL))
+     return ASN1_VALUE_NOT_FOUND;
+ 
+-  switch (type_field (node->type))
++  if (etype)
++    *etype = type;
++  switch (type)
+     {
+     case TYPE_NULL:
+       PUT_STR_VALUE (value, value_size, "NULL");
+@@ -772,9 +860,10 @@
+ 	  if ((isdigit (p->value[0])) || (p->value[0] == '-')
+ 	      || (p->value[0] == '+'))
+ 	    {
+-	      if (_asn1_convert_integer
+-		  (p->value, value, value_size, len) != ASN1_SUCCESS)
+-		return ASN1_MEM_ERROR;
++	      result = _asn1_convert_integer
++		  (p->value, value, value_size, len);
++              if (result != ASN1_SUCCESS)
++		return result;
+ 	    }
+ 	  else
+ 	    {			/* is an identifier like v1 */
+@@ -783,12 +872,13 @@
+ 		{
+ 		  if (type_field (p2->type) == TYPE_CONSTANT)
+ 		    {
+-		      if ((p2->name) && (!strcmp (p2->name, p->value)))
++		      if (!_asn1_strcmp (p2->name, p->value))
+ 			{
+-			  if (_asn1_convert_integer
++			  result = _asn1_convert_integer
+ 			      (p2->value, value, value_size,
+-			       len) != ASN1_SUCCESS)
+-			    return ASN1_MEM_ERROR;
++			       len);
++			  if (result != ASN1_SUCCESS)
++			    return result;
+ 			  break;
+ 			}
+ 		    }
+@@ -799,16 +889,19 @@
+       else
+ 	{
+ 	  len2 = -1;
+-	  if (asn1_get_octet_der
++	  result = asn1_get_octet_der
+ 	      (node->value, node->value_len, &len2, value, value_size,
+-	       len) != ASN1_SUCCESS)
+-	    return ASN1_MEM_ERROR;
++	       len);
++          if (result != ASN1_SUCCESS)
++	    return result;
+ 	}
+       break;
+     case TYPE_OBJECT_ID:
+       if (node->type & CONST_ASSIGN)
+ 	{
+-	  value[0] = 0;
++	  *len = 0;
++	  if (value)
++	  	value[0] = 0;
+ 	  p = node->down;
+ 	  while (p)
+ 	    {
+@@ -822,7 +915,7 @@
+ 		}
+ 	      p = p->right;
+ 	    }
+-	  *len = strlen (value) + 1;
++	  (*len)++;
+ 	}
+       else if ((node->type & CONST_DEFAULT) && (node->value == NULL))
+ 	{
+@@ -836,29 +929,34 @@
+ 	  PUT_STR_VALUE (value, value_size, node->value);
+ 	}
+       break;
+-    case TYPE_TIME:
+-      PUT_STR_VALUE (value, value_size, node->value);
++    case TYPE_GENERALIZED_TIME:
++    case TYPE_UTC_TIME:
++      PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len);
+       break;
+     case TYPE_OCTET_STRING:
+-      len2 = -1;
+-      if (asn1_get_octet_der
+-	  (node->value, node->value_len, &len2, value, value_size,
+-	   len) != ASN1_SUCCESS)
+-	return ASN1_MEM_ERROR;
+-      break;
+     case TYPE_GENERALSTRING:
++    case TYPE_NUMERIC_STRING:
++    case TYPE_IA5_STRING:
++    case TYPE_TELETEX_STRING:
++    case TYPE_PRINTABLE_STRING:
++    case TYPE_UNIVERSAL_STRING:
++    case TYPE_BMP_STRING:
++    case TYPE_UTF8_STRING:
++    case TYPE_VISIBLE_STRING:
+       len2 = -1;
+-      if (asn1_get_octet_der
++      result = asn1_get_octet_der
+ 	  (node->value, node->value_len, &len2, value, value_size,
+-	   len) != ASN1_SUCCESS)
+-	return ASN1_MEM_ERROR;
++	   len);
++      if (result != ASN1_SUCCESS)
++	return result;
+       break;
+     case TYPE_BIT_STRING:
+       len2 = -1;
+-      if (asn1_get_bit_der
++      result = asn1_get_bit_der
+ 	  (node->value, node->value_len, &len2, value, value_size,
+-	   len) != ASN1_SUCCESS)
+-	return ASN1_MEM_ERROR;
++	   len);
++      if (result != ASN1_SUCCESS)
++	return result;
+       break;
+     case TYPE_CHOICE:
+       PUT_STR_VALUE (value, value_size, node->down->name);
+@@ -890,13 +988,10 @@
+  * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or
+  * %ASN1_CLASS_CONTEXT_SPECIFIC.
+  *
+- * Returns:
+- *
+- *   %ASN1_SUCCESS: Set value OK.
+- *
+- *   %ASN1_ELEMENT_NOT_FOUND: NAME is not a valid element.
++ * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if
++ *   @name is not a valid element.
+  **/
+-asn1_retCode
++int
+ asn1_read_tag (ASN1_TYPE root, const char *name, int *tagValue,
+ 	       int *classValue)
+ {
+@@ -927,7 +1022,7 @@
+ 
+   if (pTag)
+     {
+-      *tagValue = strtoul (pTag->value, NULL, 10);
++      *tagValue = _asn1_strtoul (pTag->value, NULL, 10);
+ 
+       if (pTag->type & CONST_APPLICATION)
+ 	*classValue = ASN1_CLASS_APPLICATION;
+@@ -940,60 +1035,44 @@
+     }
+   else
+     {
++      unsigned type = type_field (node->type);
+       *classValue = ASN1_CLASS_UNIVERSAL;
+ 
+-      switch (type_field (node->type))
++      switch (type)
+ 	{
+-	case TYPE_NULL:
+-	  *tagValue = ASN1_TAG_NULL;
+-	  break;
+-	case TYPE_BOOLEAN:
+-	  *tagValue = ASN1_TAG_BOOLEAN;
+-	  break;
+-	case TYPE_INTEGER:
+-	  *tagValue = ASN1_TAG_INTEGER;
+-	  break;
+-	case TYPE_ENUMERATED:
+-	  *tagValue = ASN1_TAG_ENUMERATED;
+-	  break;
+-	case TYPE_OBJECT_ID:
+-	  *tagValue = ASN1_TAG_OBJECT_ID;
+-	  break;
+-	case TYPE_TIME:
+-	  if (node->type & CONST_UTC)
+-	    {
+-	      *tagValue = ASN1_TAG_UTCTime;
+-	    }
+-	  else
+-	    *tagValue = ASN1_TAG_GENERALIZEDTime;
+-	  break;
+-	case TYPE_OCTET_STRING:
+-	  *tagValue = ASN1_TAG_OCTET_STRING;
+-	  break;
+-	case TYPE_GENERALSTRING:
+-	  *tagValue = ASN1_TAG_GENERALSTRING;
+-	  break;
+-	case TYPE_BIT_STRING:
+-	  *tagValue = ASN1_TAG_BIT_STRING;
+-	  break;
+-	case TYPE_SEQUENCE:
+-	case TYPE_SEQUENCE_OF:
+-	  *tagValue = ASN1_TAG_SEQUENCE;
+-	  break;
+-	case TYPE_SET:
+-	case TYPE_SET_OF:
+-	  *tagValue = ASN1_TAG_SET;
++	CASE_HANDLED_ETYPES:
++	  *tagValue = _asn1_tags[type].tag;
+ 	  break;
+ 	case TYPE_TAG:
+ 	case TYPE_CHOICE:
+ 	case TYPE_ANY:
++	  *tagValue = -1;
+ 	  break;
+ 	default:
+ 	  break;
+ 	}
+     }
+ 
+-
+   return ASN1_SUCCESS;
++}
+ 
++/**
++ * asn1_read_node_value:
++ * @node: pointer to a node.
++ * @data: a point to a asn1_data_node_st
++ *
++ * Returns the value a data node inside a ASN1_TYPE structure.
++ * The data returned should be handled as constant values.
++ *
++ * Returns: %ASN1_SUCCESS if the node exists.
++ **/
++int
++asn1_read_node_value (ASN1_TYPE node, asn1_data_node_st * data)
++{
++  data->name = node->name;
++  data->value = node->value;
++  data->value_len = node->value_len;
++  data->type = type_field (node->type);
++
++  return ASN1_SUCCESS;
+ }
+--- ORIGINAL/./lib/structure.h	2015-07-14 18:28:22.929332224 -0700
++++ libtasn1-2.8/./lib/structure.h	2015-07-14 18:45:02.727873654 -0700
+@@ -29,13 +29,12 @@
+ #ifndef _STRUCTURE_H
+ #define _STRUCTURE_H
+ 
+-asn1_retCode _asn1_create_static_structure (ASN1_TYPE pointer,
+-					    char *output_file_name,
+-					    char *vector_name);
++int _asn1_create_static_structure (ASN1_TYPE pointer,
++				   char *output_file_name, char *vector_name);
+ 
+ ASN1_TYPE _asn1_copy_structure3 (ASN1_TYPE source_node);
+ 
+-ASN1_TYPE _asn1_add_node_only (unsigned int type);
++ASN1_TYPE _asn1_add_single_node (unsigned int type);
+ 
+ ASN1_TYPE _asn1_find_left (ASN1_TYPE node);
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-07-cve-2015-3622.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,38 @@
+Source:
+Internal
+
+Info:
+https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-3622
+The _asn1_extract_der_octet function in lib/decoding.c in GNU Libtasn1 before 
+4.5 allows remote attackers to cause a denial of service (out-of-bounds heap 
+read) via a crafted certificate.
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- ORIGINAL/./lib/decoding.c	2015-07-14 19:00:52.376976336 -0700
++++ libtasn1-2.8/./lib/decoding.c	2015-07-14 19:02:03.790570755 -0700
+@@ -758,6 +758,7 @@
+     return ASN1_DER_ERROR;
+ 
+   counter = len3 + 1;
++  DECR_LEN(der_len, len3);
+ 
+   if (len2 == -1)
+     counter_end = der_len - 2;
+@@ -766,6 +767,7 @@
+ 
+   while (counter < counter_end)
+     {
++      DECR_LEN(der_len, 1);
+       len2 = asn1_get_length_der (der + counter, der_len, &len3);
+ 
+       if (len2 < -1)
+@@ -787,7 +789,6 @@
+ 	  DECR_LEN(der_len, len2);
+ 	}
+ 
+-      DECR_LEN(der_len, 1);
+       counter += len2 + len3 + 1;
+     }
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/patches/libtasn1-08-test-parser.patch	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,59 @@
+Source:
+Internal
+
+Info:
+To fix the test input and expected output for testing function asn1_parser_asn1
+
+Status:
+Need to determine if this patch has been sent upstream.
+
+--- ORIGINAL/./tests/Test_parser.c	2015-07-14 19:10:29.112559485 -0700
++++ libtasn1-2.8/./tests/Test_parser.c	2015-07-14 19:11:26.058882047 -0700
+@@ -48,17 +48,17 @@
+   /* Test DEFINITIONS syntax */
+   {5,
+    "TEST_PARSER2 { } DEFINITIONS IMPLICIT TAGS ::= BEGIN int1 ::= INTEGER END",
+-   ASN1_SYNTAX_ERROR, _FILE_ ":6: parse error near 'TEST_PARSER'"},
++   ASN1_SYNTAX_ERROR, _FILE_ ":6: Error: syntax error, unexpected IDENTIFIER, expecting $end near 'TEST_PARSER'"},
+   {6, "TEST_PARSER { }", ASN1_SUCCESS, ""},
+ 
+   /* Test ASN1_MAX_NAME_SIZE (128) */
+   {12,
+-   "a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 ::= INTEGER",
++   "a123456789012345678901234567890123456789012345678901234567890123 ::= INTEGER",
+    ASN1_SUCCESS, ""},
+   {12,
+-   "a12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678 ::= INTEGER",
++   "a1234567890123456789012345678901234567890123456789012345678901234 ::= INTEGER",
+    ASN1_NAME_TOO_LONG,
+-   _FILE_ ":12: name too long (more than 128 characters)"},
++   _FILE_ ":12: name too long (more than 64 characters)"},
+ 
+   /* Test 'check identifier' function */
+   {12, "ident1 ::= ident2   ident2 ::= INTEGER",
+@@ -81,13 +81,13 @@
+   {14, "int1 [1] IMPLICIT INTEGER,", ASN1_SUCCESS, ""},
+   {12, "Integer ::= [1] EXPLICIT INTEGER {v1(-1), v2(1)}", ASN1_SUCCESS, ""},
+   {12, "Integer ::= INTEGER {v1(0), v2}",
+-   ASN1_SYNTAX_ERROR, _FILE_ ":12: parse error near '}'"},
++   ASN1_SYNTAX_ERROR, _FILE_ ":12: Error: syntax error, unexpected '}', expecting '(' near '}'"},
+   {12, "Integer ::= INTEGER {v1(0), 1}",
+-   ASN1_SYNTAX_ERROR, _FILE_ ":12: parse error near '1'"},
++   ASN1_SYNTAX_ERROR, _FILE_ ":12: Error: syntax error, unexpected NUM, expecting IDENTIFIER or '(' near '1'"},
+   {12, "const1 INTEGER ::= -1", ASN1_SUCCESS, ""},
+   {12, "const1 INTEGER ::= 1", ASN1_SUCCESS, ""},
+   {12, "const1 INTEGER ::= v1",
+-   ASN1_SYNTAX_ERROR, _FILE_ ":12: parse error near 'v1'"},
++   ASN1_SYNTAX_ERROR, _FILE_ ":12: Error: syntax error, unexpected IDENTIFIER, expecting NUM or '+' or '-' near 'v1'"},
+   {16, " generic generalstring",
+    ASN1_IDENTIFIER_NOT_FOUND,
+    _FILE_ ":: identifier 'generalstring' not found"},
+@@ -98,7 +98,7 @@
+   {20, "   oid1    OBJECT IDENTIFIER DEFAULT 1",
+    ASN1_IDENTIFIER_NOT_FOUND, _FILE_ ":: identifier '1' not found"},
+   {20, "   oid1    OBJECT IDENTIFIER DEFAULT",
+-   ASN1_SYNTAX_ERROR, _FILE_ ":21: parse error near '}'"},
++   ASN1_SYNTAX_ERROR, _FILE_ ":21: Error: syntax error, unexpected '}' near '}'"},
+   {20, "   oid1    OBJECT IDENTIFIER DEFAULT Oid-type1",
+    ASN1_SUCCESS, ""},
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/libtasn1/test/results-all.master	Thu Jul 30 17:45:10 2015 -0700
@@ -0,0 +1,8 @@
+PASS: Test_parser
+PASS: Test_tree
+PASS: Test_encoding
+PASS: Test_indefinite
+PASS: Test_errors
+PASS: crlf
+PASS: threadsafety
+All 7 tests passed