diff options
Diffstat (limited to 'lib/minitasn1')
-rw-r--r-- | lib/minitasn1/Makefile.am | 34 | ||||
-rw-r--r-- | lib/minitasn1/Makefile.in | 2418 | ||||
-rw-r--r-- | lib/minitasn1/coding.c | 1413 | ||||
-rw-r--r-- | lib/minitasn1/decoding.c | 2478 | ||||
-rw-r--r-- | lib/minitasn1/element.c | 1111 | ||||
-rw-r--r-- | lib/minitasn1/element.h | 40 | ||||
-rw-r--r-- | lib/minitasn1/errors.c | 100 | ||||
-rw-r--r-- | lib/minitasn1/gstr.c | 74 | ||||
-rw-r--r-- | lib/minitasn1/gstr.h | 47 | ||||
-rw-r--r-- | lib/minitasn1/int.h | 221 | ||||
-rw-r--r-- | lib/minitasn1/libtasn1.h | 637 | ||||
-rw-r--r-- | lib/minitasn1/parser_aux.c | 1173 | ||||
-rw-r--r-- | lib/minitasn1/parser_aux.h | 172 | ||||
-rw-r--r-- | lib/minitasn1/structure.c | 1220 | ||||
-rw-r--r-- | lib/minitasn1/structure.h | 45 | ||||
-rw-r--r-- | lib/minitasn1/version.c | 51 |
16 files changed, 11234 insertions, 0 deletions
diff --git a/lib/minitasn1/Makefile.am b/lib/minitasn1/Makefile.am new file mode 100644 index 0000000..9b67697 --- /dev/null +++ b/lib/minitasn1/Makefile.am @@ -0,0 +1,34 @@ +## Process this file with automake to produce Makefile.in +# Copyright (C) 2002-2010, 2012 Free Software Foundation, Inc. +# +# Author: Nikos Mavrogiannopoulos +# +# This file is part of GnuTLS. +# +# The GnuTLS is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# The GnuTLS 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with GnuTLS; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA + +include $(top_srcdir)/lib/common.mk + +AM_CPPFLAGS = -DASN1_BUILDING \ + -I$(srcdir)/../../gl \ + -I$(builddir)/../../gl \ + -I$(srcdir)/.. + +noinst_LTLIBRARIES = libminitasn1.la + +libminitasn1_la_SOURCES = libtasn1.h gstr.h int.h parser_aux.h \ + structure.h element.h decoding.c gstr.c errors.c parser_aux.c \ + structure.c element.c coding.c version.c diff --git a/lib/minitasn1/Makefile.in b/lib/minitasn1/Makefile.in new file mode 100644 index 0000000..499bcfd --- /dev/null +++ b/lib/minitasn1/Makefile.in @@ -0,0 +1,2418 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright (C) 2002-2010, 2012 Free Software Foundation, Inc. +# +# Author: Nikos Mavrogiannopoulos +# +# This file is part of GnuTLS. +# +# The GnuTLS is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# The GnuTLS 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with GnuTLS; if not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lib/minitasn1 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/lib/unistring/m4/gnulib-comp.m4 \ + $(top_srcdir)/lib/unistring/m4/inline.m4 \ + $(top_srcdir)/lib/unistring/m4/libunistring-base.m4 \ + $(top_srcdir)/src/gl/m4/atoll.m4 \ + $(top_srcdir)/src/gl/m4/bison.m4 \ + $(top_srcdir)/src/gl/m4/calloc.m4 \ + $(top_srcdir)/src/gl/m4/clock_time.m4 \ + $(top_srcdir)/src/gl/m4/codeset.m4 \ + $(top_srcdir)/src/gl/m4/ctype_h.m4 \ + $(top_srcdir)/src/gl/m4/environ.m4 \ + $(top_srcdir)/src/gl/m4/error.m4 \ + $(top_srcdir)/src/gl/m4/fdopen.m4 \ + $(top_srcdir)/src/gl/m4/flexmember.m4 \ + $(top_srcdir)/src/gl/m4/fpending.m4 \ + $(top_srcdir)/src/gl/m4/fpieee.m4 \ + $(top_srcdir)/src/gl/m4/fseek.m4 \ + $(top_srcdir)/src/gl/m4/ftruncate.m4 \ + $(top_srcdir)/src/gl/m4/getaddrinfo.m4 \ + $(top_srcdir)/src/gl/m4/getcwd.m4 \ + $(top_srcdir)/src/gl/m4/getpagesize.m4 \ + $(top_srcdir)/src/gl/m4/getpass.m4 \ + $(top_srcdir)/src/gl/m4/getprogname.m4 \ + $(top_srcdir)/src/gl/m4/gettime.m4 \ + $(top_srcdir)/src/gl/m4/gnulib-comp.m4 \ + $(top_srcdir)/src/gl/m4/hostent.m4 \ + $(top_srcdir)/src/gl/m4/intl-thread-locale.m4 \ + $(top_srcdir)/src/gl/m4/inttostr.m4 \ + $(top_srcdir)/src/gl/m4/ioctl.m4 \ + $(top_srcdir)/src/gl/m4/isblank.m4 \ + $(top_srcdir)/src/gl/m4/langinfo_h.m4 \ + $(top_srcdir)/src/gl/m4/lcmessage.m4 \ + $(top_srcdir)/src/gl/m4/locale-fr.m4 \ + $(top_srcdir)/src/gl/m4/locale-ja.m4 \ + $(top_srcdir)/src/gl/m4/locale-tr.m4 \ + $(top_srcdir)/src/gl/m4/locale-zh.m4 \ + $(top_srcdir)/src/gl/m4/locale_h.m4 \ + $(top_srcdir)/src/gl/m4/localename.m4 \ + $(top_srcdir)/src/gl/m4/lstat.m4 \ + $(top_srcdir)/src/gl/m4/mktime.m4 \ + $(top_srcdir)/src/gl/m4/nanosleep.m4 \ + $(top_srcdir)/src/gl/m4/nstrftime.m4 \ + $(top_srcdir)/src/gl/m4/parse-datetime.m4 \ + $(top_srcdir)/src/gl/m4/perror.m4 \ + $(top_srcdir)/src/gl/m4/pipe.m4 \ + $(top_srcdir)/src/gl/m4/pthread-thread.m4 \ + $(top_srcdir)/src/gl/m4/pthread_h.m4 \ + $(top_srcdir)/src/gl/m4/pthread_sigmask.m4 \ + $(top_srcdir)/src/gl/m4/putenv.m4 \ + $(top_srcdir)/src/gl/m4/raise.m4 \ + $(top_srcdir)/src/gl/m4/reallocarray.m4 \ + $(top_srcdir)/src/gl/m4/sched_h.m4 \ + $(top_srcdir)/src/gl/m4/sched_yield.m4 \ + $(top_srcdir)/src/gl/m4/select.m4 \ + $(top_srcdir)/src/gl/m4/semaphore.m4 \ + $(top_srcdir)/src/gl/m4/servent.m4 \ + $(top_srcdir)/src/gl/m4/setenv.m4 \ + $(top_srcdir)/src/gl/m4/setlocale.m4 \ + $(top_srcdir)/src/gl/m4/setlocale_null.m4 \ + $(top_srcdir)/src/gl/m4/sigaction.m4 \ + $(top_srcdir)/src/gl/m4/signal_h.m4 \ + $(top_srcdir)/src/gl/m4/signalblocking.m4 \ + $(top_srcdir)/src/gl/m4/sleep.m4 \ + $(top_srcdir)/src/gl/m4/sockets.m4 \ + $(top_srcdir)/src/gl/m4/strerror.m4 \ + $(top_srcdir)/src/gl/m4/strerror_r.m4 \ + $(top_srcdir)/src/gl/m4/strtoll.m4 \ + $(top_srcdir)/src/gl/m4/symlink.m4 \ + $(top_srcdir)/src/gl/m4/sys_ioctl_h.m4 \ + $(top_srcdir)/src/gl/m4/sys_select_h.m4 \ + $(top_srcdir)/src/gl/m4/thread.m4 \ + $(top_srcdir)/src/gl/m4/time_rz.m4 \ + $(top_srcdir)/src/gl/m4/timegm.m4 \ + $(top_srcdir)/src/gl/m4/timespec.m4 \ + $(top_srcdir)/src/gl/m4/tm_gmtoff.m4 \ + $(top_srcdir)/src/gl/m4/tzset.m4 \ + $(top_srcdir)/src/gl/m4/usleep.m4 \ + $(top_srcdir)/src/gl/m4/visibility.m4 \ + $(top_srcdir)/src/gl/m4/xalloc.m4 \ + $(top_srcdir)/src/gl/m4/yield.m4 $(top_srcdir)/m4/00gnulib.m4 \ + $(top_srcdir)/m4/__inline.m4 \ + $(top_srcdir)/m4/absolute-header.m4 $(top_srcdir)/m4/alloca.m4 \ + $(top_srcdir)/m4/arpa_inet_h.m4 \ + $(top_srcdir)/m4/ax_ac_append_to_file.m4 \ + $(top_srcdir)/m4/ax_ac_print_to_file.m4 \ + $(top_srcdir)/m4/ax_add_am_macro_static.m4 \ + $(top_srcdir)/m4/ax_am_macros_static.m4 \ + $(top_srcdir)/m4/ax_check_gnu_make.m4 \ + $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/ax_file_escapes.m4 \ + $(top_srcdir)/m4/builtin-expect.m4 \ + $(top_srcdir)/m4/byteswap.m4 $(top_srcdir)/m4/close.m4 \ + $(top_srcdir)/m4/double-slash-root.m4 $(top_srcdir)/m4/dup2.m4 \ + $(top_srcdir)/m4/eealloc.m4 $(top_srcdir)/m4/errno_h.m4 \ + $(top_srcdir)/m4/explicit_bzero.m4 \ + $(top_srcdir)/m4/exponentd.m4 $(top_srcdir)/m4/extensions.m4 \ + $(top_srcdir)/m4/extern-inline.m4 $(top_srcdir)/m4/fcntl-o.m4 \ + $(top_srcdir)/m4/fcntl.m4 $(top_srcdir)/m4/fcntl_h.m4 \ + $(top_srcdir)/m4/float_h.m4 $(top_srcdir)/m4/fopen.m4 \ + $(top_srcdir)/m4/free.m4 $(top_srcdir)/m4/fseeko.m4 \ + $(top_srcdir)/m4/fstat.m4 $(top_srcdir)/m4/ftell.m4 \ + $(top_srcdir)/m4/ftello.m4 $(top_srcdir)/m4/func.m4 \ + $(top_srcdir)/m4/getdelim.m4 $(top_srcdir)/m4/getdtablesize.m4 \ + $(top_srcdir)/m4/getline.m4 $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gettimeofday.m4 \ + $(top_srcdir)/m4/gnulib-common.m4 \ + $(top_srcdir)/m4/gnulib-comp.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/guile.m4 $(top_srcdir)/m4/hooks.m4 \ + $(top_srcdir)/m4/host-cpu-c-abi.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/inet_ntop.m4 \ + $(top_srcdir)/m4/inet_pton.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intmax_t.m4 $(top_srcdir)/m4/inttypes.m4 \ + $(top_srcdir)/m4/inttypes_h.m4 $(top_srcdir)/m4/largefile.m4 \ + $(top_srcdir)/m4/ld-output-def.m4 \ + $(top_srcdir)/m4/ld-version-script.m4 $(top_srcdir)/m4/ldd.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/limits-h.m4 $(top_srcdir)/m4/lock.m4 \ + $(top_srcdir)/m4/lseek.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/malloc.m4 \ + $(top_srcdir)/m4/malloca.m4 $(top_srcdir)/m4/manywarnings.m4 \ + $(top_srcdir)/m4/memchr.m4 $(top_srcdir)/m4/memmem.m4 \ + $(top_srcdir)/m4/minmax.m4 $(top_srcdir)/m4/mmap-anon.m4 \ + $(top_srcdir)/m4/mode_t.m4 $(top_srcdir)/m4/msvc-inval.m4 \ + $(top_srcdir)/m4/msvc-nothrow.m4 $(top_srcdir)/m4/multiarch.m4 \ + $(top_srcdir)/m4/netdb_h.m4 $(top_srcdir)/m4/netinet_in_h.m4 \ + $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/off_t.m4 \ + $(top_srcdir)/m4/open-cloexec.m4 \ + $(top_srcdir)/m4/open-slash.m4 $(top_srcdir)/m4/open.m4 \ + $(top_srcdir)/m4/pathmax.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf.m4 \ + $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/pthread_rwlock_rdlock.m4 \ + $(top_srcdir)/m4/read-file.m4 $(top_srcdir)/m4/realloc.m4 \ + $(top_srcdir)/m4/secure_getenv.m4 $(top_srcdir)/m4/size_max.m4 \ + $(top_srcdir)/m4/snprintf.m4 $(top_srcdir)/m4/socketlib.m4 \ + $(top_srcdir)/m4/socklen.m4 $(top_srcdir)/m4/sockpfaf.m4 \ + $(top_srcdir)/m4/ssize_t.m4 $(top_srcdir)/m4/stat-time.m4 \ + $(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdalign.m4 \ + $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ + $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdint_h.m4 \ + $(top_srcdir)/m4/stdio_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \ + $(top_srcdir)/m4/stpcpy.m4 $(top_srcdir)/m4/strcase.m4 \ + $(top_srcdir)/m4/strdup.m4 $(top_srcdir)/m4/string_h.m4 \ + $(top_srcdir)/m4/strings_h.m4 $(top_srcdir)/m4/strndup.m4 \ + $(top_srcdir)/m4/strnlen.m4 $(top_srcdir)/m4/strtok_r.m4 \ + $(top_srcdir)/m4/strverscmp.m4 \ + $(top_srcdir)/m4/sys_socket_h.m4 \ + $(top_srcdir)/m4/sys_stat_h.m4 $(top_srcdir)/m4/sys_time_h.m4 \ + $(top_srcdir)/m4/sys_types_h.m4 $(top_srcdir)/m4/sys_uio_h.m4 \ + $(top_srcdir)/m4/threadlib.m4 $(top_srcdir)/m4/time_h.m4 \ + $(top_srcdir)/m4/time_r.m4 $(top_srcdir)/m4/ungetc.m4 \ + $(top_srcdir)/m4/unistd_h.m4 \ + $(top_srcdir)/m4/valgrind-tests.m4 \ + $(top_srcdir)/m4/vasnprintf.m4 $(top_srcdir)/m4/vasprintf.m4 \ + $(top_srcdir)/m4/vsnprintf.m4 $(top_srcdir)/m4/warn-on-use.m4 \ + $(top_srcdir)/m4/warnings.m4 $(top_srcdir)/m4/wchar_h.m4 \ + $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \ + $(top_srcdir)/m4/xsize.m4 $(top_srcdir)/m4/zzgnulib.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libminitasn1_la_LIBADD = +am_libminitasn1_la_OBJECTS = decoding.lo gstr.lo errors.lo \ + parser_aux.lo structure.lo element.lo coding.lo version.lo +libminitasn1_la_OBJECTS = $(am_libminitasn1_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/coding.Plo ./$(DEPDIR)/decoding.Plo \ + ./$(DEPDIR)/element.Plo ./$(DEPDIR)/errors.Plo \ + ./$(DEPDIR)/gstr.Plo ./$(DEPDIR)/parser_aux.Plo \ + ./$(DEPDIR)/structure.Plo ./$(DEPDIR)/version.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libminitasn1_la_SOURCES) +DIST_SOURCES = $(libminitasn1_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp $(top_srcdir)/lib/common.mk +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AARCH64_CCASFLAGS = @AARCH64_CCASFLAGS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALLOCA_H = @ALLOCA_H@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_VALGRINDFLAGS = @AM_VALGRINDFLAGS@ +APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +ASN1PARSER = @ASN1PARSER@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BITSIZEOF_PTRDIFF_T = @BITSIZEOF_PTRDIFF_T@ +BITSIZEOF_SIG_ATOMIC_T = @BITSIZEOF_SIG_ATOMIC_T@ +BITSIZEOF_SIZE_T = @BITSIZEOF_SIZE_T@ +BITSIZEOF_WCHAR_T = @BITSIZEOF_WCHAR_T@ +BITSIZEOF_WINT_T = @BITSIZEOF_WINT_T@ +BYTESWAP_H = @BYTESWAP_H@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CFLAG_VISIBILITY = @CFLAG_VISIBILITY@ +CMOCKA_CFLAGS = @CMOCKA_CFLAGS@ +CMOCKA_LIBS = @CMOCKA_LIBS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@ +CONFIG_INCLUDE = @CONFIG_INCLUDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CRYWRAP_PATCHLEVEL = @CRYWRAP_PATCHLEVEL@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXX_LT_AGE = @CXX_LT_AGE@ +CXX_LT_CURRENT = @CXX_LT_CURRENT@ +CXX_LT_REVISION = @CXX_LT_REVISION@ +CYGPATH_W = @CYGPATH_W@ +DEFAULT_VALGRINDFLAGS = @DEFAULT_VALGRINDFLAGS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DLL_SSL_VERSION = @DLL_SSL_VERSION@ +DLL_VERSION = @DLL_VERSION@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@ +EMULTIHOP_VALUE = @EMULTIHOP_VALUE@ +ENABLE_PADLOCK = @ENABLE_PADLOCK@ +ENOLINK_HIDDEN = @ENOLINK_HIDDEN@ +ENOLINK_VALUE = @ENOLINK_VALUE@ +EOVERFLOW_HIDDEN = @EOVERFLOW_HIDDEN@ +EOVERFLOW_VALUE = @EOVERFLOW_VALUE@ +ERRNO_H = @ERRNO_H@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +FIPS140_LIBS = @FIPS140_LIBS@ +FLOAT_H = @FLOAT_H@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GETADDRINFO_LIB = @GETADDRINFO_LIB@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GL_GGL_GNULIB_ACCEPT = @GL_GGL_GNULIB_ACCEPT@ +GL_GGL_GNULIB_ACCEPT4 = @GL_GGL_GNULIB_ACCEPT4@ +GL_GGL_GNULIB_ACCESS = @GL_GGL_GNULIB_ACCESS@ +GL_GGL_GNULIB_ALIGNED_ALLOC = @GL_GGL_GNULIB_ALIGNED_ALLOC@ +GL_GGL_GNULIB_ATOLL = @GL_GGL_GNULIB_ATOLL@ +GL_GGL_GNULIB_BIND = @GL_GGL_GNULIB_BIND@ +GL_GGL_GNULIB_BTOWC = @GL_GGL_GNULIB_BTOWC@ +GL_GGL_GNULIB_CALLOC_POSIX = @GL_GGL_GNULIB_CALLOC_POSIX@ +GL_GGL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GGL_GNULIB_CANONICALIZE_FILE_NAME@ +GL_GGL_GNULIB_CHDIR = @GL_GGL_GNULIB_CHDIR@ +GL_GGL_GNULIB_CHOWN = @GL_GGL_GNULIB_CHOWN@ +GL_GGL_GNULIB_CLOSE = @GL_GGL_GNULIB_CLOSE@ +GL_GGL_GNULIB_CONNECT = @GL_GGL_GNULIB_CONNECT@ +GL_GGL_GNULIB_COPY_FILE_RANGE = @GL_GGL_GNULIB_COPY_FILE_RANGE@ +GL_GGL_GNULIB_CREAT = @GL_GGL_GNULIB_CREAT@ +GL_GGL_GNULIB_CTIME = @GL_GGL_GNULIB_CTIME@ +GL_GGL_GNULIB_DPRINTF = @GL_GGL_GNULIB_DPRINTF@ +GL_GGL_GNULIB_DUP = @GL_GGL_GNULIB_DUP@ +GL_GGL_GNULIB_DUP2 = @GL_GGL_GNULIB_DUP2@ +GL_GGL_GNULIB_DUP3 = @GL_GGL_GNULIB_DUP3@ +GL_GGL_GNULIB_DUPLOCALE = @GL_GGL_GNULIB_DUPLOCALE@ +GL_GGL_GNULIB_ENVIRON = @GL_GGL_GNULIB_ENVIRON@ +GL_GGL_GNULIB_EUIDACCESS = @GL_GGL_GNULIB_EUIDACCESS@ +GL_GGL_GNULIB_EXECL = @GL_GGL_GNULIB_EXECL@ +GL_GGL_GNULIB_EXECLE = @GL_GGL_GNULIB_EXECLE@ +GL_GGL_GNULIB_EXECLP = @GL_GGL_GNULIB_EXECLP@ +GL_GGL_GNULIB_EXECV = @GL_GGL_GNULIB_EXECV@ +GL_GGL_GNULIB_EXECVE = @GL_GGL_GNULIB_EXECVE@ +GL_GGL_GNULIB_EXECVP = @GL_GGL_GNULIB_EXECVP@ +GL_GGL_GNULIB_EXECVPE = @GL_GGL_GNULIB_EXECVPE@ +GL_GGL_GNULIB_EXPLICIT_BZERO = @GL_GGL_GNULIB_EXPLICIT_BZERO@ +GL_GGL_GNULIB_FACCESSAT = @GL_GGL_GNULIB_FACCESSAT@ +GL_GGL_GNULIB_FCHDIR = @GL_GGL_GNULIB_FCHDIR@ +GL_GGL_GNULIB_FCHMODAT = @GL_GGL_GNULIB_FCHMODAT@ +GL_GGL_GNULIB_FCHOWNAT = @GL_GGL_GNULIB_FCHOWNAT@ +GL_GGL_GNULIB_FCLOSE = @GL_GGL_GNULIB_FCLOSE@ +GL_GGL_GNULIB_FCNTL = @GL_GGL_GNULIB_FCNTL@ +GL_GGL_GNULIB_FDATASYNC = @GL_GGL_GNULIB_FDATASYNC@ +GL_GGL_GNULIB_FDOPEN = @GL_GGL_GNULIB_FDOPEN@ +GL_GGL_GNULIB_FFLUSH = @GL_GGL_GNULIB_FFLUSH@ +GL_GGL_GNULIB_FFS = @GL_GGL_GNULIB_FFS@ +GL_GGL_GNULIB_FFSL = @GL_GGL_GNULIB_FFSL@ +GL_GGL_GNULIB_FFSLL = @GL_GGL_GNULIB_FFSLL@ +GL_GGL_GNULIB_FGETC = @GL_GGL_GNULIB_FGETC@ +GL_GGL_GNULIB_FGETS = @GL_GGL_GNULIB_FGETS@ +GL_GGL_GNULIB_FOPEN = @GL_GGL_GNULIB_FOPEN@ +GL_GGL_GNULIB_FPRINTF = @GL_GGL_GNULIB_FPRINTF@ +GL_GGL_GNULIB_FPRINTF_POSIX = @GL_GGL_GNULIB_FPRINTF_POSIX@ +GL_GGL_GNULIB_FPURGE = @GL_GGL_GNULIB_FPURGE@ +GL_GGL_GNULIB_FPUTC = @GL_GGL_GNULIB_FPUTC@ +GL_GGL_GNULIB_FPUTS = @GL_GGL_GNULIB_FPUTS@ +GL_GGL_GNULIB_FREAD = @GL_GGL_GNULIB_FREAD@ +GL_GGL_GNULIB_FREE_POSIX = @GL_GGL_GNULIB_FREE_POSIX@ +GL_GGL_GNULIB_FREOPEN = @GL_GGL_GNULIB_FREOPEN@ +GL_GGL_GNULIB_FSCANF = @GL_GGL_GNULIB_FSCANF@ +GL_GGL_GNULIB_FSEEK = @GL_GGL_GNULIB_FSEEK@ +GL_GGL_GNULIB_FSEEKO = @GL_GGL_GNULIB_FSEEKO@ +GL_GGL_GNULIB_FSTAT = @GL_GGL_GNULIB_FSTAT@ +GL_GGL_GNULIB_FSTATAT = @GL_GGL_GNULIB_FSTATAT@ +GL_GGL_GNULIB_FSYNC = @GL_GGL_GNULIB_FSYNC@ +GL_GGL_GNULIB_FTELL = @GL_GGL_GNULIB_FTELL@ +GL_GGL_GNULIB_FTELLO = @GL_GGL_GNULIB_FTELLO@ +GL_GGL_GNULIB_FTRUNCATE = @GL_GGL_GNULIB_FTRUNCATE@ +GL_GGL_GNULIB_FUTIMENS = @GL_GGL_GNULIB_FUTIMENS@ +GL_GGL_GNULIB_FWRITE = @GL_GGL_GNULIB_FWRITE@ +GL_GGL_GNULIB_GETADDRINFO = @GL_GGL_GNULIB_GETADDRINFO@ +GL_GGL_GNULIB_GETC = @GL_GGL_GNULIB_GETC@ +GL_GGL_GNULIB_GETCHAR = @GL_GGL_GNULIB_GETCHAR@ +GL_GGL_GNULIB_GETCWD = @GL_GGL_GNULIB_GETCWD@ +GL_GGL_GNULIB_GETDELIM = @GL_GGL_GNULIB_GETDELIM@ +GL_GGL_GNULIB_GETDOMAINNAME = @GL_GGL_GNULIB_GETDOMAINNAME@ +GL_GGL_GNULIB_GETDTABLESIZE = @GL_GGL_GNULIB_GETDTABLESIZE@ +GL_GGL_GNULIB_GETENTROPY = @GL_GGL_GNULIB_GETENTROPY@ +GL_GGL_GNULIB_GETGROUPS = @GL_GGL_GNULIB_GETGROUPS@ +GL_GGL_GNULIB_GETHOSTNAME = @GL_GGL_GNULIB_GETHOSTNAME@ +GL_GGL_GNULIB_GETLINE = @GL_GGL_GNULIB_GETLINE@ +GL_GGL_GNULIB_GETLOADAVG = @GL_GGL_GNULIB_GETLOADAVG@ +GL_GGL_GNULIB_GETLOGIN = @GL_GGL_GNULIB_GETLOGIN@ +GL_GGL_GNULIB_GETLOGIN_R = @GL_GGL_GNULIB_GETLOGIN_R@ +GL_GGL_GNULIB_GETOPT_POSIX = @GL_GGL_GNULIB_GETOPT_POSIX@ +GL_GGL_GNULIB_GETPAGESIZE = @GL_GGL_GNULIB_GETPAGESIZE@ +GL_GGL_GNULIB_GETPASS = @GL_GGL_GNULIB_GETPASS@ +GL_GGL_GNULIB_GETPEERNAME = @GL_GGL_GNULIB_GETPEERNAME@ +GL_GGL_GNULIB_GETSOCKNAME = @GL_GGL_GNULIB_GETSOCKNAME@ +GL_GGL_GNULIB_GETSOCKOPT = @GL_GGL_GNULIB_GETSOCKOPT@ +GL_GGL_GNULIB_GETSUBOPT = @GL_GGL_GNULIB_GETSUBOPT@ +GL_GGL_GNULIB_GETTIMEOFDAY = @GL_GGL_GNULIB_GETTIMEOFDAY@ +GL_GGL_GNULIB_GETUMASK = @GL_GGL_GNULIB_GETUMASK@ +GL_GGL_GNULIB_GETUSERSHELL = @GL_GGL_GNULIB_GETUSERSHELL@ +GL_GGL_GNULIB_GRANTPT = @GL_GGL_GNULIB_GRANTPT@ +GL_GGL_GNULIB_GROUP_MEMBER = @GL_GGL_GNULIB_GROUP_MEMBER@ +GL_GGL_GNULIB_IMAXABS = @GL_GGL_GNULIB_IMAXABS@ +GL_GGL_GNULIB_IMAXDIV = @GL_GGL_GNULIB_IMAXDIV@ +GL_GGL_GNULIB_INET_NTOP = @GL_GGL_GNULIB_INET_NTOP@ +GL_GGL_GNULIB_INET_PTON = @GL_GGL_GNULIB_INET_PTON@ +GL_GGL_GNULIB_IOCTL = @GL_GGL_GNULIB_IOCTL@ +GL_GGL_GNULIB_ISATTY = @GL_GGL_GNULIB_ISATTY@ +GL_GGL_GNULIB_ISBLANK = @GL_GGL_GNULIB_ISBLANK@ +GL_GGL_GNULIB_LCHMOD = @GL_GGL_GNULIB_LCHMOD@ +GL_GGL_GNULIB_LCHOWN = @GL_GGL_GNULIB_LCHOWN@ +GL_GGL_GNULIB_LINK = @GL_GGL_GNULIB_LINK@ +GL_GGL_GNULIB_LINKAT = @GL_GGL_GNULIB_LINKAT@ +GL_GGL_GNULIB_LISTEN = @GL_GGL_GNULIB_LISTEN@ +GL_GGL_GNULIB_LOCALECONV = @GL_GGL_GNULIB_LOCALECONV@ +GL_GGL_GNULIB_LOCALENAME = @GL_GGL_GNULIB_LOCALENAME@ +GL_GGL_GNULIB_LOCALTIME = @GL_GGL_GNULIB_LOCALTIME@ +GL_GGL_GNULIB_LSEEK = @GL_GGL_GNULIB_LSEEK@ +GL_GGL_GNULIB_LSTAT = @GL_GGL_GNULIB_LSTAT@ +GL_GGL_GNULIB_MALLOC_POSIX = @GL_GGL_GNULIB_MALLOC_POSIX@ +GL_GGL_GNULIB_MBRLEN = @GL_GGL_GNULIB_MBRLEN@ +GL_GGL_GNULIB_MBRTOWC = @GL_GGL_GNULIB_MBRTOWC@ +GL_GGL_GNULIB_MBSCASECMP = @GL_GGL_GNULIB_MBSCASECMP@ +GL_GGL_GNULIB_MBSCASESTR = @GL_GGL_GNULIB_MBSCASESTR@ +GL_GGL_GNULIB_MBSCHR = @GL_GGL_GNULIB_MBSCHR@ +GL_GGL_GNULIB_MBSCSPN = @GL_GGL_GNULIB_MBSCSPN@ +GL_GGL_GNULIB_MBSINIT = @GL_GGL_GNULIB_MBSINIT@ +GL_GGL_GNULIB_MBSLEN = @GL_GGL_GNULIB_MBSLEN@ +GL_GGL_GNULIB_MBSNCASECMP = @GL_GGL_GNULIB_MBSNCASECMP@ +GL_GGL_GNULIB_MBSNLEN = @GL_GGL_GNULIB_MBSNLEN@ +GL_GGL_GNULIB_MBSNRTOWCS = @GL_GGL_GNULIB_MBSNRTOWCS@ +GL_GGL_GNULIB_MBSPBRK = @GL_GGL_GNULIB_MBSPBRK@ +GL_GGL_GNULIB_MBSPCASECMP = @GL_GGL_GNULIB_MBSPCASECMP@ +GL_GGL_GNULIB_MBSRCHR = @GL_GGL_GNULIB_MBSRCHR@ +GL_GGL_GNULIB_MBSRTOWCS = @GL_GGL_GNULIB_MBSRTOWCS@ +GL_GGL_GNULIB_MBSSEP = @GL_GGL_GNULIB_MBSSEP@ +GL_GGL_GNULIB_MBSSPN = @GL_GGL_GNULIB_MBSSPN@ +GL_GGL_GNULIB_MBSSTR = @GL_GGL_GNULIB_MBSSTR@ +GL_GGL_GNULIB_MBSTOK_R = @GL_GGL_GNULIB_MBSTOK_R@ +GL_GGL_GNULIB_MBTOWC = @GL_GGL_GNULIB_MBTOWC@ +GL_GGL_GNULIB_MDA_ACCESS = @GL_GGL_GNULIB_MDA_ACCESS@ +GL_GGL_GNULIB_MDA_CHDIR = @GL_GGL_GNULIB_MDA_CHDIR@ +GL_GGL_GNULIB_MDA_CHMOD = @GL_GGL_GNULIB_MDA_CHMOD@ +GL_GGL_GNULIB_MDA_CLOSE = @GL_GGL_GNULIB_MDA_CLOSE@ +GL_GGL_GNULIB_MDA_CREAT = @GL_GGL_GNULIB_MDA_CREAT@ +GL_GGL_GNULIB_MDA_DUP = @GL_GGL_GNULIB_MDA_DUP@ +GL_GGL_GNULIB_MDA_DUP2 = @GL_GGL_GNULIB_MDA_DUP2@ +GL_GGL_GNULIB_MDA_ECVT = @GL_GGL_GNULIB_MDA_ECVT@ +GL_GGL_GNULIB_MDA_EXECL = @GL_GGL_GNULIB_MDA_EXECL@ +GL_GGL_GNULIB_MDA_EXECLE = @GL_GGL_GNULIB_MDA_EXECLE@ +GL_GGL_GNULIB_MDA_EXECLP = @GL_GGL_GNULIB_MDA_EXECLP@ +GL_GGL_GNULIB_MDA_EXECV = @GL_GGL_GNULIB_MDA_EXECV@ +GL_GGL_GNULIB_MDA_EXECVE = @GL_GGL_GNULIB_MDA_EXECVE@ +GL_GGL_GNULIB_MDA_EXECVP = @GL_GGL_GNULIB_MDA_EXECVP@ +GL_GGL_GNULIB_MDA_EXECVPE = @GL_GGL_GNULIB_MDA_EXECVPE@ +GL_GGL_GNULIB_MDA_FCLOSEALL = @GL_GGL_GNULIB_MDA_FCLOSEALL@ +GL_GGL_GNULIB_MDA_FCVT = @GL_GGL_GNULIB_MDA_FCVT@ +GL_GGL_GNULIB_MDA_FDOPEN = @GL_GGL_GNULIB_MDA_FDOPEN@ +GL_GGL_GNULIB_MDA_FILENO = @GL_GGL_GNULIB_MDA_FILENO@ +GL_GGL_GNULIB_MDA_GCVT = @GL_GGL_GNULIB_MDA_GCVT@ +GL_GGL_GNULIB_MDA_GETCWD = @GL_GGL_GNULIB_MDA_GETCWD@ +GL_GGL_GNULIB_MDA_GETPID = @GL_GGL_GNULIB_MDA_GETPID@ +GL_GGL_GNULIB_MDA_GETW = @GL_GGL_GNULIB_MDA_GETW@ +GL_GGL_GNULIB_MDA_ISATTY = @GL_GGL_GNULIB_MDA_ISATTY@ +GL_GGL_GNULIB_MDA_LSEEK = @GL_GGL_GNULIB_MDA_LSEEK@ +GL_GGL_GNULIB_MDA_MEMCCPY = @GL_GGL_GNULIB_MDA_MEMCCPY@ +GL_GGL_GNULIB_MDA_MKDIR = @GL_GGL_GNULIB_MDA_MKDIR@ +GL_GGL_GNULIB_MDA_MKTEMP = @GL_GGL_GNULIB_MDA_MKTEMP@ +GL_GGL_GNULIB_MDA_OPEN = @GL_GGL_GNULIB_MDA_OPEN@ +GL_GGL_GNULIB_MDA_PUTENV = @GL_GGL_GNULIB_MDA_PUTENV@ +GL_GGL_GNULIB_MDA_PUTW = @GL_GGL_GNULIB_MDA_PUTW@ +GL_GGL_GNULIB_MDA_READ = @GL_GGL_GNULIB_MDA_READ@ +GL_GGL_GNULIB_MDA_RMDIR = @GL_GGL_GNULIB_MDA_RMDIR@ +GL_GGL_GNULIB_MDA_STRDUP = @GL_GGL_GNULIB_MDA_STRDUP@ +GL_GGL_GNULIB_MDA_SWAB = @GL_GGL_GNULIB_MDA_SWAB@ +GL_GGL_GNULIB_MDA_TEMPNAM = @GL_GGL_GNULIB_MDA_TEMPNAM@ +GL_GGL_GNULIB_MDA_TZSET = @GL_GGL_GNULIB_MDA_TZSET@ +GL_GGL_GNULIB_MDA_UMASK = @GL_GGL_GNULIB_MDA_UMASK@ +GL_GGL_GNULIB_MDA_UNLINK = @GL_GGL_GNULIB_MDA_UNLINK@ +GL_GGL_GNULIB_MDA_WCSDUP = @GL_GGL_GNULIB_MDA_WCSDUP@ +GL_GGL_GNULIB_MDA_WRITE = @GL_GGL_GNULIB_MDA_WRITE@ +GL_GGL_GNULIB_MEMCHR = @GL_GGL_GNULIB_MEMCHR@ +GL_GGL_GNULIB_MEMMEM = @GL_GGL_GNULIB_MEMMEM@ +GL_GGL_GNULIB_MEMPCPY = @GL_GGL_GNULIB_MEMPCPY@ +GL_GGL_GNULIB_MEMRCHR = @GL_GGL_GNULIB_MEMRCHR@ +GL_GGL_GNULIB_MKDIR = @GL_GGL_GNULIB_MKDIR@ +GL_GGL_GNULIB_MKDIRAT = @GL_GGL_GNULIB_MKDIRAT@ +GL_GGL_GNULIB_MKDTEMP = @GL_GGL_GNULIB_MKDTEMP@ +GL_GGL_GNULIB_MKFIFO = @GL_GGL_GNULIB_MKFIFO@ +GL_GGL_GNULIB_MKFIFOAT = @GL_GGL_GNULIB_MKFIFOAT@ +GL_GGL_GNULIB_MKNOD = @GL_GGL_GNULIB_MKNOD@ +GL_GGL_GNULIB_MKNODAT = @GL_GGL_GNULIB_MKNODAT@ +GL_GGL_GNULIB_MKOSTEMP = @GL_GGL_GNULIB_MKOSTEMP@ +GL_GGL_GNULIB_MKOSTEMPS = @GL_GGL_GNULIB_MKOSTEMPS@ +GL_GGL_GNULIB_MKSTEMP = @GL_GGL_GNULIB_MKSTEMP@ +GL_GGL_GNULIB_MKSTEMPS = @GL_GGL_GNULIB_MKSTEMPS@ +GL_GGL_GNULIB_MKTIME = @GL_GGL_GNULIB_MKTIME@ +GL_GGL_GNULIB_NANOSLEEP = @GL_GGL_GNULIB_NANOSLEEP@ +GL_GGL_GNULIB_NL_LANGINFO = @GL_GGL_GNULIB_NL_LANGINFO@ +GL_GGL_GNULIB_NONBLOCKING = @GL_GGL_GNULIB_NONBLOCKING@ +GL_GGL_GNULIB_OBSTACK_PRINTF = @GL_GGL_GNULIB_OBSTACK_PRINTF@ +GL_GGL_GNULIB_OBSTACK_PRINTF_POSIX = @GL_GGL_GNULIB_OBSTACK_PRINTF_POSIX@ +GL_GGL_GNULIB_OPEN = @GL_GGL_GNULIB_OPEN@ +GL_GGL_GNULIB_OPENAT = @GL_GGL_GNULIB_OPENAT@ +GL_GGL_GNULIB_OVERRIDES_STRUCT_STAT = @GL_GGL_GNULIB_OVERRIDES_STRUCT_STAT@ +GL_GGL_GNULIB_PCLOSE = @GL_GGL_GNULIB_PCLOSE@ +GL_GGL_GNULIB_PERROR = @GL_GGL_GNULIB_PERROR@ +GL_GGL_GNULIB_PIPE = @GL_GGL_GNULIB_PIPE@ +GL_GGL_GNULIB_PIPE2 = @GL_GGL_GNULIB_PIPE2@ +GL_GGL_GNULIB_POPEN = @GL_GGL_GNULIB_POPEN@ +GL_GGL_GNULIB_POSIX_MEMALIGN = @GL_GGL_GNULIB_POSIX_MEMALIGN@ +GL_GGL_GNULIB_POSIX_OPENPT = @GL_GGL_GNULIB_POSIX_OPENPT@ +GL_GGL_GNULIB_PREAD = @GL_GGL_GNULIB_PREAD@ +GL_GGL_GNULIB_PRINTF = @GL_GGL_GNULIB_PRINTF@ +GL_GGL_GNULIB_PRINTF_POSIX = @GL_GGL_GNULIB_PRINTF_POSIX@ +GL_GGL_GNULIB_PSELECT = @GL_GGL_GNULIB_PSELECT@ +GL_GGL_GNULIB_PTHREAD_COND = @GL_GGL_GNULIB_PTHREAD_COND@ +GL_GGL_GNULIB_PTHREAD_MUTEX = @GL_GGL_GNULIB_PTHREAD_MUTEX@ +GL_GGL_GNULIB_PTHREAD_MUTEX_TIMEDLOCK = @GL_GGL_GNULIB_PTHREAD_MUTEX_TIMEDLOCK@ +GL_GGL_GNULIB_PTHREAD_ONCE = @GL_GGL_GNULIB_PTHREAD_ONCE@ +GL_GGL_GNULIB_PTHREAD_RWLOCK = @GL_GGL_GNULIB_PTHREAD_RWLOCK@ +GL_GGL_GNULIB_PTHREAD_SIGMASK = @GL_GGL_GNULIB_PTHREAD_SIGMASK@ +GL_GGL_GNULIB_PTHREAD_SPIN = @GL_GGL_GNULIB_PTHREAD_SPIN@ +GL_GGL_GNULIB_PTHREAD_THREAD = @GL_GGL_GNULIB_PTHREAD_THREAD@ +GL_GGL_GNULIB_PTHREAD_TSS = @GL_GGL_GNULIB_PTHREAD_TSS@ +GL_GGL_GNULIB_PTSNAME = @GL_GGL_GNULIB_PTSNAME@ +GL_GGL_GNULIB_PTSNAME_R = @GL_GGL_GNULIB_PTSNAME_R@ +GL_GGL_GNULIB_PUTC = @GL_GGL_GNULIB_PUTC@ +GL_GGL_GNULIB_PUTCHAR = @GL_GGL_GNULIB_PUTCHAR@ +GL_GGL_GNULIB_PUTENV = @GL_GGL_GNULIB_PUTENV@ +GL_GGL_GNULIB_PUTS = @GL_GGL_GNULIB_PUTS@ +GL_GGL_GNULIB_PWRITE = @GL_GGL_GNULIB_PWRITE@ +GL_GGL_GNULIB_QSORT_R = @GL_GGL_GNULIB_QSORT_R@ +GL_GGL_GNULIB_RAISE = @GL_GGL_GNULIB_RAISE@ +GL_GGL_GNULIB_RANDOM = @GL_GGL_GNULIB_RANDOM@ +GL_GGL_GNULIB_RANDOM_R = @GL_GGL_GNULIB_RANDOM_R@ +GL_GGL_GNULIB_RAWMEMCHR = @GL_GGL_GNULIB_RAWMEMCHR@ +GL_GGL_GNULIB_READ = @GL_GGL_GNULIB_READ@ +GL_GGL_GNULIB_READLINK = @GL_GGL_GNULIB_READLINK@ +GL_GGL_GNULIB_READLINKAT = @GL_GGL_GNULIB_READLINKAT@ +GL_GGL_GNULIB_REALLOCARRAY = @GL_GGL_GNULIB_REALLOCARRAY@ +GL_GGL_GNULIB_REALLOC_POSIX = @GL_GGL_GNULIB_REALLOC_POSIX@ +GL_GGL_GNULIB_REALPATH = @GL_GGL_GNULIB_REALPATH@ +GL_GGL_GNULIB_RECV = @GL_GGL_GNULIB_RECV@ +GL_GGL_GNULIB_RECVFROM = @GL_GGL_GNULIB_RECVFROM@ +GL_GGL_GNULIB_REMOVE = @GL_GGL_GNULIB_REMOVE@ +GL_GGL_GNULIB_RENAME = @GL_GGL_GNULIB_RENAME@ +GL_GGL_GNULIB_RENAMEAT = @GL_GGL_GNULIB_RENAMEAT@ +GL_GGL_GNULIB_RMDIR = @GL_GGL_GNULIB_RMDIR@ +GL_GGL_GNULIB_RPMATCH = @GL_GGL_GNULIB_RPMATCH@ +GL_GGL_GNULIB_SCANF = @GL_GGL_GNULIB_SCANF@ +GL_GGL_GNULIB_SCHED_YIELD = @GL_GGL_GNULIB_SCHED_YIELD@ +GL_GGL_GNULIB_SECURE_GETENV = @GL_GGL_GNULIB_SECURE_GETENV@ +GL_GGL_GNULIB_SELECT = @GL_GGL_GNULIB_SELECT@ +GL_GGL_GNULIB_SEND = @GL_GGL_GNULIB_SEND@ +GL_GGL_GNULIB_SENDTO = @GL_GGL_GNULIB_SENDTO@ +GL_GGL_GNULIB_SETENV = @GL_GGL_GNULIB_SETENV@ +GL_GGL_GNULIB_SETHOSTNAME = @GL_GGL_GNULIB_SETHOSTNAME@ +GL_GGL_GNULIB_SETLOCALE = @GL_GGL_GNULIB_SETLOCALE@ +GL_GGL_GNULIB_SETLOCALE_NULL = @GL_GGL_GNULIB_SETLOCALE_NULL@ +GL_GGL_GNULIB_SETSOCKOPT = @GL_GGL_GNULIB_SETSOCKOPT@ +GL_GGL_GNULIB_SHUTDOWN = @GL_GGL_GNULIB_SHUTDOWN@ +GL_GGL_GNULIB_SIGABBREV_NP = @GL_GGL_GNULIB_SIGABBREV_NP@ +GL_GGL_GNULIB_SIGACTION = @GL_GGL_GNULIB_SIGACTION@ +GL_GGL_GNULIB_SIGDESCR_NP = @GL_GGL_GNULIB_SIGDESCR_NP@ +GL_GGL_GNULIB_SIGNAL_H_SIGPIPE = @GL_GGL_GNULIB_SIGNAL_H_SIGPIPE@ +GL_GGL_GNULIB_SIGPROCMASK = @GL_GGL_GNULIB_SIGPROCMASK@ +GL_GGL_GNULIB_SLEEP = @GL_GGL_GNULIB_SLEEP@ +GL_GGL_GNULIB_SNPRINTF = @GL_GGL_GNULIB_SNPRINTF@ +GL_GGL_GNULIB_SOCKET = @GL_GGL_GNULIB_SOCKET@ +GL_GGL_GNULIB_SPRINTF_POSIX = @GL_GGL_GNULIB_SPRINTF_POSIX@ +GL_GGL_GNULIB_STAT = @GL_GGL_GNULIB_STAT@ +GL_GGL_GNULIB_STDIO_H_NONBLOCKING = @GL_GGL_GNULIB_STDIO_H_NONBLOCKING@ +GL_GGL_GNULIB_STDIO_H_SIGPIPE = @GL_GGL_GNULIB_STDIO_H_SIGPIPE@ +GL_GGL_GNULIB_STPCPY = @GL_GGL_GNULIB_STPCPY@ +GL_GGL_GNULIB_STPNCPY = @GL_GGL_GNULIB_STPNCPY@ +GL_GGL_GNULIB_STRCASESTR = @GL_GGL_GNULIB_STRCASESTR@ +GL_GGL_GNULIB_STRCHRNUL = @GL_GGL_GNULIB_STRCHRNUL@ +GL_GGL_GNULIB_STRDUP = @GL_GGL_GNULIB_STRDUP@ +GL_GGL_GNULIB_STRERROR = @GL_GGL_GNULIB_STRERROR@ +GL_GGL_GNULIB_STRERRORNAME_NP = @GL_GGL_GNULIB_STRERRORNAME_NP@ +GL_GGL_GNULIB_STRERROR_R = @GL_GGL_GNULIB_STRERROR_R@ +GL_GGL_GNULIB_STRFTIME = @GL_GGL_GNULIB_STRFTIME@ +GL_GGL_GNULIB_STRNCAT = @GL_GGL_GNULIB_STRNCAT@ +GL_GGL_GNULIB_STRNDUP = @GL_GGL_GNULIB_STRNDUP@ +GL_GGL_GNULIB_STRNLEN = @GL_GGL_GNULIB_STRNLEN@ +GL_GGL_GNULIB_STRPBRK = @GL_GGL_GNULIB_STRPBRK@ +GL_GGL_GNULIB_STRPTIME = @GL_GGL_GNULIB_STRPTIME@ +GL_GGL_GNULIB_STRSEP = @GL_GGL_GNULIB_STRSEP@ +GL_GGL_GNULIB_STRSIGNAL = @GL_GGL_GNULIB_STRSIGNAL@ +GL_GGL_GNULIB_STRSTR = @GL_GGL_GNULIB_STRSTR@ +GL_GGL_GNULIB_STRTOD = @GL_GGL_GNULIB_STRTOD@ +GL_GGL_GNULIB_STRTOIMAX = @GL_GGL_GNULIB_STRTOIMAX@ +GL_GGL_GNULIB_STRTOK_R = @GL_GGL_GNULIB_STRTOK_R@ +GL_GGL_GNULIB_STRTOL = @GL_GGL_GNULIB_STRTOL@ +GL_GGL_GNULIB_STRTOLD = @GL_GGL_GNULIB_STRTOLD@ +GL_GGL_GNULIB_STRTOLL = @GL_GGL_GNULIB_STRTOLL@ +GL_GGL_GNULIB_STRTOUL = @GL_GGL_GNULIB_STRTOUL@ +GL_GGL_GNULIB_STRTOULL = @GL_GGL_GNULIB_STRTOULL@ +GL_GGL_GNULIB_STRTOUMAX = @GL_GGL_GNULIB_STRTOUMAX@ +GL_GGL_GNULIB_STRVERSCMP = @GL_GGL_GNULIB_STRVERSCMP@ +GL_GGL_GNULIB_SYMLINK = @GL_GGL_GNULIB_SYMLINK@ +GL_GGL_GNULIB_SYMLINKAT = @GL_GGL_GNULIB_SYMLINKAT@ +GL_GGL_GNULIB_SYSTEM_POSIX = @GL_GGL_GNULIB_SYSTEM_POSIX@ +GL_GGL_GNULIB_TIMEGM = @GL_GGL_GNULIB_TIMEGM@ +GL_GGL_GNULIB_TIMESPEC_GET = @GL_GGL_GNULIB_TIMESPEC_GET@ +GL_GGL_GNULIB_TIME_R = @GL_GGL_GNULIB_TIME_R@ +GL_GGL_GNULIB_TIME_RZ = @GL_GGL_GNULIB_TIME_RZ@ +GL_GGL_GNULIB_TMPFILE = @GL_GGL_GNULIB_TMPFILE@ +GL_GGL_GNULIB_TRUNCATE = @GL_GGL_GNULIB_TRUNCATE@ +GL_GGL_GNULIB_TTYNAME_R = @GL_GGL_GNULIB_TTYNAME_R@ +GL_GGL_GNULIB_TZSET = @GL_GGL_GNULIB_TZSET@ +GL_GGL_GNULIB_UNISTD_H_NONBLOCKING = @GL_GGL_GNULIB_UNISTD_H_NONBLOCKING@ +GL_GGL_GNULIB_UNISTD_H_SIGPIPE = @GL_GGL_GNULIB_UNISTD_H_SIGPIPE@ +GL_GGL_GNULIB_UNLINK = @GL_GGL_GNULIB_UNLINK@ +GL_GGL_GNULIB_UNLINKAT = @GL_GGL_GNULIB_UNLINKAT@ +GL_GGL_GNULIB_UNLOCKPT = @GL_GGL_GNULIB_UNLOCKPT@ +GL_GGL_GNULIB_UNSETENV = @GL_GGL_GNULIB_UNSETENV@ +GL_GGL_GNULIB_USLEEP = @GL_GGL_GNULIB_USLEEP@ +GL_GGL_GNULIB_UTIMENSAT = @GL_GGL_GNULIB_UTIMENSAT@ +GL_GGL_GNULIB_VASPRINTF = @GL_GGL_GNULIB_VASPRINTF@ +GL_GGL_GNULIB_VDPRINTF = @GL_GGL_GNULIB_VDPRINTF@ +GL_GGL_GNULIB_VFPRINTF = @GL_GGL_GNULIB_VFPRINTF@ +GL_GGL_GNULIB_VFPRINTF_POSIX = @GL_GGL_GNULIB_VFPRINTF_POSIX@ +GL_GGL_GNULIB_VFSCANF = @GL_GGL_GNULIB_VFSCANF@ +GL_GGL_GNULIB_VPRINTF = @GL_GGL_GNULIB_VPRINTF@ +GL_GGL_GNULIB_VPRINTF_POSIX = @GL_GGL_GNULIB_VPRINTF_POSIX@ +GL_GGL_GNULIB_VSCANF = @GL_GGL_GNULIB_VSCANF@ +GL_GGL_GNULIB_VSNPRINTF = @GL_GGL_GNULIB_VSNPRINTF@ +GL_GGL_GNULIB_VSPRINTF_POSIX = @GL_GGL_GNULIB_VSPRINTF_POSIX@ +GL_GGL_GNULIB_WCPCPY = @GL_GGL_GNULIB_WCPCPY@ +GL_GGL_GNULIB_WCPNCPY = @GL_GGL_GNULIB_WCPNCPY@ +GL_GGL_GNULIB_WCRTOMB = @GL_GGL_GNULIB_WCRTOMB@ +GL_GGL_GNULIB_WCSCASECMP = @GL_GGL_GNULIB_WCSCASECMP@ +GL_GGL_GNULIB_WCSCAT = @GL_GGL_GNULIB_WCSCAT@ +GL_GGL_GNULIB_WCSCHR = @GL_GGL_GNULIB_WCSCHR@ +GL_GGL_GNULIB_WCSCMP = @GL_GGL_GNULIB_WCSCMP@ +GL_GGL_GNULIB_WCSCOLL = @GL_GGL_GNULIB_WCSCOLL@ +GL_GGL_GNULIB_WCSCPY = @GL_GGL_GNULIB_WCSCPY@ +GL_GGL_GNULIB_WCSCSPN = @GL_GGL_GNULIB_WCSCSPN@ +GL_GGL_GNULIB_WCSDUP = @GL_GGL_GNULIB_WCSDUP@ +GL_GGL_GNULIB_WCSFTIME = @GL_GGL_GNULIB_WCSFTIME@ +GL_GGL_GNULIB_WCSLEN = @GL_GGL_GNULIB_WCSLEN@ +GL_GGL_GNULIB_WCSNCASECMP = @GL_GGL_GNULIB_WCSNCASECMP@ +GL_GGL_GNULIB_WCSNCAT = @GL_GGL_GNULIB_WCSNCAT@ +GL_GGL_GNULIB_WCSNCMP = @GL_GGL_GNULIB_WCSNCMP@ +GL_GGL_GNULIB_WCSNCPY = @GL_GGL_GNULIB_WCSNCPY@ +GL_GGL_GNULIB_WCSNLEN = @GL_GGL_GNULIB_WCSNLEN@ +GL_GGL_GNULIB_WCSNRTOMBS = @GL_GGL_GNULIB_WCSNRTOMBS@ +GL_GGL_GNULIB_WCSPBRK = @GL_GGL_GNULIB_WCSPBRK@ +GL_GGL_GNULIB_WCSRCHR = @GL_GGL_GNULIB_WCSRCHR@ +GL_GGL_GNULIB_WCSRTOMBS = @GL_GGL_GNULIB_WCSRTOMBS@ +GL_GGL_GNULIB_WCSSPN = @GL_GGL_GNULIB_WCSSPN@ +GL_GGL_GNULIB_WCSSTR = @GL_GGL_GNULIB_WCSSTR@ +GL_GGL_GNULIB_WCSTOK = @GL_GGL_GNULIB_WCSTOK@ +GL_GGL_GNULIB_WCSWIDTH = @GL_GGL_GNULIB_WCSWIDTH@ +GL_GGL_GNULIB_WCSXFRM = @GL_GGL_GNULIB_WCSXFRM@ +GL_GGL_GNULIB_WCTOB = @GL_GGL_GNULIB_WCTOB@ +GL_GGL_GNULIB_WCTOMB = @GL_GGL_GNULIB_WCTOMB@ +GL_GGL_GNULIB_WCWIDTH = @GL_GGL_GNULIB_WCWIDTH@ +GL_GGL_GNULIB_WMEMCHR = @GL_GGL_GNULIB_WMEMCHR@ +GL_GGL_GNULIB_WMEMCMP = @GL_GGL_GNULIB_WMEMCMP@ +GL_GGL_GNULIB_WMEMCPY = @GL_GGL_GNULIB_WMEMCPY@ +GL_GGL_GNULIB_WMEMMOVE = @GL_GGL_GNULIB_WMEMMOVE@ +GL_GGL_GNULIB_WMEMPCPY = @GL_GGL_GNULIB_WMEMPCPY@ +GL_GGL_GNULIB_WMEMSET = @GL_GGL_GNULIB_WMEMSET@ +GL_GGL_GNULIB_WRITE = @GL_GGL_GNULIB_WRITE@ +GL_GGL_GNULIB__EXIT = @GL_GGL_GNULIB__EXIT@ +GL_GNULIB_ACCEPT = @GL_GNULIB_ACCEPT@ +GL_GNULIB_ACCEPT4 = @GL_GNULIB_ACCEPT4@ +GL_GNULIB_ACCESS = @GL_GNULIB_ACCESS@ +GL_GNULIB_ALIGNED_ALLOC = @GL_GNULIB_ALIGNED_ALLOC@ +GL_GNULIB_ATOLL = @GL_GNULIB_ATOLL@ +GL_GNULIB_BIND = @GL_GNULIB_BIND@ +GL_GNULIB_BTOWC = @GL_GNULIB_BTOWC@ +GL_GNULIB_CALLOC_POSIX = @GL_GNULIB_CALLOC_POSIX@ +GL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GNULIB_CANONICALIZE_FILE_NAME@ +GL_GNULIB_CHDIR = @GL_GNULIB_CHDIR@ +GL_GNULIB_CHOWN = @GL_GNULIB_CHOWN@ +GL_GNULIB_CLOSE = @GL_GNULIB_CLOSE@ +GL_GNULIB_CONNECT = @GL_GNULIB_CONNECT@ +GL_GNULIB_COPY_FILE_RANGE = @GL_GNULIB_COPY_FILE_RANGE@ +GL_GNULIB_CREAT = @GL_GNULIB_CREAT@ +GL_GNULIB_CTIME = @GL_GNULIB_CTIME@ +GL_GNULIB_DPRINTF = @GL_GNULIB_DPRINTF@ +GL_GNULIB_DUP = @GL_GNULIB_DUP@ +GL_GNULIB_DUP2 = @GL_GNULIB_DUP2@ +GL_GNULIB_DUP3 = @GL_GNULIB_DUP3@ +GL_GNULIB_ENVIRON = @GL_GNULIB_ENVIRON@ +GL_GNULIB_EUIDACCESS = @GL_GNULIB_EUIDACCESS@ +GL_GNULIB_EXECL = @GL_GNULIB_EXECL@ +GL_GNULIB_EXECLE = @GL_GNULIB_EXECLE@ +GL_GNULIB_EXECLP = @GL_GNULIB_EXECLP@ +GL_GNULIB_EXECV = @GL_GNULIB_EXECV@ +GL_GNULIB_EXECVE = @GL_GNULIB_EXECVE@ +GL_GNULIB_EXECVP = @GL_GNULIB_EXECVP@ +GL_GNULIB_EXECVPE = @GL_GNULIB_EXECVPE@ +GL_GNULIB_EXPLICIT_BZERO = @GL_GNULIB_EXPLICIT_BZERO@ +GL_GNULIB_FACCESSAT = @GL_GNULIB_FACCESSAT@ +GL_GNULIB_FCHDIR = @GL_GNULIB_FCHDIR@ +GL_GNULIB_FCHMODAT = @GL_GNULIB_FCHMODAT@ +GL_GNULIB_FCHOWNAT = @GL_GNULIB_FCHOWNAT@ +GL_GNULIB_FCLOSE = @GL_GNULIB_FCLOSE@ +GL_GNULIB_FCNTL = @GL_GNULIB_FCNTL@ +GL_GNULIB_FDATASYNC = @GL_GNULIB_FDATASYNC@ +GL_GNULIB_FDOPEN = @GL_GNULIB_FDOPEN@ +GL_GNULIB_FFLUSH = @GL_GNULIB_FFLUSH@ +GL_GNULIB_FFS = @GL_GNULIB_FFS@ +GL_GNULIB_FFSL = @GL_GNULIB_FFSL@ +GL_GNULIB_FFSLL = @GL_GNULIB_FFSLL@ +GL_GNULIB_FGETC = @GL_GNULIB_FGETC@ +GL_GNULIB_FGETS = @GL_GNULIB_FGETS@ +GL_GNULIB_FOPEN = @GL_GNULIB_FOPEN@ +GL_GNULIB_FPRINTF = @GL_GNULIB_FPRINTF@ +GL_GNULIB_FPRINTF_POSIX = @GL_GNULIB_FPRINTF_POSIX@ +GL_GNULIB_FPURGE = @GL_GNULIB_FPURGE@ +GL_GNULIB_FPUTC = @GL_GNULIB_FPUTC@ +GL_GNULIB_FPUTS = @GL_GNULIB_FPUTS@ +GL_GNULIB_FREAD = @GL_GNULIB_FREAD@ +GL_GNULIB_FREE_POSIX = @GL_GNULIB_FREE_POSIX@ +GL_GNULIB_FREOPEN = @GL_GNULIB_FREOPEN@ +GL_GNULIB_FSCANF = @GL_GNULIB_FSCANF@ +GL_GNULIB_FSEEK = @GL_GNULIB_FSEEK@ +GL_GNULIB_FSEEKO = @GL_GNULIB_FSEEKO@ +GL_GNULIB_FSTAT = @GL_GNULIB_FSTAT@ +GL_GNULIB_FSTATAT = @GL_GNULIB_FSTATAT@ +GL_GNULIB_FSYNC = @GL_GNULIB_FSYNC@ +GL_GNULIB_FTELL = @GL_GNULIB_FTELL@ +GL_GNULIB_FTELLO = @GL_GNULIB_FTELLO@ +GL_GNULIB_FTRUNCATE = @GL_GNULIB_FTRUNCATE@ +GL_GNULIB_FUTIMENS = @GL_GNULIB_FUTIMENS@ +GL_GNULIB_FWRITE = @GL_GNULIB_FWRITE@ +GL_GNULIB_GETADDRINFO = @GL_GNULIB_GETADDRINFO@ +GL_GNULIB_GETC = @GL_GNULIB_GETC@ +GL_GNULIB_GETCHAR = @GL_GNULIB_GETCHAR@ +GL_GNULIB_GETCWD = @GL_GNULIB_GETCWD@ +GL_GNULIB_GETDELIM = @GL_GNULIB_GETDELIM@ +GL_GNULIB_GETDOMAINNAME = @GL_GNULIB_GETDOMAINNAME@ +GL_GNULIB_GETDTABLESIZE = @GL_GNULIB_GETDTABLESIZE@ +GL_GNULIB_GETENTROPY = @GL_GNULIB_GETENTROPY@ +GL_GNULIB_GETGROUPS = @GL_GNULIB_GETGROUPS@ +GL_GNULIB_GETHOSTNAME = @GL_GNULIB_GETHOSTNAME@ +GL_GNULIB_GETLINE = @GL_GNULIB_GETLINE@ +GL_GNULIB_GETLOADAVG = @GL_GNULIB_GETLOADAVG@ +GL_GNULIB_GETLOGIN = @GL_GNULIB_GETLOGIN@ +GL_GNULIB_GETLOGIN_R = @GL_GNULIB_GETLOGIN_R@ +GL_GNULIB_GETOPT_POSIX = @GL_GNULIB_GETOPT_POSIX@ +GL_GNULIB_GETPAGESIZE = @GL_GNULIB_GETPAGESIZE@ +GL_GNULIB_GETPASS = @GL_GNULIB_GETPASS@ +GL_GNULIB_GETPEERNAME = @GL_GNULIB_GETPEERNAME@ +GL_GNULIB_GETSOCKNAME = @GL_GNULIB_GETSOCKNAME@ +GL_GNULIB_GETSOCKOPT = @GL_GNULIB_GETSOCKOPT@ +GL_GNULIB_GETSUBOPT = @GL_GNULIB_GETSUBOPT@ +GL_GNULIB_GETTIMEOFDAY = @GL_GNULIB_GETTIMEOFDAY@ +GL_GNULIB_GETUMASK = @GL_GNULIB_GETUMASK@ +GL_GNULIB_GETUSERSHELL = @GL_GNULIB_GETUSERSHELL@ +GL_GNULIB_GRANTPT = @GL_GNULIB_GRANTPT@ +GL_GNULIB_GROUP_MEMBER = @GL_GNULIB_GROUP_MEMBER@ +GL_GNULIB_IMAXABS = @GL_GNULIB_IMAXABS@ +GL_GNULIB_IMAXDIV = @GL_GNULIB_IMAXDIV@ +GL_GNULIB_INET_NTOP = @GL_GNULIB_INET_NTOP@ +GL_GNULIB_INET_PTON = @GL_GNULIB_INET_PTON@ +GL_GNULIB_ISATTY = @GL_GNULIB_ISATTY@ +GL_GNULIB_LCHMOD = @GL_GNULIB_LCHMOD@ +GL_GNULIB_LCHOWN = @GL_GNULIB_LCHOWN@ +GL_GNULIB_LINK = @GL_GNULIB_LINK@ +GL_GNULIB_LINKAT = @GL_GNULIB_LINKAT@ +GL_GNULIB_LISTEN = @GL_GNULIB_LISTEN@ +GL_GNULIB_LOCALTIME = @GL_GNULIB_LOCALTIME@ +GL_GNULIB_LSEEK = @GL_GNULIB_LSEEK@ +GL_GNULIB_LSTAT = @GL_GNULIB_LSTAT@ +GL_GNULIB_MALLOC_POSIX = @GL_GNULIB_MALLOC_POSIX@ +GL_GNULIB_MBRLEN = @GL_GNULIB_MBRLEN@ +GL_GNULIB_MBRTOWC = @GL_GNULIB_MBRTOWC@ +GL_GNULIB_MBSCASECMP = @GL_GNULIB_MBSCASECMP@ +GL_GNULIB_MBSCASESTR = @GL_GNULIB_MBSCASESTR@ +GL_GNULIB_MBSCHR = @GL_GNULIB_MBSCHR@ +GL_GNULIB_MBSCSPN = @GL_GNULIB_MBSCSPN@ +GL_GNULIB_MBSINIT = @GL_GNULIB_MBSINIT@ +GL_GNULIB_MBSLEN = @GL_GNULIB_MBSLEN@ +GL_GNULIB_MBSNCASECMP = @GL_GNULIB_MBSNCASECMP@ +GL_GNULIB_MBSNLEN = @GL_GNULIB_MBSNLEN@ +GL_GNULIB_MBSNRTOWCS = @GL_GNULIB_MBSNRTOWCS@ +GL_GNULIB_MBSPBRK = @GL_GNULIB_MBSPBRK@ +GL_GNULIB_MBSPCASECMP = @GL_GNULIB_MBSPCASECMP@ +GL_GNULIB_MBSRCHR = @GL_GNULIB_MBSRCHR@ +GL_GNULIB_MBSRTOWCS = @GL_GNULIB_MBSRTOWCS@ +GL_GNULIB_MBSSEP = @GL_GNULIB_MBSSEP@ +GL_GNULIB_MBSSPN = @GL_GNULIB_MBSSPN@ +GL_GNULIB_MBSSTR = @GL_GNULIB_MBSSTR@ +GL_GNULIB_MBSTOK_R = @GL_GNULIB_MBSTOK_R@ +GL_GNULIB_MBTOWC = @GL_GNULIB_MBTOWC@ +GL_GNULIB_MDA_ACCESS = @GL_GNULIB_MDA_ACCESS@ +GL_GNULIB_MDA_CHDIR = @GL_GNULIB_MDA_CHDIR@ +GL_GNULIB_MDA_CHMOD = @GL_GNULIB_MDA_CHMOD@ +GL_GNULIB_MDA_CLOSE = @GL_GNULIB_MDA_CLOSE@ +GL_GNULIB_MDA_CREAT = @GL_GNULIB_MDA_CREAT@ +GL_GNULIB_MDA_DUP = @GL_GNULIB_MDA_DUP@ +GL_GNULIB_MDA_DUP2 = @GL_GNULIB_MDA_DUP2@ +GL_GNULIB_MDA_ECVT = @GL_GNULIB_MDA_ECVT@ +GL_GNULIB_MDA_EXECL = @GL_GNULIB_MDA_EXECL@ +GL_GNULIB_MDA_EXECLE = @GL_GNULIB_MDA_EXECLE@ +GL_GNULIB_MDA_EXECLP = @GL_GNULIB_MDA_EXECLP@ +GL_GNULIB_MDA_EXECV = @GL_GNULIB_MDA_EXECV@ +GL_GNULIB_MDA_EXECVE = @GL_GNULIB_MDA_EXECVE@ +GL_GNULIB_MDA_EXECVP = @GL_GNULIB_MDA_EXECVP@ +GL_GNULIB_MDA_EXECVPE = @GL_GNULIB_MDA_EXECVPE@ +GL_GNULIB_MDA_FCLOSEALL = @GL_GNULIB_MDA_FCLOSEALL@ +GL_GNULIB_MDA_FCVT = @GL_GNULIB_MDA_FCVT@ +GL_GNULIB_MDA_FDOPEN = @GL_GNULIB_MDA_FDOPEN@ +GL_GNULIB_MDA_FILENO = @GL_GNULIB_MDA_FILENO@ +GL_GNULIB_MDA_GCVT = @GL_GNULIB_MDA_GCVT@ +GL_GNULIB_MDA_GETCWD = @GL_GNULIB_MDA_GETCWD@ +GL_GNULIB_MDA_GETPID = @GL_GNULIB_MDA_GETPID@ +GL_GNULIB_MDA_GETW = @GL_GNULIB_MDA_GETW@ +GL_GNULIB_MDA_ISATTY = @GL_GNULIB_MDA_ISATTY@ +GL_GNULIB_MDA_LSEEK = @GL_GNULIB_MDA_LSEEK@ +GL_GNULIB_MDA_MEMCCPY = @GL_GNULIB_MDA_MEMCCPY@ +GL_GNULIB_MDA_MKDIR = @GL_GNULIB_MDA_MKDIR@ +GL_GNULIB_MDA_MKTEMP = @GL_GNULIB_MDA_MKTEMP@ +GL_GNULIB_MDA_OPEN = @GL_GNULIB_MDA_OPEN@ +GL_GNULIB_MDA_PUTENV = @GL_GNULIB_MDA_PUTENV@ +GL_GNULIB_MDA_PUTW = @GL_GNULIB_MDA_PUTW@ +GL_GNULIB_MDA_READ = @GL_GNULIB_MDA_READ@ +GL_GNULIB_MDA_RMDIR = @GL_GNULIB_MDA_RMDIR@ +GL_GNULIB_MDA_STRDUP = @GL_GNULIB_MDA_STRDUP@ +GL_GNULIB_MDA_SWAB = @GL_GNULIB_MDA_SWAB@ +GL_GNULIB_MDA_TEMPNAM = @GL_GNULIB_MDA_TEMPNAM@ +GL_GNULIB_MDA_TZSET = @GL_GNULIB_MDA_TZSET@ +GL_GNULIB_MDA_UMASK = @GL_GNULIB_MDA_UMASK@ +GL_GNULIB_MDA_UNLINK = @GL_GNULIB_MDA_UNLINK@ +GL_GNULIB_MDA_WCSDUP = @GL_GNULIB_MDA_WCSDUP@ +GL_GNULIB_MDA_WRITE = @GL_GNULIB_MDA_WRITE@ +GL_GNULIB_MEMCHR = @GL_GNULIB_MEMCHR@ +GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@ +GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@ +GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@ +GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@ +GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@ +GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@ +GL_GNULIB_MKFIFO = @GL_GNULIB_MKFIFO@ +GL_GNULIB_MKFIFOAT = @GL_GNULIB_MKFIFOAT@ +GL_GNULIB_MKNOD = @GL_GNULIB_MKNOD@ +GL_GNULIB_MKNODAT = @GL_GNULIB_MKNODAT@ +GL_GNULIB_MKOSTEMP = @GL_GNULIB_MKOSTEMP@ +GL_GNULIB_MKOSTEMPS = @GL_GNULIB_MKOSTEMPS@ +GL_GNULIB_MKSTEMP = @GL_GNULIB_MKSTEMP@ +GL_GNULIB_MKSTEMPS = @GL_GNULIB_MKSTEMPS@ +GL_GNULIB_MKTIME = @GL_GNULIB_MKTIME@ +GL_GNULIB_NANOSLEEP = @GL_GNULIB_NANOSLEEP@ +GL_GNULIB_NONBLOCKING = @GL_GNULIB_NONBLOCKING@ +GL_GNULIB_OBSTACK_PRINTF = @GL_GNULIB_OBSTACK_PRINTF@ +GL_GNULIB_OBSTACK_PRINTF_POSIX = @GL_GNULIB_OBSTACK_PRINTF_POSIX@ +GL_GNULIB_OPEN = @GL_GNULIB_OPEN@ +GL_GNULIB_OPENAT = @GL_GNULIB_OPENAT@ +GL_GNULIB_OVERRIDES_STRUCT_STAT = @GL_GNULIB_OVERRIDES_STRUCT_STAT@ +GL_GNULIB_PCLOSE = @GL_GNULIB_PCLOSE@ +GL_GNULIB_PERROR = @GL_GNULIB_PERROR@ +GL_GNULIB_PIPE = @GL_GNULIB_PIPE@ +GL_GNULIB_PIPE2 = @GL_GNULIB_PIPE2@ +GL_GNULIB_POPEN = @GL_GNULIB_POPEN@ +GL_GNULIB_POSIX_MEMALIGN = @GL_GNULIB_POSIX_MEMALIGN@ +GL_GNULIB_POSIX_OPENPT = @GL_GNULIB_POSIX_OPENPT@ +GL_GNULIB_PREAD = @GL_GNULIB_PREAD@ +GL_GNULIB_PRINTF = @GL_GNULIB_PRINTF@ +GL_GNULIB_PRINTF_POSIX = @GL_GNULIB_PRINTF_POSIX@ +GL_GNULIB_PTSNAME = @GL_GNULIB_PTSNAME@ +GL_GNULIB_PTSNAME_R = @GL_GNULIB_PTSNAME_R@ +GL_GNULIB_PUTC = @GL_GNULIB_PUTC@ +GL_GNULIB_PUTCHAR = @GL_GNULIB_PUTCHAR@ +GL_GNULIB_PUTENV = @GL_GNULIB_PUTENV@ +GL_GNULIB_PUTS = @GL_GNULIB_PUTS@ +GL_GNULIB_PWRITE = @GL_GNULIB_PWRITE@ +GL_GNULIB_QSORT_R = @GL_GNULIB_QSORT_R@ +GL_GNULIB_RANDOM = @GL_GNULIB_RANDOM@ +GL_GNULIB_RANDOM_R = @GL_GNULIB_RANDOM_R@ +GL_GNULIB_RAWMEMCHR = @GL_GNULIB_RAWMEMCHR@ +GL_GNULIB_READ = @GL_GNULIB_READ@ +GL_GNULIB_READLINK = @GL_GNULIB_READLINK@ +GL_GNULIB_READLINKAT = @GL_GNULIB_READLINKAT@ +GL_GNULIB_REALLOCARRAY = @GL_GNULIB_REALLOCARRAY@ +GL_GNULIB_REALLOC_POSIX = @GL_GNULIB_REALLOC_POSIX@ +GL_GNULIB_REALPATH = @GL_GNULIB_REALPATH@ +GL_GNULIB_RECV = @GL_GNULIB_RECV@ +GL_GNULIB_RECVFROM = @GL_GNULIB_RECVFROM@ +GL_GNULIB_REMOVE = @GL_GNULIB_REMOVE@ +GL_GNULIB_RENAME = @GL_GNULIB_RENAME@ +GL_GNULIB_RENAMEAT = @GL_GNULIB_RENAMEAT@ +GL_GNULIB_RMDIR = @GL_GNULIB_RMDIR@ +GL_GNULIB_RPMATCH = @GL_GNULIB_RPMATCH@ +GL_GNULIB_SCANF = @GL_GNULIB_SCANF@ +GL_GNULIB_SECURE_GETENV = @GL_GNULIB_SECURE_GETENV@ +GL_GNULIB_SEND = @GL_GNULIB_SEND@ +GL_GNULIB_SENDTO = @GL_GNULIB_SENDTO@ +GL_GNULIB_SETENV = @GL_GNULIB_SETENV@ +GL_GNULIB_SETHOSTNAME = @GL_GNULIB_SETHOSTNAME@ +GL_GNULIB_SETSOCKOPT = @GL_GNULIB_SETSOCKOPT@ +GL_GNULIB_SHUTDOWN = @GL_GNULIB_SHUTDOWN@ +GL_GNULIB_SIGABBREV_NP = @GL_GNULIB_SIGABBREV_NP@ +GL_GNULIB_SIGDESCR_NP = @GL_GNULIB_SIGDESCR_NP@ +GL_GNULIB_SLEEP = @GL_GNULIB_SLEEP@ +GL_GNULIB_SNPRINTF = @GL_GNULIB_SNPRINTF@ +GL_GNULIB_SOCKET = @GL_GNULIB_SOCKET@ +GL_GNULIB_SPRINTF_POSIX = @GL_GNULIB_SPRINTF_POSIX@ +GL_GNULIB_STAT = @GL_GNULIB_STAT@ +GL_GNULIB_STDIO_H_NONBLOCKING = @GL_GNULIB_STDIO_H_NONBLOCKING@ +GL_GNULIB_STDIO_H_SIGPIPE = @GL_GNULIB_STDIO_H_SIGPIPE@ +GL_GNULIB_STPCPY = @GL_GNULIB_STPCPY@ +GL_GNULIB_STPNCPY = @GL_GNULIB_STPNCPY@ +GL_GNULIB_STRCASESTR = @GL_GNULIB_STRCASESTR@ +GL_GNULIB_STRCHRNUL = @GL_GNULIB_STRCHRNUL@ +GL_GNULIB_STRDUP = @GL_GNULIB_STRDUP@ +GL_GNULIB_STRERROR = @GL_GNULIB_STRERROR@ +GL_GNULIB_STRERRORNAME_NP = @GL_GNULIB_STRERRORNAME_NP@ +GL_GNULIB_STRERROR_R = @GL_GNULIB_STRERROR_R@ +GL_GNULIB_STRFTIME = @GL_GNULIB_STRFTIME@ +GL_GNULIB_STRNCAT = @GL_GNULIB_STRNCAT@ +GL_GNULIB_STRNDUP = @GL_GNULIB_STRNDUP@ +GL_GNULIB_STRNLEN = @GL_GNULIB_STRNLEN@ +GL_GNULIB_STRPBRK = @GL_GNULIB_STRPBRK@ +GL_GNULIB_STRPTIME = @GL_GNULIB_STRPTIME@ +GL_GNULIB_STRSEP = @GL_GNULIB_STRSEP@ +GL_GNULIB_STRSIGNAL = @GL_GNULIB_STRSIGNAL@ +GL_GNULIB_STRSTR = @GL_GNULIB_STRSTR@ +GL_GNULIB_STRTOD = @GL_GNULIB_STRTOD@ +GL_GNULIB_STRTOIMAX = @GL_GNULIB_STRTOIMAX@ +GL_GNULIB_STRTOK_R = @GL_GNULIB_STRTOK_R@ +GL_GNULIB_STRTOL = @GL_GNULIB_STRTOL@ +GL_GNULIB_STRTOLD = @GL_GNULIB_STRTOLD@ +GL_GNULIB_STRTOLL = @GL_GNULIB_STRTOLL@ +GL_GNULIB_STRTOUL = @GL_GNULIB_STRTOUL@ +GL_GNULIB_STRTOULL = @GL_GNULIB_STRTOULL@ +GL_GNULIB_STRTOUMAX = @GL_GNULIB_STRTOUMAX@ +GL_GNULIB_STRVERSCMP = @GL_GNULIB_STRVERSCMP@ +GL_GNULIB_SYMLINK = @GL_GNULIB_SYMLINK@ +GL_GNULIB_SYMLINKAT = @GL_GNULIB_SYMLINKAT@ +GL_GNULIB_SYSTEM_POSIX = @GL_GNULIB_SYSTEM_POSIX@ +GL_GNULIB_TIMEGM = @GL_GNULIB_TIMEGM@ +GL_GNULIB_TIMESPEC_GET = @GL_GNULIB_TIMESPEC_GET@ +GL_GNULIB_TIME_R = @GL_GNULIB_TIME_R@ +GL_GNULIB_TIME_RZ = @GL_GNULIB_TIME_RZ@ +GL_GNULIB_TMPFILE = @GL_GNULIB_TMPFILE@ +GL_GNULIB_TRUNCATE = @GL_GNULIB_TRUNCATE@ +GL_GNULIB_TTYNAME_R = @GL_GNULIB_TTYNAME_R@ +GL_GNULIB_TZSET = @GL_GNULIB_TZSET@ +GL_GNULIB_UNISTD_H_NONBLOCKING = @GL_GNULIB_UNISTD_H_NONBLOCKING@ +GL_GNULIB_UNISTD_H_SIGPIPE = @GL_GNULIB_UNISTD_H_SIGPIPE@ +GL_GNULIB_UNLINK = @GL_GNULIB_UNLINK@ +GL_GNULIB_UNLINKAT = @GL_GNULIB_UNLINKAT@ +GL_GNULIB_UNLOCKPT = @GL_GNULIB_UNLOCKPT@ +GL_GNULIB_UNSETENV = @GL_GNULIB_UNSETENV@ +GL_GNULIB_USLEEP = @GL_GNULIB_USLEEP@ +GL_GNULIB_UTIMENSAT = @GL_GNULIB_UTIMENSAT@ +GL_GNULIB_VASPRINTF = @GL_GNULIB_VASPRINTF@ +GL_GNULIB_VDPRINTF = @GL_GNULIB_VDPRINTF@ +GL_GNULIB_VFPRINTF = @GL_GNULIB_VFPRINTF@ +GL_GNULIB_VFPRINTF_POSIX = @GL_GNULIB_VFPRINTF_POSIX@ +GL_GNULIB_VFSCANF = @GL_GNULIB_VFSCANF@ +GL_GNULIB_VPRINTF = @GL_GNULIB_VPRINTF@ +GL_GNULIB_VPRINTF_POSIX = @GL_GNULIB_VPRINTF_POSIX@ +GL_GNULIB_VSCANF = @GL_GNULIB_VSCANF@ +GL_GNULIB_VSNPRINTF = @GL_GNULIB_VSNPRINTF@ +GL_GNULIB_VSPRINTF_POSIX = @GL_GNULIB_VSPRINTF_POSIX@ +GL_GNULIB_WCPCPY = @GL_GNULIB_WCPCPY@ +GL_GNULIB_WCPNCPY = @GL_GNULIB_WCPNCPY@ +GL_GNULIB_WCRTOMB = @GL_GNULIB_WCRTOMB@ +GL_GNULIB_WCSCASECMP = @GL_GNULIB_WCSCASECMP@ +GL_GNULIB_WCSCAT = @GL_GNULIB_WCSCAT@ +GL_GNULIB_WCSCHR = @GL_GNULIB_WCSCHR@ +GL_GNULIB_WCSCMP = @GL_GNULIB_WCSCMP@ +GL_GNULIB_WCSCOLL = @GL_GNULIB_WCSCOLL@ +GL_GNULIB_WCSCPY = @GL_GNULIB_WCSCPY@ +GL_GNULIB_WCSCSPN = @GL_GNULIB_WCSCSPN@ +GL_GNULIB_WCSDUP = @GL_GNULIB_WCSDUP@ +GL_GNULIB_WCSFTIME = @GL_GNULIB_WCSFTIME@ +GL_GNULIB_WCSLEN = @GL_GNULIB_WCSLEN@ +GL_GNULIB_WCSNCASECMP = @GL_GNULIB_WCSNCASECMP@ +GL_GNULIB_WCSNCAT = @GL_GNULIB_WCSNCAT@ +GL_GNULIB_WCSNCMP = @GL_GNULIB_WCSNCMP@ +GL_GNULIB_WCSNCPY = @GL_GNULIB_WCSNCPY@ +GL_GNULIB_WCSNLEN = @GL_GNULIB_WCSNLEN@ +GL_GNULIB_WCSNRTOMBS = @GL_GNULIB_WCSNRTOMBS@ +GL_GNULIB_WCSPBRK = @GL_GNULIB_WCSPBRK@ +GL_GNULIB_WCSRCHR = @GL_GNULIB_WCSRCHR@ +GL_GNULIB_WCSRTOMBS = @GL_GNULIB_WCSRTOMBS@ +GL_GNULIB_WCSSPN = @GL_GNULIB_WCSSPN@ +GL_GNULIB_WCSSTR = @GL_GNULIB_WCSSTR@ +GL_GNULIB_WCSTOK = @GL_GNULIB_WCSTOK@ +GL_GNULIB_WCSWIDTH = @GL_GNULIB_WCSWIDTH@ +GL_GNULIB_WCSXFRM = @GL_GNULIB_WCSXFRM@ +GL_GNULIB_WCTOB = @GL_GNULIB_WCTOB@ +GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@ +GL_GNULIB_WCWIDTH = @GL_GNULIB_WCWIDTH@ +GL_GNULIB_WMEMCHR = @GL_GNULIB_WMEMCHR@ +GL_GNULIB_WMEMCMP = @GL_GNULIB_WMEMCMP@ +GL_GNULIB_WMEMCPY = @GL_GNULIB_WMEMCPY@ +GL_GNULIB_WMEMMOVE = @GL_GNULIB_WMEMMOVE@ +GL_GNULIB_WMEMPCPY = @GL_GNULIB_WMEMPCPY@ +GL_GNULIB_WMEMSET = @GL_GNULIB_WMEMSET@ +GL_GNULIB_WRITE = @GL_GNULIB_WRITE@ +GL_GNULIB__EXIT = @GL_GNULIB__EXIT@ +GMP_CFLAGS = @GMP_CFLAGS@ +GMP_LIBS = @GMP_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNULIBHEADERS_OVERRIDE_WINT_T = @GNULIBHEADERS_OVERRIDE_WINT_T@ +GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@ +GNUTLS_LIBS_PRIVATE = @GNUTLS_LIBS_PRIVATE@ +GNUTLS_REQUIRES_PRIVATE = @GNUTLS_REQUIRES_PRIVATE@ +GPERF = @GPERF@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUILD = @GUILD@ +GUILE = @GUILE@ +GUILE_CFLAGS = @GUILE_CFLAGS@ +GUILE_CONFIG = @GUILE_CONFIG@ +GUILE_EFFECTIVE_VERSION = @GUILE_EFFECTIVE_VERSION@ +GUILE_EXTENSION = @GUILE_EXTENSION@ +GUILE_LDFLAGS = @GUILE_LDFLAGS@ +GUILE_LIBS = @GUILE_LIBS@ +GUILE_LTLIBS = @GUILE_LTLIBS@ +GUILE_SITE = @GUILE_SITE@ +GUILE_SITE_CCACHE = @GUILE_SITE_CCACHE@ +GUILE_TOOLS = @GUILE_TOOLS@ +HAVE_ACCEPT4 = @HAVE_ACCEPT4@ +HAVE_ALIGNED_ALLOC = @HAVE_ALIGNED_ALLOC@ +HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ +HAVE_ARPA_INET_H = @HAVE_ARPA_INET_H@ +HAVE_ATOLL = @HAVE_ATOLL@ +HAVE_BTOWC = @HAVE_BTOWC@ +HAVE_C99_STDINT_H = @HAVE_C99_STDINT_H@ +HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ +HAVE_CHOWN = @HAVE_CHOWN@ +HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@ +HAVE_CRTDEFS_H = @HAVE_CRTDEFS_H@ +HAVE_DECL_ECVT = @HAVE_DECL_ECVT@ +HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ +HAVE_DECL_EXECVPE = @HAVE_DECL_EXECVPE@ +HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@ +HAVE_DECL_FCLOSEALL = @HAVE_DECL_FCLOSEALL@ +HAVE_DECL_FCVT = @HAVE_DECL_FCVT@ +HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@ +HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@ +HAVE_DECL_FREEADDRINFO = @HAVE_DECL_FREEADDRINFO@ +HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@ +HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@ +HAVE_DECL_GAI_STRERROR = @HAVE_DECL_GAI_STRERROR@ +HAVE_DECL_GCVT = @HAVE_DECL_GCVT@ +HAVE_DECL_GETADDRINFO = @HAVE_DECL_GETADDRINFO@ +HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@ +HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@ +HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@ +HAVE_DECL_GETLOADAVG = @HAVE_DECL_GETLOADAVG@ +HAVE_DECL_GETLOGIN = @HAVE_DECL_GETLOGIN@ +HAVE_DECL_GETLOGIN_R = @HAVE_DECL_GETLOGIN_R@ +HAVE_DECL_GETNAMEINFO = @HAVE_DECL_GETNAMEINFO@ +HAVE_DECL_GETPAGESIZE = @HAVE_DECL_GETPAGESIZE@ +HAVE_DECL_GETUSERSHELL = @HAVE_DECL_GETUSERSHELL@ +HAVE_DECL_IMAXABS = @HAVE_DECL_IMAXABS@ +HAVE_DECL_IMAXDIV = @HAVE_DECL_IMAXDIV@ +HAVE_DECL_INET_NTOP = @HAVE_DECL_INET_NTOP@ +HAVE_DECL_INET_PTON = @HAVE_DECL_INET_PTON@ +HAVE_DECL_INITSTATE = @HAVE_DECL_INITSTATE@ +HAVE_DECL_LOCALTIME_R = @HAVE_DECL_LOCALTIME_R@ +HAVE_DECL_MEMMEM = @HAVE_DECL_MEMMEM@ +HAVE_DECL_MEMRCHR = @HAVE_DECL_MEMRCHR@ +HAVE_DECL_OBSTACK_PRINTF = @HAVE_DECL_OBSTACK_PRINTF@ +HAVE_DECL_SETENV = @HAVE_DECL_SETENV@ +HAVE_DECL_SETHOSTNAME = @HAVE_DECL_SETHOSTNAME@ +HAVE_DECL_SETSTATE = @HAVE_DECL_SETSTATE@ +HAVE_DECL_SNPRINTF = @HAVE_DECL_SNPRINTF@ +HAVE_DECL_STRDUP = @HAVE_DECL_STRDUP@ +HAVE_DECL_STRERROR_R = @HAVE_DECL_STRERROR_R@ +HAVE_DECL_STRNCASECMP = @HAVE_DECL_STRNCASECMP@ +HAVE_DECL_STRNDUP = @HAVE_DECL_STRNDUP@ +HAVE_DECL_STRNLEN = @HAVE_DECL_STRNLEN@ +HAVE_DECL_STRSIGNAL = @HAVE_DECL_STRSIGNAL@ +HAVE_DECL_STRTOIMAX = @HAVE_DECL_STRTOIMAX@ +HAVE_DECL_STRTOK_R = @HAVE_DECL_STRTOK_R@ +HAVE_DECL_STRTOUMAX = @HAVE_DECL_STRTOUMAX@ +HAVE_DECL_TRUNCATE = @HAVE_DECL_TRUNCATE@ +HAVE_DECL_TTYNAME_R = @HAVE_DECL_TTYNAME_R@ +HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@ +HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@ +HAVE_DECL_WCSDUP = @HAVE_DECL_WCSDUP@ +HAVE_DECL_WCTOB = @HAVE_DECL_WCTOB@ +HAVE_DECL_WCWIDTH = @HAVE_DECL_WCWIDTH@ +HAVE_DPRINTF = @HAVE_DPRINTF@ +HAVE_DUP3 = @HAVE_DUP3@ +HAVE_DUPLOCALE = @HAVE_DUPLOCALE@ +HAVE_EUIDACCESS = @HAVE_EUIDACCESS@ +HAVE_EXECVPE = @HAVE_EXECVPE@ +HAVE_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@ +HAVE_FACCESSAT = @HAVE_FACCESSAT@ +HAVE_FCHDIR = @HAVE_FCHDIR@ +HAVE_FCHMODAT = @HAVE_FCHMODAT@ +HAVE_FCHOWNAT = @HAVE_FCHOWNAT@ +HAVE_FCNTL = @HAVE_FCNTL@ +HAVE_FDATASYNC = @HAVE_FDATASYNC@ +HAVE_FEATURES_H = @HAVE_FEATURES_H@ +HAVE_FFS = @HAVE_FFS@ +HAVE_FFSL = @HAVE_FFSL@ +HAVE_FFSLL = @HAVE_FFSLL@ +HAVE_FREELOCALE = @HAVE_FREELOCALE@ +HAVE_FSEEKO = @HAVE_FSEEKO@ +HAVE_FSTATAT = @HAVE_FSTATAT@ +HAVE_FSYNC = @HAVE_FSYNC@ +HAVE_FTELLO = @HAVE_FTELLO@ +HAVE_FTRUNCATE = @HAVE_FTRUNCATE@ +HAVE_FUTIMENS = @HAVE_FUTIMENS@ +HAVE_GETDTABLESIZE = @HAVE_GETDTABLESIZE@ +HAVE_GETENTROPY = @HAVE_GETENTROPY@ +HAVE_GETGROUPS = @HAVE_GETGROUPS@ +HAVE_GETHOSTNAME = @HAVE_GETHOSTNAME@ +HAVE_GETLOGIN = @HAVE_GETLOGIN@ +HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@ +HAVE_GETPASS = @HAVE_GETPASS@ +HAVE_GETSUBOPT = @HAVE_GETSUBOPT@ +HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@ +HAVE_GETUMASK = @HAVE_GETUMASK@ +HAVE_GRANTPT = @HAVE_GRANTPT@ +HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@ +HAVE_IMAXDIV_T = @HAVE_IMAXDIV_T@ +HAVE_INITSTATE = @HAVE_INITSTATE@ +HAVE_INTTYPES_H = @HAVE_INTTYPES_H@ +HAVE_ISBLANK = @HAVE_ISBLANK@ +HAVE_LANGINFO_ALTMON = @HAVE_LANGINFO_ALTMON@ +HAVE_LANGINFO_CODESET = @HAVE_LANGINFO_CODESET@ +HAVE_LANGINFO_ERA = @HAVE_LANGINFO_ERA@ +HAVE_LANGINFO_H = @HAVE_LANGINFO_H@ +HAVE_LANGINFO_T_FMT_AMPM = @HAVE_LANGINFO_T_FMT_AMPM@ +HAVE_LANGINFO_YESEXPR = @HAVE_LANGINFO_YESEXPR@ +HAVE_LCHMOD = @HAVE_LCHMOD@ +HAVE_LCHOWN = @HAVE_LCHOWN@ +HAVE_LIBCRYPTO = @HAVE_LIBCRYPTO@ +HAVE_LIBDL = @HAVE_LIBDL@ +HAVE_LIBEV = @HAVE_LIBEV@ +HAVE_LIBPTHREAD = @HAVE_LIBPTHREAD@ +HAVE_LIBRT = @HAVE_LIBRT@ +HAVE_LIBSECCOMP = @HAVE_LIBSECCOMP@ +HAVE_LIBZ = @HAVE_LIBZ@ +HAVE_LINK = @HAVE_LINK@ +HAVE_LINKAT = @HAVE_LINKAT@ +HAVE_LSTAT = @HAVE_LSTAT@ +HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@ +HAVE_MBRLEN = @HAVE_MBRLEN@ +HAVE_MBRTOWC = @HAVE_MBRTOWC@ +HAVE_MBSINIT = @HAVE_MBSINIT@ +HAVE_MBSLEN = @HAVE_MBSLEN@ +HAVE_MBSNRTOWCS = @HAVE_MBSNRTOWCS@ +HAVE_MBSRTOWCS = @HAVE_MBSRTOWCS@ +HAVE_MBTOWC = @HAVE_MBTOWC@ +HAVE_MEMPCPY = @HAVE_MEMPCPY@ +HAVE_MKDIRAT = @HAVE_MKDIRAT@ +HAVE_MKDTEMP = @HAVE_MKDTEMP@ +HAVE_MKFIFO = @HAVE_MKFIFO@ +HAVE_MKFIFOAT = @HAVE_MKFIFOAT@ +HAVE_MKNOD = @HAVE_MKNOD@ +HAVE_MKNODAT = @HAVE_MKNODAT@ +HAVE_MKOSTEMP = @HAVE_MKOSTEMP@ +HAVE_MKOSTEMPS = @HAVE_MKOSTEMPS@ +HAVE_MKSTEMP = @HAVE_MKSTEMP@ +HAVE_MKSTEMPS = @HAVE_MKSTEMPS@ +HAVE_MSVC_INVALID_PARAMETER_HANDLER = @HAVE_MSVC_INVALID_PARAMETER_HANDLER@ +HAVE_NANOSLEEP = @HAVE_NANOSLEEP@ +HAVE_NETDB_H = @HAVE_NETDB_H@ +HAVE_NETINET_IN_H = @HAVE_NETINET_IN_H@ +HAVE_NEWLOCALE = @HAVE_NEWLOCALE@ +HAVE_NL_LANGINFO = @HAVE_NL_LANGINFO@ +HAVE_OPENAT = @HAVE_OPENAT@ +HAVE_OS_H = @HAVE_OS_H@ +HAVE_PCLOSE = @HAVE_PCLOSE@ +HAVE_PIPE = @HAVE_PIPE@ +HAVE_PIPE2 = @HAVE_PIPE2@ +HAVE_POPEN = @HAVE_POPEN@ +HAVE_POSIX_MEMALIGN = @HAVE_POSIX_MEMALIGN@ +HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@ +HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@ +HAVE_PREAD = @HAVE_PREAD@ +HAVE_PSELECT = @HAVE_PSELECT@ +HAVE_PTHREAD_ATTR_DESTROY = @HAVE_PTHREAD_ATTR_DESTROY@ +HAVE_PTHREAD_ATTR_GETDETACHSTATE = @HAVE_PTHREAD_ATTR_GETDETACHSTATE@ +HAVE_PTHREAD_ATTR_INIT = @HAVE_PTHREAD_ATTR_INIT@ +HAVE_PTHREAD_ATTR_SETDETACHSTATE = @HAVE_PTHREAD_ATTR_SETDETACHSTATE@ +HAVE_PTHREAD_CONDATTR_DESTROY = @HAVE_PTHREAD_CONDATTR_DESTROY@ +HAVE_PTHREAD_CONDATTR_INIT = @HAVE_PTHREAD_CONDATTR_INIT@ +HAVE_PTHREAD_COND_BROADCAST = @HAVE_PTHREAD_COND_BROADCAST@ +HAVE_PTHREAD_COND_DESTROY = @HAVE_PTHREAD_COND_DESTROY@ +HAVE_PTHREAD_COND_INIT = @HAVE_PTHREAD_COND_INIT@ +HAVE_PTHREAD_COND_SIGNAL = @HAVE_PTHREAD_COND_SIGNAL@ +HAVE_PTHREAD_COND_TIMEDWAIT = @HAVE_PTHREAD_COND_TIMEDWAIT@ +HAVE_PTHREAD_COND_WAIT = @HAVE_PTHREAD_COND_WAIT@ +HAVE_PTHREAD_CREATE = @HAVE_PTHREAD_CREATE@ +HAVE_PTHREAD_CREATE_DETACHED = @HAVE_PTHREAD_CREATE_DETACHED@ +HAVE_PTHREAD_DETACH = @HAVE_PTHREAD_DETACH@ +HAVE_PTHREAD_EQUAL = @HAVE_PTHREAD_EQUAL@ +HAVE_PTHREAD_EXIT = @HAVE_PTHREAD_EXIT@ +HAVE_PTHREAD_GETSPECIFIC = @HAVE_PTHREAD_GETSPECIFIC@ +HAVE_PTHREAD_H = @HAVE_PTHREAD_H@ +HAVE_PTHREAD_JOIN = @HAVE_PTHREAD_JOIN@ +HAVE_PTHREAD_KEY_CREATE = @HAVE_PTHREAD_KEY_CREATE@ +HAVE_PTHREAD_KEY_DELETE = @HAVE_PTHREAD_KEY_DELETE@ +HAVE_PTHREAD_MUTEXATTR_DESTROY = @HAVE_PTHREAD_MUTEXATTR_DESTROY@ +HAVE_PTHREAD_MUTEXATTR_GETROBUST = @HAVE_PTHREAD_MUTEXATTR_GETROBUST@ +HAVE_PTHREAD_MUTEXATTR_GETTYPE = @HAVE_PTHREAD_MUTEXATTR_GETTYPE@ +HAVE_PTHREAD_MUTEXATTR_INIT = @HAVE_PTHREAD_MUTEXATTR_INIT@ +HAVE_PTHREAD_MUTEXATTR_SETROBUST = @HAVE_PTHREAD_MUTEXATTR_SETROBUST@ +HAVE_PTHREAD_MUTEXATTR_SETTYPE = @HAVE_PTHREAD_MUTEXATTR_SETTYPE@ +HAVE_PTHREAD_MUTEX_DESTROY = @HAVE_PTHREAD_MUTEX_DESTROY@ +HAVE_PTHREAD_MUTEX_INIT = @HAVE_PTHREAD_MUTEX_INIT@ +HAVE_PTHREAD_MUTEX_LOCK = @HAVE_PTHREAD_MUTEX_LOCK@ +HAVE_PTHREAD_MUTEX_RECURSIVE = @HAVE_PTHREAD_MUTEX_RECURSIVE@ +HAVE_PTHREAD_MUTEX_ROBUST = @HAVE_PTHREAD_MUTEX_ROBUST@ +HAVE_PTHREAD_MUTEX_TIMEDLOCK = @HAVE_PTHREAD_MUTEX_TIMEDLOCK@ +HAVE_PTHREAD_MUTEX_TRYLOCK = @HAVE_PTHREAD_MUTEX_TRYLOCK@ +HAVE_PTHREAD_MUTEX_UNLOCK = @HAVE_PTHREAD_MUTEX_UNLOCK@ +HAVE_PTHREAD_ONCE = @HAVE_PTHREAD_ONCE@ +HAVE_PTHREAD_PROCESS_SHARED = @HAVE_PTHREAD_PROCESS_SHARED@ +HAVE_PTHREAD_RWLOCKATTR_DESTROY = @HAVE_PTHREAD_RWLOCKATTR_DESTROY@ +HAVE_PTHREAD_RWLOCKATTR_INIT = @HAVE_PTHREAD_RWLOCKATTR_INIT@ +HAVE_PTHREAD_RWLOCK_DESTROY = @HAVE_PTHREAD_RWLOCK_DESTROY@ +HAVE_PTHREAD_RWLOCK_INIT = @HAVE_PTHREAD_RWLOCK_INIT@ +HAVE_PTHREAD_RWLOCK_RDLOCK = @HAVE_PTHREAD_RWLOCK_RDLOCK@ +HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK = @HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK@ +HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK = @HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK@ +HAVE_PTHREAD_RWLOCK_TRYRDLOCK = @HAVE_PTHREAD_RWLOCK_TRYRDLOCK@ +HAVE_PTHREAD_RWLOCK_TRYWRLOCK = @HAVE_PTHREAD_RWLOCK_TRYWRLOCK@ +HAVE_PTHREAD_RWLOCK_UNLOCK = @HAVE_PTHREAD_RWLOCK_UNLOCK@ +HAVE_PTHREAD_RWLOCK_WRLOCK = @HAVE_PTHREAD_RWLOCK_WRLOCK@ +HAVE_PTHREAD_SELF = @HAVE_PTHREAD_SELF@ +HAVE_PTHREAD_SETSPECIFIC = @HAVE_PTHREAD_SETSPECIFIC@ +HAVE_PTHREAD_SIGMASK = @HAVE_PTHREAD_SIGMASK@ +HAVE_PTHREAD_SPINLOCK_T = @HAVE_PTHREAD_SPINLOCK_T@ +HAVE_PTHREAD_SPIN_DESTROY = @HAVE_PTHREAD_SPIN_DESTROY@ +HAVE_PTHREAD_SPIN_INIT = @HAVE_PTHREAD_SPIN_INIT@ +HAVE_PTHREAD_SPIN_LOCK = @HAVE_PTHREAD_SPIN_LOCK@ +HAVE_PTHREAD_SPIN_TRYLOCK = @HAVE_PTHREAD_SPIN_TRYLOCK@ +HAVE_PTHREAD_SPIN_UNLOCK = @HAVE_PTHREAD_SPIN_UNLOCK@ +HAVE_PTHREAD_T = @HAVE_PTHREAD_T@ +HAVE_PTSNAME = @HAVE_PTSNAME@ +HAVE_PTSNAME_R = @HAVE_PTSNAME_R@ +HAVE_PWRITE = @HAVE_PWRITE@ +HAVE_QSORT_R = @HAVE_QSORT_R@ +HAVE_RAISE = @HAVE_RAISE@ +HAVE_RANDOM = @HAVE_RANDOM@ +HAVE_RANDOM_H = @HAVE_RANDOM_H@ +HAVE_RANDOM_R = @HAVE_RANDOM_R@ +HAVE_RAWMEMCHR = @HAVE_RAWMEMCHR@ +HAVE_READLINK = @HAVE_READLINK@ +HAVE_READLINKAT = @HAVE_READLINKAT@ +HAVE_REALLOCARRAY = @HAVE_REALLOCARRAY@ +HAVE_REALPATH = @HAVE_REALPATH@ +HAVE_RENAMEAT = @HAVE_RENAMEAT@ +HAVE_RPMATCH = @HAVE_RPMATCH@ +HAVE_SA_FAMILY_T = @HAVE_SA_FAMILY_T@ +HAVE_SCHED_H = @HAVE_SCHED_H@ +HAVE_SCHED_YIELD = @HAVE_SCHED_YIELD@ +HAVE_SECURE_GETENV = @HAVE_SECURE_GETENV@ +HAVE_SETENV = @HAVE_SETENV@ +HAVE_SETHOSTNAME = @HAVE_SETHOSTNAME@ +HAVE_SETSTATE = @HAVE_SETSTATE@ +HAVE_SIGABBREV_NP = @HAVE_SIGABBREV_NP@ +HAVE_SIGACTION = @HAVE_SIGACTION@ +HAVE_SIGDESCR_NP = @HAVE_SIGDESCR_NP@ +HAVE_SIGHANDLER_T = @HAVE_SIGHANDLER_T@ +HAVE_SIGINFO_T = @HAVE_SIGINFO_T@ +HAVE_SIGNED_SIG_ATOMIC_T = @HAVE_SIGNED_SIG_ATOMIC_T@ +HAVE_SIGNED_WCHAR_T = @HAVE_SIGNED_WCHAR_T@ +HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ +HAVE_SIGSET_T = @HAVE_SIGSET_T@ +HAVE_SLEEP = @HAVE_SLEEP@ +HAVE_STDINT_H = @HAVE_STDINT_H@ +HAVE_STPCPY = @HAVE_STPCPY@ +HAVE_STPNCPY = @HAVE_STPNCPY@ +HAVE_STRCASECMP = @HAVE_STRCASECMP@ +HAVE_STRCASESTR = @HAVE_STRCASESTR@ +HAVE_STRCHRNUL = @HAVE_STRCHRNUL@ +HAVE_STRERRORNAME_NP = @HAVE_STRERRORNAME_NP@ +HAVE_STRINGS_H = @HAVE_STRINGS_H@ +HAVE_STRPBRK = @HAVE_STRPBRK@ +HAVE_STRPTIME = @HAVE_STRPTIME@ +HAVE_STRSEP = @HAVE_STRSEP@ +HAVE_STRTOD = @HAVE_STRTOD@ +HAVE_STRTOL = @HAVE_STRTOL@ +HAVE_STRTOLD = @HAVE_STRTOLD@ +HAVE_STRTOLL = @HAVE_STRTOLL@ +HAVE_STRTOUL = @HAVE_STRTOUL@ +HAVE_STRTOULL = @HAVE_STRTOULL@ +HAVE_STRUCT_ADDRINFO = @HAVE_STRUCT_ADDRINFO@ +HAVE_STRUCT_RANDOM_DATA = @HAVE_STRUCT_RANDOM_DATA@ +HAVE_STRUCT_SCHED_PARAM = @HAVE_STRUCT_SCHED_PARAM@ +HAVE_STRUCT_SIGACTION_SA_SIGACTION = @HAVE_STRUCT_SIGACTION_SA_SIGACTION@ +HAVE_STRUCT_SOCKADDR_STORAGE = @HAVE_STRUCT_SOCKADDR_STORAGE@ +HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = @HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY@ +HAVE_STRUCT_TIMEVAL = @HAVE_STRUCT_TIMEVAL@ +HAVE_STRVERSCMP = @HAVE_STRVERSCMP@ +HAVE_SYMLINK = @HAVE_SYMLINK@ +HAVE_SYMLINKAT = @HAVE_SYMLINKAT@ +HAVE_SYS_BITYPES_H = @HAVE_SYS_BITYPES_H@ +HAVE_SYS_CDEFS_H = @HAVE_SYS_CDEFS_H@ +HAVE_SYS_INTTYPES_H = @HAVE_SYS_INTTYPES_H@ +HAVE_SYS_IOCTL_H = @HAVE_SYS_IOCTL_H@ +HAVE_SYS_LOADAVG_H = @HAVE_SYS_LOADAVG_H@ +HAVE_SYS_PARAM_H = @HAVE_SYS_PARAM_H@ +HAVE_SYS_SELECT_H = @HAVE_SYS_SELECT_H@ +HAVE_SYS_SOCKET_H = @HAVE_SYS_SOCKET_H@ +HAVE_SYS_TIME_H = @HAVE_SYS_TIME_H@ +HAVE_SYS_TYPES_H = @HAVE_SYS_TYPES_H@ +HAVE_SYS_UIO_H = @HAVE_SYS_UIO_H@ +HAVE_TIMEGM = @HAVE_TIMEGM@ +HAVE_TIMESPEC_GET = @HAVE_TIMESPEC_GET@ +HAVE_TIMEZONE_T = @HAVE_TIMEZONE_T@ +HAVE_TYPE_VOLATILE_SIG_ATOMIC_T = @HAVE_TYPE_VOLATILE_SIG_ATOMIC_T@ +HAVE_UNISTD_H = @HAVE_UNISTD_H@ +HAVE_UNLINKAT = @HAVE_UNLINKAT@ +HAVE_UNLOCKPT = @HAVE_UNLOCKPT@ +HAVE_USLEEP = @HAVE_USLEEP@ +HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ +HAVE_VASPRINTF = @HAVE_VASPRINTF@ +HAVE_VDPRINTF = @HAVE_VDPRINTF@ +HAVE_VISIBILITY = @HAVE_VISIBILITY@ +HAVE_WCHAR_H = @HAVE_WCHAR_H@ +HAVE_WCHAR_T = @HAVE_WCHAR_T@ +HAVE_WCPCPY = @HAVE_WCPCPY@ +HAVE_WCPNCPY = @HAVE_WCPNCPY@ +HAVE_WCRTOMB = @HAVE_WCRTOMB@ +HAVE_WCSCASECMP = @HAVE_WCSCASECMP@ +HAVE_WCSCAT = @HAVE_WCSCAT@ +HAVE_WCSCHR = @HAVE_WCSCHR@ +HAVE_WCSCMP = @HAVE_WCSCMP@ +HAVE_WCSCOLL = @HAVE_WCSCOLL@ +HAVE_WCSCPY = @HAVE_WCSCPY@ +HAVE_WCSCSPN = @HAVE_WCSCSPN@ +HAVE_WCSDUP = @HAVE_WCSDUP@ +HAVE_WCSFTIME = @HAVE_WCSFTIME@ +HAVE_WCSLEN = @HAVE_WCSLEN@ +HAVE_WCSNCASECMP = @HAVE_WCSNCASECMP@ +HAVE_WCSNCAT = @HAVE_WCSNCAT@ +HAVE_WCSNCMP = @HAVE_WCSNCMP@ +HAVE_WCSNCPY = @HAVE_WCSNCPY@ +HAVE_WCSNLEN = @HAVE_WCSNLEN@ +HAVE_WCSNRTOMBS = @HAVE_WCSNRTOMBS@ +HAVE_WCSPBRK = @HAVE_WCSPBRK@ +HAVE_WCSRCHR = @HAVE_WCSRCHR@ +HAVE_WCSRTOMBS = @HAVE_WCSRTOMBS@ +HAVE_WCSSPN = @HAVE_WCSSPN@ +HAVE_WCSSTR = @HAVE_WCSSTR@ +HAVE_WCSTOK = @HAVE_WCSTOK@ +HAVE_WCSWIDTH = @HAVE_WCSWIDTH@ +HAVE_WCSXFRM = @HAVE_WCSXFRM@ +HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WINT_T = @HAVE_WINT_T@ +HAVE_WMEMCHR = @HAVE_WMEMCHR@ +HAVE_WMEMCMP = @HAVE_WMEMCMP@ +HAVE_WMEMCPY = @HAVE_WMEMCPY@ +HAVE_WMEMMOVE = @HAVE_WMEMMOVE@ +HAVE_WMEMPCPY = @HAVE_WMEMPCPY@ +HAVE_WMEMSET = @HAVE_WMEMSET@ +HAVE_WS2TCPIP_H = @HAVE_WS2TCPIP_H@ +HAVE_XLOCALE_H = @HAVE_XLOCALE_H@ +HAVE__BOOL = @HAVE__BOOL@ +HAVE__EXIT = @HAVE__EXIT@ +HOGWEED_CFLAGS = @HOGWEED_CFLAGS@ +HOGWEED_LIBS = @HOGWEED_LIBS@ +HOSTENT_LIB = @HOSTENT_LIB@ +HTML_DIR = @HTML_DIR@ +INCLUDE_NEXT = @INCLUDE_NEXT@ +INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ +INET_NTOP_LIB = @INET_NTOP_LIB@ +INET_PTON_LIB = @INET_PTON_LIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INT32_MAX_LT_INTMAX_MAX = @INT32_MAX_LT_INTMAX_MAX@ +INT64_MAX_EQ_LONG_MAX = @INT64_MAX_EQ_LONG_MAX@ +INTLLIBS = @INTLLIBS@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDDPOSTPROC = @LDDPOSTPROC@ +LDDPROG = @LDDPROG@ +LDFLAGS = @LDFLAGS@ +LIBATOMIC_LIBS = @LIBATOMIC_LIBS@ +LIBBROTLIDEC_CFLAGS = @LIBBROTLIDEC_CFLAGS@ +LIBBROTLIDEC_LIBS = @LIBBROTLIDEC_LIBS@ +LIBBROTLIENC_CFLAGS = @LIBBROTLIENC_CFLAGS@ +LIBBROTLIENC_LIBS = @LIBBROTLIENC_LIBS@ +LIBCRYPTO = @LIBCRYPTO@ +LIBCRYPTO_PREFIX = @LIBCRYPTO_PREFIX@ +LIBDL = @LIBDL@ +LIBDL_PREFIX = @LIBDL_PREFIX@ +LIBEV = @LIBEV@ +LIBEV_LIBS = @LIBEV_LIBS@ +LIBEV_PREFIX = @LIBEV_PREFIX@ +LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ +LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ +LIBICONV = @LIBICONV@ +LIBIDN2_CFLAGS = @LIBIDN2_CFLAGS@ +LIBIDN2_LIBS = @LIBIDN2_LIBS@ +LIBINTL = @LIBINTL@ +LIBKCAPI_CFLAGS = @LIBKCAPI_CFLAGS@ +LIBKCAPI_LIBS = @LIBKCAPI_LIBS@ +LIBMULTITHREAD = @LIBMULTITHREAD@ +LIBOBJS = @LIBOBJS@ +LIBPMULTITHREAD = @LIBPMULTITHREAD@ +LIBPTHREAD = @LIBPTHREAD@ +LIBPTHREAD_PREFIX = @LIBPTHREAD_PREFIX@ +LIBRT = @LIBRT@ +LIBRT_PREFIX = @LIBRT_PREFIX@ +LIBS = @LIBS@ +LIBSECCOMP = @LIBSECCOMP@ +LIBSECCOMP_PREFIX = @LIBSECCOMP_PREFIX@ +LIBSOCKET = @LIBSOCKET@ +LIBSTDTHREAD = @LIBSTDTHREAD@ +LIBTASN1_CFLAGS = @LIBTASN1_CFLAGS@ +LIBTASN1_LIBS = @LIBTASN1_LIBS@ +LIBTESTS_LIBDEPS = @LIBTESTS_LIBDEPS@ +LIBTHREAD = @LIBTHREAD@ +LIBTOOL = @LIBTOOL@ +LIBUNISTRING = @LIBUNISTRING@ +LIBUNISTRING_UNICTYPE_H = @LIBUNISTRING_UNICTYPE_H@ +LIBUNISTRING_UNINORM_H = @LIBUNISTRING_UNINORM_H@ +LIBUNISTRING_UNISTR_H = @LIBUNISTRING_UNISTR_H@ +LIBUNISTRING_UNITYPES_H = @LIBUNISTRING_UNITYPES_H@ +LIBZ = @LIBZ@ +LIBZSTD_CFLAGS = @LIBZSTD_CFLAGS@ +LIBZSTD_LIBS = @LIBZSTD_LIBS@ +LIBZ_PC = @LIBZ_PC@ +LIBZ_PREFIX = @LIBZ_PREFIX@ +LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@ +LIB_NANOSLEEP = @LIB_NANOSLEEP@ +LIB_PTHREAD = @LIB_PTHREAD@ +LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ +LIB_SCHED_YIELD = @LIB_SCHED_YIELD@ +LIB_SELECT = @LIB_SELECT@ +LIB_SEMAPHORE = @LIB_SEMAPHORE@ +LIB_SETLOCALE = @LIB_SETLOCALE@ +LIB_SETLOCALE_NULL = @LIB_SETLOCALE_NULL@ +LIMITS_H = @LIMITS_H@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOCALENAME_ENHANCE_LOCALE_FUNCS = @LOCALENAME_ENHANCE_LOCALE_FUNCS@ +LOCALE_FR = @LOCALE_FR@ +LOCALE_FR_UTF8 = @LOCALE_FR_UTF8@ +LOCALE_JA = @LOCALE_JA@ +LOCALE_TR_UTF8 = @LOCALE_TR_UTF8@ +LOCALE_ZH_CN = @LOCALE_ZH_CN@ +LOG_VALGRIND = @LOG_VALGRIND@ +LTALLOCA = @LTALLOCA@ +LTLIBCRYPTO = @LTLIBCRYPTO@ +LTLIBDL = @LTLIBDL@ +LTLIBEV = @LTLIBEV@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBMULTITHREAD = @LTLIBMULTITHREAD@ +LTLIBOBJS = @LTLIBOBJS@ +LTLIBPTHREAD = @LTLIBPTHREAD@ +LTLIBRT = @LTLIBRT@ +LTLIBSECCOMP = @LTLIBSECCOMP@ +LTLIBTHREAD = @LTLIBTHREAD@ +LTLIBZ = @LTLIBZ@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_DANE_AGE = @LT_DANE_AGE@ +LT_DANE_CURRENT = @LT_DANE_CURRENT@ +LT_DANE_REVISION = @LT_DANE_REVISION@ +LT_REVISION = @LT_REVISION@ +LT_SSL_AGE = @LT_SSL_AGE@ +LT_SSL_CURRENT = @LT_SSL_CURRENT@ +LT_SSL_REVISION = @LT_SSL_REVISION@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_XSSL_AGE = @LT_XSSL_AGE@ +LT_XSSL_CURRENT = @LT_XSSL_CURRENT@ +LT_XSSL_REVISION = @LT_XSSL_REVISION@ +MAINT = @MAINT@ +MAJOR_VERSION = @MAJOR_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MINOR_VERSION = @MINOR_VERSION@ +MKDIR_P = @MKDIR_P@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@ +NETINET_IN_H = @NETINET_IN_H@ +NETTLE_CFLAGS = @NETTLE_CFLAGS@ +NETTLE_LIBS = @NETTLE_LIBS@ +NEXT_ARPA_INET_H = @NEXT_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H = @NEXT_AS_FIRST_DIRECTIVE_ARPA_INET_H@ +NEXT_AS_FIRST_DIRECTIVE_CTYPE_H = @NEXT_AS_FIRST_DIRECTIVE_CTYPE_H@ +NEXT_AS_FIRST_DIRECTIVE_ERRNO_H = @NEXT_AS_FIRST_DIRECTIVE_ERRNO_H@ +NEXT_AS_FIRST_DIRECTIVE_FCNTL_H = @NEXT_AS_FIRST_DIRECTIVE_FCNTL_H@ +NEXT_AS_FIRST_DIRECTIVE_FLOAT_H = @NEXT_AS_FIRST_DIRECTIVE_FLOAT_H@ +NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H = @NEXT_AS_FIRST_DIRECTIVE_LANGINFO_H@ +NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ +NEXT_AS_FIRST_DIRECTIVE_LOCALE_H = @NEXT_AS_FIRST_DIRECTIVE_LOCALE_H@ +NEXT_AS_FIRST_DIRECTIVE_NETDB_H = @NEXT_AS_FIRST_DIRECTIVE_NETDB_H@ +NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H = @NEXT_AS_FIRST_DIRECTIVE_NETINET_IN_H@ +NEXT_AS_FIRST_DIRECTIVE_PTHREAD_H = @NEXT_AS_FIRST_DIRECTIVE_PTHREAD_H@ +NEXT_AS_FIRST_DIRECTIVE_SCHED_H = @NEXT_AS_FIRST_DIRECTIVE_SCHED_H@ +NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ +NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ +NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ +NEXT_AS_FIRST_DIRECTIVE_STDLIB_H = @NEXT_AS_FIRST_DIRECTIVE_STDLIB_H@ +NEXT_AS_FIRST_DIRECTIVE_STRINGS_H = @NEXT_AS_FIRST_DIRECTIVE_STRINGS_H@ +NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_IOCTL_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SELECT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_SOCKET_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_STAT_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_TYPES_H@ +NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H = @NEXT_AS_FIRST_DIRECTIVE_SYS_UIO_H@ +NEXT_AS_FIRST_DIRECTIVE_TIME_H = @NEXT_AS_FIRST_DIRECTIVE_TIME_H@ +NEXT_AS_FIRST_DIRECTIVE_UNISTD_H = @NEXT_AS_FIRST_DIRECTIVE_UNISTD_H@ +NEXT_AS_FIRST_DIRECTIVE_WCHAR_H = @NEXT_AS_FIRST_DIRECTIVE_WCHAR_H@ +NEXT_CTYPE_H = @NEXT_CTYPE_H@ +NEXT_ERRNO_H = @NEXT_ERRNO_H@ +NEXT_FCNTL_H = @NEXT_FCNTL_H@ +NEXT_FLOAT_H = @NEXT_FLOAT_H@ +NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ +NEXT_LANGINFO_H = @NEXT_LANGINFO_H@ +NEXT_LIMITS_H = @NEXT_LIMITS_H@ +NEXT_LOCALE_H = @NEXT_LOCALE_H@ +NEXT_NETDB_H = @NEXT_NETDB_H@ +NEXT_NETINET_IN_H = @NEXT_NETINET_IN_H@ +NEXT_PTHREAD_H = @NEXT_PTHREAD_H@ +NEXT_SCHED_H = @NEXT_SCHED_H@ +NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_STDDEF_H = @NEXT_STDDEF_H@ +NEXT_STDINT_H = @NEXT_STDINT_H@ +NEXT_STDIO_H = @NEXT_STDIO_H@ +NEXT_STDLIB_H = @NEXT_STDLIB_H@ +NEXT_STRINGS_H = @NEXT_STRINGS_H@ +NEXT_STRING_H = @NEXT_STRING_H@ +NEXT_SYS_IOCTL_H = @NEXT_SYS_IOCTL_H@ +NEXT_SYS_SELECT_H = @NEXT_SYS_SELECT_H@ +NEXT_SYS_SOCKET_H = @NEXT_SYS_SOCKET_H@ +NEXT_SYS_STAT_H = @NEXT_SYS_STAT_H@ +NEXT_SYS_TIME_H = @NEXT_SYS_TIME_H@ +NEXT_SYS_TYPES_H = @NEXT_SYS_TYPES_H@ +NEXT_SYS_UIO_H = @NEXT_SYS_UIO_H@ +NEXT_TIME_H = @NEXT_TIME_H@ +NEXT_UNISTD_H = @NEXT_UNISTD_H@ +NEXT_WCHAR_H = @NEXT_WCHAR_H@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NUMBER_VERSION = @NUMBER_VERSION@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +P11_KIT_CFLAGS = @P11_KIT_CFLAGS@ +P11_KIT_LIBS = @P11_KIT_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PARSE_DATETIME_BISON = @PARSE_DATETIME_BISON@ +PATCH_VERSION = @PATCH_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKCS12_ITER_COUNT = @PKCS12_ITER_COUNT@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PMCCABE = @PMCCABE@ +POSUB = @POSUB@ +PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ +PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ +PRIPTR_PREFIX = @PRIPTR_PREFIX@ +PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ +PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +REPLACE_ACCESS = @REPLACE_ACCESS@ +REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@ +REPLACE_BTOWC = @REPLACE_BTOWC@ +REPLACE_CALLOC = @REPLACE_CALLOC@ +REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHOWN = @REPLACE_CHOWN@ +REPLACE_CLOSE = @REPLACE_CLOSE@ +REPLACE_CREAT = @REPLACE_CREAT@ +REPLACE_CTIME = @REPLACE_CTIME@ +REPLACE_DPRINTF = @REPLACE_DPRINTF@ +REPLACE_DUP = @REPLACE_DUP@ +REPLACE_DUP2 = @REPLACE_DUP2@ +REPLACE_DUPLOCALE = @REPLACE_DUPLOCALE@ +REPLACE_EXECL = @REPLACE_EXECL@ +REPLACE_EXECLE = @REPLACE_EXECLE@ +REPLACE_EXECLP = @REPLACE_EXECLP@ +REPLACE_EXECV = @REPLACE_EXECV@ +REPLACE_EXECVE = @REPLACE_EXECVE@ +REPLACE_EXECVP = @REPLACE_EXECVP@ +REPLACE_EXECVPE = @REPLACE_EXECVPE@ +REPLACE_FACCESSAT = @REPLACE_FACCESSAT@ +REPLACE_FCHMODAT = @REPLACE_FCHMODAT@ +REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@ +REPLACE_FCLOSE = @REPLACE_FCLOSE@ +REPLACE_FCNTL = @REPLACE_FCNTL@ +REPLACE_FDOPEN = @REPLACE_FDOPEN@ +REPLACE_FFLUSH = @REPLACE_FFLUSH@ +REPLACE_FFSLL = @REPLACE_FFSLL@ +REPLACE_FOPEN = @REPLACE_FOPEN@ +REPLACE_FPRINTF = @REPLACE_FPRINTF@ +REPLACE_FPURGE = @REPLACE_FPURGE@ +REPLACE_FREE = @REPLACE_FREE@ +REPLACE_FREELOCALE = @REPLACE_FREELOCALE@ +REPLACE_FREOPEN = @REPLACE_FREOPEN@ +REPLACE_FSEEK = @REPLACE_FSEEK@ +REPLACE_FSEEKO = @REPLACE_FSEEKO@ +REPLACE_FSTAT = @REPLACE_FSTAT@ +REPLACE_FSTATAT = @REPLACE_FSTATAT@ +REPLACE_FTELL = @REPLACE_FTELL@ +REPLACE_FTELLO = @REPLACE_FTELLO@ +REPLACE_FTRUNCATE = @REPLACE_FTRUNCATE@ +REPLACE_FUTIMENS = @REPLACE_FUTIMENS@ +REPLACE_GAI_STRERROR = @REPLACE_GAI_STRERROR@ +REPLACE_GETADDRINFO = @REPLACE_GETADDRINFO@ +REPLACE_GETCWD = @REPLACE_GETCWD@ +REPLACE_GETDELIM = @REPLACE_GETDELIM@ +REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@ +REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@ +REPLACE_GETGROUPS = @REPLACE_GETGROUPS@ +REPLACE_GETLINE = @REPLACE_GETLINE@ +REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@ +REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@ +REPLACE_GETPASS = @REPLACE_GETPASS@ +REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@ +REPLACE_GMTIME = @REPLACE_GMTIME@ +REPLACE_INET_NTOP = @REPLACE_INET_NTOP@ +REPLACE_INET_PTON = @REPLACE_INET_PTON@ +REPLACE_INITSTATE = @REPLACE_INITSTATE@ +REPLACE_IOCTL = @REPLACE_IOCTL@ +REPLACE_ISATTY = @REPLACE_ISATTY@ +REPLACE_ITOLD = @REPLACE_ITOLD@ +REPLACE_LCHOWN = @REPLACE_LCHOWN@ +REPLACE_LINK = @REPLACE_LINK@ +REPLACE_LINKAT = @REPLACE_LINKAT@ +REPLACE_LOCALECONV = @REPLACE_LOCALECONV@ +REPLACE_LOCALTIME = @REPLACE_LOCALTIME@ +REPLACE_LOCALTIME_R = @REPLACE_LOCALTIME_R@ +REPLACE_LSEEK = @REPLACE_LSEEK@ +REPLACE_LSTAT = @REPLACE_LSTAT@ +REPLACE_MALLOC = @REPLACE_MALLOC@ +REPLACE_MBRLEN = @REPLACE_MBRLEN@ +REPLACE_MBRTOWC = @REPLACE_MBRTOWC@ +REPLACE_MBSINIT = @REPLACE_MBSINIT@ +REPLACE_MBSNRTOWCS = @REPLACE_MBSNRTOWCS@ +REPLACE_MBSRTOWCS = @REPLACE_MBSRTOWCS@ +REPLACE_MBSTATE_T = @REPLACE_MBSTATE_T@ +REPLACE_MBTOWC = @REPLACE_MBTOWC@ +REPLACE_MEMCHR = @REPLACE_MEMCHR@ +REPLACE_MEMMEM = @REPLACE_MEMMEM@ +REPLACE_MKDIR = @REPLACE_MKDIR@ +REPLACE_MKFIFO = @REPLACE_MKFIFO@ +REPLACE_MKFIFOAT = @REPLACE_MKFIFOAT@ +REPLACE_MKNOD = @REPLACE_MKNOD@ +REPLACE_MKNODAT = @REPLACE_MKNODAT@ +REPLACE_MKSTEMP = @REPLACE_MKSTEMP@ +REPLACE_MKTIME = @REPLACE_MKTIME@ +REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@ +REPLACE_NEWLOCALE = @REPLACE_NEWLOCALE@ +REPLACE_NL_LANGINFO = @REPLACE_NL_LANGINFO@ +REPLACE_NULL = @REPLACE_NULL@ +REPLACE_OBSTACK_PRINTF = @REPLACE_OBSTACK_PRINTF@ +REPLACE_OPEN = @REPLACE_OPEN@ +REPLACE_OPENAT = @REPLACE_OPENAT@ +REPLACE_PERROR = @REPLACE_PERROR@ +REPLACE_POPEN = @REPLACE_POPEN@ +REPLACE_POSIX_MEMALIGN = @REPLACE_POSIX_MEMALIGN@ +REPLACE_PREAD = @REPLACE_PREAD@ +REPLACE_PRINTF = @REPLACE_PRINTF@ +REPLACE_PSELECT = @REPLACE_PSELECT@ +REPLACE_PTHREAD_ATTR_DESTROY = @REPLACE_PTHREAD_ATTR_DESTROY@ +REPLACE_PTHREAD_ATTR_GETDETACHSTATE = @REPLACE_PTHREAD_ATTR_GETDETACHSTATE@ +REPLACE_PTHREAD_ATTR_INIT = @REPLACE_PTHREAD_ATTR_INIT@ +REPLACE_PTHREAD_ATTR_SETDETACHSTATE = @REPLACE_PTHREAD_ATTR_SETDETACHSTATE@ +REPLACE_PTHREAD_CONDATTR_DESTROY = @REPLACE_PTHREAD_CONDATTR_DESTROY@ +REPLACE_PTHREAD_CONDATTR_INIT = @REPLACE_PTHREAD_CONDATTR_INIT@ +REPLACE_PTHREAD_COND_BROADCAST = @REPLACE_PTHREAD_COND_BROADCAST@ +REPLACE_PTHREAD_COND_DESTROY = @REPLACE_PTHREAD_COND_DESTROY@ +REPLACE_PTHREAD_COND_INIT = @REPLACE_PTHREAD_COND_INIT@ +REPLACE_PTHREAD_COND_SIGNAL = @REPLACE_PTHREAD_COND_SIGNAL@ +REPLACE_PTHREAD_COND_TIMEDWAIT = @REPLACE_PTHREAD_COND_TIMEDWAIT@ +REPLACE_PTHREAD_COND_WAIT = @REPLACE_PTHREAD_COND_WAIT@ +REPLACE_PTHREAD_CREATE = @REPLACE_PTHREAD_CREATE@ +REPLACE_PTHREAD_DETACH = @REPLACE_PTHREAD_DETACH@ +REPLACE_PTHREAD_EQUAL = @REPLACE_PTHREAD_EQUAL@ +REPLACE_PTHREAD_EXIT = @REPLACE_PTHREAD_EXIT@ +REPLACE_PTHREAD_GETSPECIFIC = @REPLACE_PTHREAD_GETSPECIFIC@ +REPLACE_PTHREAD_JOIN = @REPLACE_PTHREAD_JOIN@ +REPLACE_PTHREAD_KEY_CREATE = @REPLACE_PTHREAD_KEY_CREATE@ +REPLACE_PTHREAD_KEY_DELETE = @REPLACE_PTHREAD_KEY_DELETE@ +REPLACE_PTHREAD_MUTEXATTR_DESTROY = @REPLACE_PTHREAD_MUTEXATTR_DESTROY@ +REPLACE_PTHREAD_MUTEXATTR_GETROBUST = @REPLACE_PTHREAD_MUTEXATTR_GETROBUST@ +REPLACE_PTHREAD_MUTEXATTR_GETTYPE = @REPLACE_PTHREAD_MUTEXATTR_GETTYPE@ +REPLACE_PTHREAD_MUTEXATTR_INIT = @REPLACE_PTHREAD_MUTEXATTR_INIT@ +REPLACE_PTHREAD_MUTEXATTR_SETROBUST = @REPLACE_PTHREAD_MUTEXATTR_SETROBUST@ +REPLACE_PTHREAD_MUTEXATTR_SETTYPE = @REPLACE_PTHREAD_MUTEXATTR_SETTYPE@ +REPLACE_PTHREAD_MUTEX_DESTROY = @REPLACE_PTHREAD_MUTEX_DESTROY@ +REPLACE_PTHREAD_MUTEX_INIT = @REPLACE_PTHREAD_MUTEX_INIT@ +REPLACE_PTHREAD_MUTEX_LOCK = @REPLACE_PTHREAD_MUTEX_LOCK@ +REPLACE_PTHREAD_MUTEX_TIMEDLOCK = @REPLACE_PTHREAD_MUTEX_TIMEDLOCK@ +REPLACE_PTHREAD_MUTEX_TRYLOCK = @REPLACE_PTHREAD_MUTEX_TRYLOCK@ +REPLACE_PTHREAD_MUTEX_UNLOCK = @REPLACE_PTHREAD_MUTEX_UNLOCK@ +REPLACE_PTHREAD_ONCE = @REPLACE_PTHREAD_ONCE@ +REPLACE_PTHREAD_RWLOCKATTR_DESTROY = @REPLACE_PTHREAD_RWLOCKATTR_DESTROY@ +REPLACE_PTHREAD_RWLOCKATTR_INIT = @REPLACE_PTHREAD_RWLOCKATTR_INIT@ +REPLACE_PTHREAD_RWLOCK_DESTROY = @REPLACE_PTHREAD_RWLOCK_DESTROY@ +REPLACE_PTHREAD_RWLOCK_INIT = @REPLACE_PTHREAD_RWLOCK_INIT@ +REPLACE_PTHREAD_RWLOCK_RDLOCK = @REPLACE_PTHREAD_RWLOCK_RDLOCK@ +REPLACE_PTHREAD_RWLOCK_TIMEDRDLOCK = @REPLACE_PTHREAD_RWLOCK_TIMEDRDLOCK@ +REPLACE_PTHREAD_RWLOCK_TIMEDWRLOCK = @REPLACE_PTHREAD_RWLOCK_TIMEDWRLOCK@ +REPLACE_PTHREAD_RWLOCK_TRYRDLOCK = @REPLACE_PTHREAD_RWLOCK_TRYRDLOCK@ +REPLACE_PTHREAD_RWLOCK_TRYWRLOCK = @REPLACE_PTHREAD_RWLOCK_TRYWRLOCK@ +REPLACE_PTHREAD_RWLOCK_UNLOCK = @REPLACE_PTHREAD_RWLOCK_UNLOCK@ +REPLACE_PTHREAD_RWLOCK_WRLOCK = @REPLACE_PTHREAD_RWLOCK_WRLOCK@ +REPLACE_PTHREAD_SELF = @REPLACE_PTHREAD_SELF@ +REPLACE_PTHREAD_SETSPECIFIC = @REPLACE_PTHREAD_SETSPECIFIC@ +REPLACE_PTHREAD_SIGMASK = @REPLACE_PTHREAD_SIGMASK@ +REPLACE_PTHREAD_SPIN_DESTROY = @REPLACE_PTHREAD_SPIN_DESTROY@ +REPLACE_PTHREAD_SPIN_INIT = @REPLACE_PTHREAD_SPIN_INIT@ +REPLACE_PTHREAD_SPIN_LOCK = @REPLACE_PTHREAD_SPIN_LOCK@ +REPLACE_PTHREAD_SPIN_TRYLOCK = @REPLACE_PTHREAD_SPIN_TRYLOCK@ +REPLACE_PTHREAD_SPIN_UNLOCK = @REPLACE_PTHREAD_SPIN_UNLOCK@ +REPLACE_PTSNAME = @REPLACE_PTSNAME@ +REPLACE_PTSNAME_R = @REPLACE_PTSNAME_R@ +REPLACE_PUTENV = @REPLACE_PUTENV@ +REPLACE_PWRITE = @REPLACE_PWRITE@ +REPLACE_QSORT_R = @REPLACE_QSORT_R@ +REPLACE_RAISE = @REPLACE_RAISE@ +REPLACE_RANDOM = @REPLACE_RANDOM@ +REPLACE_RANDOM_R = @REPLACE_RANDOM_R@ +REPLACE_READ = @REPLACE_READ@ +REPLACE_READLINK = @REPLACE_READLINK@ +REPLACE_READLINKAT = @REPLACE_READLINKAT@ +REPLACE_REALLOC = @REPLACE_REALLOC@ +REPLACE_REALLOCARRAY = @REPLACE_REALLOCARRAY@ +REPLACE_REALPATH = @REPLACE_REALPATH@ +REPLACE_REMOVE = @REPLACE_REMOVE@ +REPLACE_RENAME = @REPLACE_RENAME@ +REPLACE_RENAMEAT = @REPLACE_RENAMEAT@ +REPLACE_RMDIR = @REPLACE_RMDIR@ +REPLACE_SCHED_YIELD = @REPLACE_SCHED_YIELD@ +REPLACE_SELECT = @REPLACE_SELECT@ +REPLACE_SETENV = @REPLACE_SETENV@ +REPLACE_SETLOCALE = @REPLACE_SETLOCALE@ +REPLACE_SETSTATE = @REPLACE_SETSTATE@ +REPLACE_SLEEP = @REPLACE_SLEEP@ +REPLACE_SNPRINTF = @REPLACE_SNPRINTF@ +REPLACE_SPRINTF = @REPLACE_SPRINTF@ +REPLACE_STAT = @REPLACE_STAT@ +REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@ +REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@ +REPLACE_STPNCPY = @REPLACE_STPNCPY@ +REPLACE_STRCASESTR = @REPLACE_STRCASESTR@ +REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@ +REPLACE_STRDUP = @REPLACE_STRDUP@ +REPLACE_STRERROR = @REPLACE_STRERROR@ +REPLACE_STRERRORNAME_NP = @REPLACE_STRERRORNAME_NP@ +REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ +REPLACE_STRFTIME = @REPLACE_STRFTIME@ +REPLACE_STRNCAT = @REPLACE_STRNCAT@ +REPLACE_STRNDUP = @REPLACE_STRNDUP@ +REPLACE_STRNLEN = @REPLACE_STRNLEN@ +REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ +REPLACE_STRSTR = @REPLACE_STRSTR@ +REPLACE_STRTOD = @REPLACE_STRTOD@ +REPLACE_STRTOIMAX = @REPLACE_STRTOIMAX@ +REPLACE_STRTOK_R = @REPLACE_STRTOK_R@ +REPLACE_STRTOL = @REPLACE_STRTOL@ +REPLACE_STRTOLD = @REPLACE_STRTOLD@ +REPLACE_STRTOLL = @REPLACE_STRTOLL@ +REPLACE_STRTOUL = @REPLACE_STRTOUL@ +REPLACE_STRTOULL = @REPLACE_STRTOULL@ +REPLACE_STRTOUMAX = @REPLACE_STRTOUMAX@ +REPLACE_STRUCT_LCONV = @REPLACE_STRUCT_LCONV@ +REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@ +REPLACE_SYMLINK = @REPLACE_SYMLINK@ +REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@ +REPLACE_TIMEGM = @REPLACE_TIMEGM@ +REPLACE_TMPFILE = @REPLACE_TMPFILE@ +REPLACE_TRUNCATE = @REPLACE_TRUNCATE@ +REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@ +REPLACE_TZSET = @REPLACE_TZSET@ +REPLACE_UNLINK = @REPLACE_UNLINK@ +REPLACE_UNLINKAT = @REPLACE_UNLINKAT@ +REPLACE_UNSETENV = @REPLACE_UNSETENV@ +REPLACE_USLEEP = @REPLACE_USLEEP@ +REPLACE_UTIMENSAT = @REPLACE_UTIMENSAT@ +REPLACE_VASPRINTF = @REPLACE_VASPRINTF@ +REPLACE_VDPRINTF = @REPLACE_VDPRINTF@ +REPLACE_VFPRINTF = @REPLACE_VFPRINTF@ +REPLACE_VPRINTF = @REPLACE_VPRINTF@ +REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@ +REPLACE_VSPRINTF = @REPLACE_VSPRINTF@ +REPLACE_WCRTOMB = @REPLACE_WCRTOMB@ +REPLACE_WCSFTIME = @REPLACE_WCSFTIME@ +REPLACE_WCSNRTOMBS = @REPLACE_WCSNRTOMBS@ +REPLACE_WCSRTOMBS = @REPLACE_WCSRTOMBS@ +REPLACE_WCSTOK = @REPLACE_WCSTOK@ +REPLACE_WCSWIDTH = @REPLACE_WCSWIDTH@ +REPLACE_WCTOB = @REPLACE_WCTOB@ +REPLACE_WCTOMB = @REPLACE_WCTOMB@ +REPLACE_WCWIDTH = @REPLACE_WCWIDTH@ +REPLACE_WRITE = @REPLACE_WRITE@ +SED = @SED@ +SERVENT_LIB = @SERVENT_LIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ +SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +STDALIGN_H = @STDALIGN_H@ +STDBOOL_H = @STDBOOL_H@ +STDDEF_H = @STDDEF_H@ +STDINT_H = @STDINT_H@ +STRIP = @STRIP@ +SYS_IOCTL_H_HAVE_WINSOCK2_H = @SYS_IOCTL_H_HAVE_WINSOCK2_H@ +SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @SYS_IOCTL_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +SYS_TIME_H_DEFINES_STRUCT_TIMESPEC = @SYS_TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_STRUCT_TIMESPEC = @TIME_H_DEFINES_STRUCT_TIMESPEC@ +TIME_H_DEFINES_TIME_UTC = @TIME_H_DEFINES_TIME_UTC@ +TROUSERS_LIB = @TROUSERS_LIB@ +TSS2_CFLAGS = @TSS2_CFLAGS@ +TSS2_LIBS = @TSS2_LIBS@ +TSS_CFLAGS = @TSS_CFLAGS@ +TSS_LIBS = @TSS_LIBS@ +UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ +UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ +UNBOUND_CFLAGS = @UNBOUND_CFLAGS@ +UNBOUND_LIBS = @UNBOUND_LIBS@ +UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ +UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ +UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@ +UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ +UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ +USE_NLS = @USE_NLS@ +VALGRIND = @VALGRIND@ +VALGRINDFLAGS = @VALGRINDFLAGS@ +VALGRIND_PROGRAM = @VALGRIND_PROGRAM@ +VERSION = @VERSION@ +WARN_CFLAGS = @WARN_CFLAGS@ +WCHAR_T_SUFFIX = @WCHAR_T_SUFFIX@ +WERROR_CFLAGS = @WERROR_CFLAGS@ +WINDOWS_64_BIT_OFF_T = @WINDOWS_64_BIT_OFF_T@ +WINDOWS_64_BIT_ST_SIZE = @WINDOWS_64_BIT_ST_SIZE@ +WINDOWS_STAT_INODES = @WINDOWS_STAT_INODES@ +WINDOWS_STAT_TIMESPEC = @WINDOWS_STAT_TIMESPEC@ +WINT_T_SUFFIX = @WINT_T_SUFFIX@ +WSTACK_CFLAGS = @WSTACK_CFLAGS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +YIELD_LIB = @YIELD_LIB@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_cv_sizeof_time_t = @ac_cv_sizeof_time_t@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +ggl_LIBOBJS = @ggl_LIBOBJS@ +ggl_LTLIBOBJS = @ggl_LTLIBOBJS@ +ggltests_LIBOBJS = @ggltests_LIBOBJS@ +ggltests_LTLIBOBJS = @ggltests_LTLIBOBJS@ +ggltests_WITNESS = @ggltests_WITNESS@ +gl_LIBOBJS = @gl_LIBOBJS@ +gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gltests_LIBOBJS = @gltests_LIBOBJS@ +gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ +gltests_WITNESS = @gltests_WITNESS@ +gnutls_so = @gnutls_so@ +guile_snarf = @guile_snarf@ +guileextensiondir = @guileextensiondir@ +guilesiteccachedir = @guilesiteccachedir@ +guilesitedir = @guilesitedir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ifGNUmake = @ifGNUmake@ +ifnGNUmake = @ifnGNUmake@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +maybe_guileextensiondir = @maybe_guileextensiondir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +unistring_LIBOBJS = @unistring_LIBOBJS@ +unistring_LTLIBOBJS = @unistring_LTLIBOBJS@ +unistringtests_LIBOBJS = @unistringtests_LIBOBJS@ +unistringtests_LTLIBOBJS = @unistringtests_LTLIBOBJS@ +unistringtests_WITNESS = @unistringtests_WITNESS@ +AM_CFLAGS = $(WERROR_CFLAGS) $(WSTACK_CFLAGS) $(WARN_CFLAGS) $(NETTLE_CFLAGS) \ + $(LIBTASN1_CFLAGS) $(LIBIDN2_CFLAGS) $(P11_KIT_CFLAGS) $(LIBZSTD_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) + +COMMON_LINK_FLAGS = $(CODE_COVERAGE_LDFLAGS) +V_GPERF = $(V_GPERF_@AM_V@) +V_GPERF_ = $(V_GPERF_@AM_DEFAULT_V@) +V_GPERF_0 = @echo " GPERF " $@; +AM_CPPFLAGS = -DASN1_BUILDING \ + -I$(srcdir)/../../gl \ + -I$(builddir)/../../gl \ + -I$(srcdir)/.. + +noinst_LTLIBRARIES = libminitasn1.la +libminitasn1_la_SOURCES = libtasn1.h gstr.h int.h parser_aux.h \ + structure.h element.h decoding.c gstr.c errors.c parser_aux.c \ + structure.c element.c coding.c version.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/lib/common.mk $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/minitasn1/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/minitasn1/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/lib/common.mk $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libminitasn1.la: $(libminitasn1_la_OBJECTS) $(libminitasn1_la_DEPENDENCIES) $(EXTRA_libminitasn1_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libminitasn1_la_OBJECTS) $(libminitasn1_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/coding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decoding.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/element.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_aux.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/structure.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/coding.Plo + -rm -f ./$(DEPDIR)/decoding.Plo + -rm -f ./$(DEPDIR)/element.Plo + -rm -f ./$(DEPDIR)/errors.Plo + -rm -f ./$(DEPDIR)/gstr.Plo + -rm -f ./$(DEPDIR)/parser_aux.Plo + -rm -f ./$(DEPDIR)/structure.Plo + -rm -f ./$(DEPDIR)/version.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/coding.Plo + -rm -f ./$(DEPDIR)/decoding.Plo + -rm -f ./$(DEPDIR)/element.Plo + -rm -f ./$(DEPDIR)/errors.Plo + -rm -f ./$(DEPDIR)/gstr.Plo + -rm -f ./$(DEPDIR)/parser_aux.Plo + -rm -f ./$(DEPDIR)/structure.Plo + -rm -f ./$(DEPDIR)/version.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-noinstLTLIBRARIES \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/minitasn1/coding.c b/lib/minitasn1/coding.c new file mode 100644 index 0000000..5a947a7 --- /dev/null +++ b/lib/minitasn1/coding.c @@ -0,0 +1,1413 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/*****************************************************/ +/* File: coding.c */ +/* Description: Functions to create a DER coding of */ +/* an ASN1 type. */ +/*****************************************************/ + +#include <int.h> +#include "parser_aux.h" +#include <gstr.h> +#include "element.h" +#include "minmax.h" +#include <structure.h> + +#define MAX_TAG_LEN 16 + +/******************************************************/ +/* Function : _asn1_error_description_value_not_found */ +/* Description: creates the ErrorDescription string */ +/* for the ASN1_VALUE_NOT_FOUND error. */ +/* Parameters: */ +/* node: node of the tree where the value is NULL. */ +/* ErrorDescription: string returned. */ +/* Return: */ +/******************************************************/ +static void +_asn1_error_description_value_not_found (asn1_node node, + char *ErrorDescription) +{ + + if (ErrorDescription == NULL) + return; + + Estrcpy (ErrorDescription, ":: value of element '"); + _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), + ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); + Estrcat (ErrorDescription, "' not found"); + +} + +/** + * asn1_length_der: + * @len: value to convert. + * @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. + * + * To know the size of the DER encoding use a %NULL value for @der. + **/ +void +asn1_length_der (unsigned long int len, unsigned char *der, int *der_len) +{ + int k; + unsigned char temp[ASN1_MAX_LENGTH_SIZE]; +#if SIZEOF_UNSIGNED_LONG_INT > 8 + len &= 0xFFFFFFFFFFFFFFFF; +#endif + + if (len < 128) + { + /* short form */ + if (der != NULL) + der[0] = (unsigned char) len; + *der_len = 1; + } + else + { + /* Long form */ + k = 0; + while (len) + { + temp[k++] = len & 0xFF; + len = len >> 8; + } + *der_len = k + 1; + if (der != NULL) + { + der[0] = ((unsigned char) k & 0x7F) + 128; + while (k--) + der[*der_len - 1 - k] = temp[k]; + } + } +} + +/******************************************************/ +/* 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. */ +/* ans: string returned. */ +/* ans_len: number of meaningful bytes of ANS */ +/* (ans[0]..ans[ans_len-1]). */ +/* Return: */ +/******************************************************/ +static void +_asn1_tag_der (unsigned char class, unsigned int tag_value, + unsigned char ans[ASN1_MAX_TAG_SIZE], int *ans_len) +{ + int k; + unsigned char temp[ASN1_MAX_TAG_SIZE]; + + if (tag_value < 31) + { + /* short form */ + ans[0] = (class & 0xE0) + ((unsigned char) (tag_value & 0x1F)); + *ans_len = 1; + } + else + { + /* Long form */ + ans[0] = (class & 0xE0) + 31; + k = 0; + while (tag_value != 0) + { + temp[k++] = tag_value & 0x7F; + tag_value >>= 7; + + if (k > ASN1_MAX_TAG_SIZE - 1) + break; /* will not encode larger tags */ + } + *ans_len = k + 1; + while (k--) + ans[*ans_len - 1 - k] = temp[k] + 128; + ans[*ans_len - 1] -= 128; + } +} + +/** + * asn1_octet_der: + * @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. + * + * 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, + unsigned char *der, int *der_len) +{ + int len_len; + + 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 (ASN1_ETYPE_) + * @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 */ +/* type (length included). */ +/* Parameters: */ +/* str: TIME null-terminated string. */ +/* der: string returned. */ +/* der_len: number of meaningful bytes of DER */ +/* (der[0]..der[ans_len-1]). Initially it */ +/* if must store the lenght of DER. */ +/* Return: */ +/* ASN1_MEM_ERROR when DER isn't big enough */ +/* ASN1_SUCCESS otherwise */ +/******************************************************/ +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 (str_len, (max_len > 0) ? der : NULL, &len_len); + + 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; + + return ASN1_SUCCESS; +} + + +/* +void +_asn1_get_utctime_der(unsigned char *der,int *der_len,unsigned char *str) +{ + int len_len,str_len; + char temp[20]; + + if(str==NULL) return; + str_len=asn1_get_length_der(der,*der_len,&len_len); + if (str_len<0) return; + memcpy(temp,der+len_len,str_len); + *der_len=str_len+len_len; + switch(str_len) + { + case 11: + temp[10]=0; + strcat(temp,"00+0000"); + break; + case 13: + temp[12]=0; + strcat(temp,"+0000"); + break; + case 15: + temp[15]=0; + memmove(temp+12,temp+10,6); + temp[10]=temp[11]='0'; + break; + case 17: + temp[17]=0; + break; + default: + return; + } + strcpy(str,temp); +} +*/ + +static +void encode_val(uint64_t val, unsigned char *der, int max_len, int *der_len) +{ + int first, k; + unsigned char bit7; + + first = 0; + for (k = sizeof(val); k >= 0; k--) + { + bit7 = (val >> (k * 7)) & 0x7F; + if (bit7 || first || !k) + { + if (k) + bit7 |= 0x80; + if (max_len > (*der_len)) + der[*der_len] = bit7; + (*der_len)++; + first = 1; + } + } +} + +/******************************************************/ +/* Function : _asn1_object_id_der */ +/* Description: creates the DER coding for an */ +/* OBJECT IDENTIFIER type (length included). */ +/* Parameters: */ +/* str: OBJECT IDENTIFIER null-terminated string. */ +/* der: string returned. */ +/* der_len: number of meaningful bytes of DER */ +/* (der[0]..der[ans_len-1]). Initially it */ +/* must store the length of DER. */ +/* Return: */ +/* ASN1_MEM_ERROR when DER isn't big enough */ +/* ASN1_SUCCESS if succesful */ +/* or an error value. */ +/******************************************************/ +static int +_asn1_object_id_der (const char *str, unsigned char *der, int *der_len) +{ + int len_len, counter, max_len; + char *temp, *n_end, *n_start; + uint64_t val, val1 = 0; + int str_len = _asn1_strlen (str); + + max_len = *der_len; + *der_len = 0; + + if (der == NULL && max_len > 0) + return ASN1_VALUE_NOT_VALID; + + temp = malloc (str_len + 2); + if (temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + memcpy (temp, str, str_len); + temp[str_len] = '.'; + temp[str_len + 1] = 0; + + counter = 0; + n_start = temp; + while ((n_end = strchr (n_start, '.'))) + { + *n_end = 0; + val = _asn1_strtou64 (n_start, NULL, 10); + counter++; + + if (counter == 1) + { + val1 = val; + } + else if (counter == 2) + { + uint64_t val0; + + if (val1 > 2) + { + free(temp); + return ASN1_VALUE_NOT_VALID; + } + else if ((val1 == 0 || val1 == 1) && val > 39) + { + free(temp); + return ASN1_VALUE_NOT_VALID; + } + + val0 = 40 * val1 + val; + encode_val(val0, der, max_len, der_len); + } + else + { + encode_val(val, der, max_len, der_len); + } + n_start = n_end + 1; + } + + asn1_length_der (*der_len, NULL, &len_len); + if (max_len >= (*der_len + len_len)) + { + memmove (der + len_len, der, *der_len); + asn1_length_der (*der_len, der, &len_len); + } + *der_len += len_len; + + free (temp); + + if (max_len < (*der_len)) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + +/** + * asn1_object_id_der: + * @str: An object identifier in numeric, dot format. + * @der: buffer to hold the returned encoding (may be %NULL). + * @der_len: initially the size of @der; will hold the final size. + * @flags: must be zero + * + * Creates the DER encoding of the provided object identifier. + * + * Returns: %ASN1_SUCCESS if DER encoding was OK, %ASN1_VALUE_NOT_VALID + * if @str is not a valid OID, %ASN1_MEM_ERROR if the @der + * vector isn't big enough and in this case @der_len will contain the + * length needed. + **/ +int asn1_object_id_der(const char *str, unsigned char *der, int *der_len, unsigned flags) +{ + unsigned char tag_der[MAX_TAG_LEN]; + int tag_len = 0, r; + int max_len = *der_len; + + *der_len = 0; + + _asn1_tag_der (ETYPE_CLASS (ASN1_ETYPE_OBJECT_ID), ETYPE_TAG (ASN1_ETYPE_OBJECT_ID), + tag_der, &tag_len); + + if (max_len > tag_len) + { + memcpy(der, tag_der, tag_len); + } + max_len -= tag_len; + der += tag_len; + + r = _asn1_object_id_der (str, der, &max_len); + if (r == ASN1_MEM_ERROR || r == ASN1_SUCCESS) + { + *der_len = max_len + tag_len; + } + + return r; +} + +static const unsigned char bit_mask[] = + { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 }; + +/** + * asn1_bit_der: + * @str: BIT string. + * @bit_len: number of meaningful bits in STR. + * @der: string returned. + * @der_len: number of meaningful bytes of DER + * (der[0]..der[ans_len-1]). + * + * 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, + unsigned char *der, int *der_len) +{ + int len_len, len_byte, len_pad; + + if (der == NULL) + return; + + len_byte = bit_len >> 3; + len_pad = 8 - (bit_len & 7); + if (len_pad == 8) + len_pad = 0; + else + len_byte++; + asn1_length_der (len_byte + 1, der, &len_len); + der[len_len] = len_pad; + + if (str) + memcpy (der + len_len + 1, str, len_byte); + der[len_len + len_byte] &= bit_mask[len_pad]; + *der_len = len_byte + len_len + 1; +} + + +/******************************************************/ +/* Function : _asn1_complete_explicit_tag */ +/* Description: add the length coding to the EXPLICIT */ +/* tags. */ +/* Parameters: */ +/* node: pointer to the tree element. */ +/* der: string with the DER coding of the whole tree*/ +/* counter: number of meaningful bytes of DER */ +/* (der[0]..der[*counter-1]). */ +/* max_len: size of der vector */ +/* Return: */ +/* ASN1_MEM_ERROR if der vector isn't big enough, */ +/* otherwise ASN1_SUCCESS. */ +/******************************************************/ +static int +_asn1_complete_explicit_tag (asn1_node node, unsigned char *der, + int *counter, int *max_len) +{ + asn1_node p; + int is_tag_implicit, len2, len3; + unsigned char temp[SIZEOF_UNSIGNED_INT]; + + if (der == NULL && *max_len > 0) + return ASN1_VALUE_NOT_VALID; + + is_tag_implicit = 0; + + 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 + which store buffer positions -- simon@josefsson.org 2002-09-06 + */ + while (p->right) + p = p->right; + while (p && p != node->down->left) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if (p->type & CONST_EXPLICIT) + { + len2 = strtol (p->name, NULL, 10); + _asn1_set_name (p, NULL); + + asn1_length_der (*counter - len2, temp, &len3); + if (len3 <= (*max_len)) + { + memmove (der + len2 + len3, der + len2, + *counter - len2); + memcpy (der + len2, temp, len3); + } + *max_len -= len3; + *counter += len3; + is_tag_implicit = 0; + } + else + { /* CONST_IMPLICIT */ + if (!is_tag_implicit) + { + is_tag_implicit = 1; + } + } + } + p = p->left; + } + } + + if (*max_len < 0) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + +const tag_and_class_st _asn1_tags[] = { + [ASN1_ETYPE_GENERALSTRING] = + {ASN1_TAG_GENERALSTRING, ASN1_CLASS_UNIVERSAL, "type:GENERALSTRING"}, + [ASN1_ETYPE_NUMERIC_STRING] = + {ASN1_TAG_NUMERIC_STRING, ASN1_CLASS_UNIVERSAL, "type:NUMERIC_STR"}, + [ASN1_ETYPE_IA5_STRING] = + {ASN1_TAG_IA5_STRING, ASN1_CLASS_UNIVERSAL, "type:IA5_STR"}, + [ASN1_ETYPE_TELETEX_STRING] = + {ASN1_TAG_TELETEX_STRING, ASN1_CLASS_UNIVERSAL, "type:TELETEX_STR"}, + [ASN1_ETYPE_PRINTABLE_STRING] = + {ASN1_TAG_PRINTABLE_STRING, ASN1_CLASS_UNIVERSAL, "type:PRINTABLE_STR"}, + [ASN1_ETYPE_UNIVERSAL_STRING] = + {ASN1_TAG_UNIVERSAL_STRING, ASN1_CLASS_UNIVERSAL, "type:UNIVERSAL_STR"}, + [ASN1_ETYPE_BMP_STRING] = + {ASN1_TAG_BMP_STRING, ASN1_CLASS_UNIVERSAL, "type:BMP_STR"}, + [ASN1_ETYPE_UTF8_STRING] = + {ASN1_TAG_UTF8_STRING, ASN1_CLASS_UNIVERSAL, "type:UTF8_STR"}, + [ASN1_ETYPE_VISIBLE_STRING] = + {ASN1_TAG_VISIBLE_STRING, ASN1_CLASS_UNIVERSAL, "type:VISIBLE_STR"}, + [ASN1_ETYPE_OCTET_STRING] = + {ASN1_TAG_OCTET_STRING, ASN1_CLASS_UNIVERSAL, "type:OCT_STR"}, + [ASN1_ETYPE_BIT_STRING] = + {ASN1_TAG_BIT_STRING, ASN1_CLASS_UNIVERSAL, "type:BIT_STR"}, + [ASN1_ETYPE_OBJECT_ID] = + {ASN1_TAG_OBJECT_ID, ASN1_CLASS_UNIVERSAL, "type:OBJ_ID"}, + [ASN1_ETYPE_NULL] = {ASN1_TAG_NULL, ASN1_CLASS_UNIVERSAL, "type:NULL"}, + [ASN1_ETYPE_BOOLEAN] = + {ASN1_TAG_BOOLEAN, ASN1_CLASS_UNIVERSAL, "type:BOOLEAN"}, + [ASN1_ETYPE_INTEGER] = + {ASN1_TAG_INTEGER, ASN1_CLASS_UNIVERSAL, "type:INTEGER"}, + [ASN1_ETYPE_ENUMERATED] = + {ASN1_TAG_ENUMERATED, ASN1_CLASS_UNIVERSAL, "type:ENUMERATED"}, + [ASN1_ETYPE_SEQUENCE] = + {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SEQUENCE"}, + [ASN1_ETYPE_SEQUENCE_OF] = + {ASN1_TAG_SEQUENCE, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SEQ_OF"}, + [ASN1_ETYPE_SET] = + {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, "type:SET"}, + [ASN1_ETYPE_SET_OF] = + {ASN1_TAG_SET, ASN1_CLASS_UNIVERSAL | ASN1_CLASS_STRUCTURED, + "type:SET_OF"}, + [ASN1_ETYPE_GENERALIZED_TIME] = + {ASN1_TAG_GENERALIZEDTime, ASN1_CLASS_UNIVERSAL, "type:GENERALIZED_TIME"}, + [ASN1_ETYPE_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 */ +/* Description: creates the DER coding of tags of one */ +/* NODE. */ +/* Parameters: */ +/* node: pointer to the tree element. */ +/* der: string returned */ +/* counter: number of meaningful bytes of DER */ +/* (counter[0]..der[*counter-1]). */ +/* max_len: size of der vector */ +/* Return: */ +/* ASN1_GENERIC_ERROR if the type is unknown, */ +/* ASN1_MEM_ERROR if der vector isn't big enough, */ +/* otherwise ASN1_SUCCESS. */ +/******************************************************/ +static int +_asn1_insert_tag_der (asn1_node node, unsigned char *der, int *counter, + int *max_len) +{ + asn1_node p; + int tag_len, is_tag_implicit; + unsigned char class, class_implicit = 0, temp[MAX(SIZEOF_UNSIGNED_INT * 3 + 1, LTOSTR_MAX_SIZE)]; + unsigned long tag_implicit = 0; + unsigned char tag_der[MAX_TAG_LEN]; + + is_tag_implicit = 0; + + if (node->type & CONST_TAG) + { + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if (p->type & CONST_APPLICATION) + class = ASN1_CLASS_APPLICATION; + else if (p->type & CONST_UNIVERSAL) + class = ASN1_CLASS_UNIVERSAL; + else if (p->type & CONST_PRIVATE) + class = ASN1_CLASS_PRIVATE; + else + class = ASN1_CLASS_CONTEXT_SPECIFIC; + + if (p->type & CONST_EXPLICIT) + { + if (is_tag_implicit) + _asn1_tag_der (class_implicit, tag_implicit, tag_der, + &tag_len); + else + _asn1_tag_der (class | ASN1_CLASS_STRUCTURED, + _asn1_strtoul (p->value, NULL, 10), + tag_der, &tag_len); + + *max_len -= tag_len; + if (der && *max_len >= 0) + memcpy (der + *counter, tag_der, tag_len); + *counter += tag_len; + + _asn1_ltostr (*counter, (char *) temp); + _asn1_set_name (p, (const char *) temp); + + is_tag_implicit = 0; + } + else + { /* CONST_IMPLICIT */ + if (!is_tag_implicit) + { + if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || + (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) + || (type_field (node->type) == ASN1_ETYPE_SET) + || (type_field (node->type) == ASN1_ETYPE_SET_OF)) + class |= ASN1_CLASS_STRUCTURED; + class_implicit = class; + tag_implicit = _asn1_strtoul (p->value, NULL, 10); + is_tag_implicit = 1; + } + } + } + p = p->right; + } + } + + if (is_tag_implicit) + { + _asn1_tag_der (class_implicit, tag_implicit, tag_der, &tag_len); + } + else + { + unsigned type = type_field (node->type); + switch (type) + { + CASE_HANDLED_ETYPES: + _asn1_tag_der (_asn1_tags[type].class, _asn1_tags[type].tag, + tag_der, &tag_len); + break; + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_CHOICE: + case ASN1_ETYPE_ANY: + tag_len = 0; + break; + default: + return ASN1_GENERIC_ERROR; + } + } + + *max_len -= tag_len; + if (der && *max_len >= 0) + memcpy (der + *counter, tag_der, tag_len); + *counter += tag_len; + + if (*max_len < 0) + return ASN1_MEM_ERROR; + + return ASN1_SUCCESS; +} + +/******************************************************/ +/* Function : _asn1_ordering_set */ +/* Description: puts the elements of a SET type in */ +/* the correct order according to DER rules. */ +/* Parameters: */ +/* der: string with the DER coding. */ +/* node: pointer to the SET element. */ +/* Return: */ +/* ASN1_SUCCESS if successful */ +/* or an error value. */ +/******************************************************/ +static int +_asn1_ordering_set (unsigned char *der, int der_len, asn1_node node) +{ + struct vet + { + int end; + unsigned long value; + struct vet *next, *prev; + }; + + int counter, len, len2; + struct vet *first, *last, *p_vet, *p2_vet; + asn1_node p; + unsigned char class, *temp; + unsigned long tag, t; + int err; + + counter = 0; + + if (type_field (node->type) != ASN1_ETYPE_SET) + return ASN1_VALUE_NOT_VALID; + + p = node->down; + while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || + (type_field (p->type) == ASN1_ETYPE_SIZE))) + p = p->right; + + if ((p == NULL) || (p->right == NULL)) + return ASN1_SUCCESS; + + first = last = NULL; + while (p) + { + p_vet = malloc (sizeof (struct vet)); + if (p_vet == NULL) + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } + + p_vet->next = NULL; + p_vet->prev = last; + if (first == NULL) + first = p_vet; + else + last->next = p_vet; + last = p_vet; + + /* tag value calculation */ + err = asn1_get_tag_der (der + counter, der_len - counter, &class, &len2, + &tag); + if (err != ASN1_SUCCESS) + goto error; + + t = ((unsigned int)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) + { + err = ASN1_DER_ERROR; + goto error; + } + counter += len + len2; + + p_vet->end = counter; + p = p->right; + } + + p_vet = first; + + while (p_vet) + { + p2_vet = p_vet->next; + counter = 0; + while (p2_vet) + { + if (p_vet->value > p2_vet->value) + { + /* change position */ + temp = malloc (p_vet->end - counter); + if (temp == NULL) + { + 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); + free (temp); + + tag = p_vet->value; + p_vet->value = p2_vet->value; + p2_vet->value = tag; + + p_vet->end = counter + (p2_vet->end - p_vet->end); + } + counter = p_vet->end; + + p2_vet = p2_vet->next; + p_vet = p_vet->next; + } + + if (p_vet != first) + p_vet->prev->next = NULL; + else + first = NULL; + free (p_vet); + p_vet = first; + } + return ASN1_SUCCESS; + +error: + while (first != NULL) + { + p_vet = first; + first = first->next; + free(p_vet); + } + return err; +} + +struct vet +{ + unsigned char *ptr; + int size; +}; + +static int setof_compar(const void *_e1, const void *_e2) +{ + unsigned length; + const struct vet *e1 = _e1, *e2 = _e2; + int rval; + + /* The encodings of the component values of a set-of value shall + * appear in ascending order, the encodings being compared + * as octet strings with the shorter components being + * padded at their trailing end with 0-octets. + * The padding octets are for comparison purposes and + * do not appear in the encodings. + */ + length = MIN(e1->size, e2->size); + + rval = memcmp(e1->ptr, e2->ptr, length); + if (rval == 0 && e1->size != e2->size) + { + if (e1->size > e2->size) + rval = 1; + else if (e2->size > e1->size) + rval = -1; + } + + return rval; +} + +/******************************************************/ +/* Function : _asn1_ordering_set_of */ +/* Description: puts the elements of a SET OF type in */ +/* the correct order according to DER rules. */ +/* Parameters: */ +/* der: string with the DER coding. */ +/* node: pointer to the SET OF element. */ +/* Return: */ +/* ASN1_SUCCESS if successful */ +/* or an error value. */ +/******************************************************/ +static int +_asn1_ordering_set_of (unsigned char *der, int der_len, asn1_node node) +{ + int counter, len, len2; + struct vet *list = NULL, *tlist; + unsigned list_size = 0; + struct vet *p_vet; + asn1_node p; + unsigned char class; + unsigned i; + unsigned char *out = NULL; + int err; + + counter = 0; + + if (type_field (node->type) != ASN1_ETYPE_SET_OF) + return ASN1_VALUE_NOT_VALID; + + p = node->down; + while (p && ((type_field (p->type) == ASN1_ETYPE_TAG) || + (type_field (p->type) == ASN1_ETYPE_SIZE))) + p = p->right; + if (p == NULL) + return ASN1_VALUE_NOT_VALID; + p = p->right; + + if ((p == NULL) || (p->right == NULL)) + return ASN1_SUCCESS; + + while (p) + { + list_size++; + tlist = realloc (list, list_size*sizeof(struct vet)); + if (tlist == NULL) + { + err = ASN1_MEM_ALLOC_ERROR; + goto error; + } + list = tlist; + p_vet = &list[list_size-1]; + + p_vet->ptr = der+counter; + p_vet->size = 0; + + /* extraction of tag and length */ + if (der_len - counter > 0) + { + err = asn1_get_tag_der (der + counter, der_len - counter, &class, + &len, NULL); + if (err != ASN1_SUCCESS) + goto error; + counter += len; + p_vet->size += len; + + len2 = asn1_get_length_der (der + counter, der_len - counter, &len); + if (len2 < 0) + { + err = ASN1_DER_ERROR; + goto error; + } + counter += len + len2; + p_vet->size += len + len2; + + } + else + { + err = ASN1_DER_ERROR; + goto error; + } + p = p->right; + } + + if (counter > der_len) + { + err = ASN1_DER_ERROR; + goto error; + } + + qsort(list, list_size, sizeof(struct vet), setof_compar); + + out = malloc(der_len); + if (out == NULL) + { + err = ASN1_MEM_ERROR; + goto error; + } + + /* the sum of p_vet->size == der_len */ + counter = 0; + for (i = 0; i < list_size; i++) + { + p_vet = &list[i]; + memcpy(out+counter, p_vet->ptr, p_vet->size); + counter += p_vet->size; + } + memcpy(der, out, der_len); + free(out); + + err = ASN1_SUCCESS; + +error: + free(list); + return err; +} + +/** + * asn1_der_coding: + * @element: pointer to an ASN1 element + * @name: the name of the structure you want to encode (it must be + * inside *POINTER). + * @ider: vector that will contain the DER encoding. DER must be a + * 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 + * string if success. + * + * Creates the DER encoding for the NAME structure (inside *POINTER + * structure). + * + * 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. + **/ +int +asn1_der_coding (asn1_node_const element, const char *name, void *ider, int *len, + char *ErrorDescription) +{ + asn1_node node, p, p2; + unsigned char temp[MAX(LTOSTR_MAX_SIZE, SIZEOF_UNSIGNED_LONG_INT * 3 + 1)]; + int counter, counter_old, len2, len3, move, max_len, max_len_old; + int err; + unsigned char *der = ider; + unsigned char dummy; + + if (ErrorDescription) + ErrorDescription[0] = 0; + + node = asn1_find_node (element, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + /* Node is now a locally allocated variable. + * That is because in some point we modify the + * structure, and I don't know why! --nmav + */ + node = _asn1_copy_structure3 (node); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + max_len = *len; + + if (der == NULL && max_len > 0) + { + err = ASN1_VALUE_NOT_VALID; + goto error; + } + + counter = 0; + move = DOWN; + p = node; + + while (1) + { + + counter_old = counter; + max_len_old = max_len; + if (move != UP) + { + p->start = counter; + err = _asn1_insert_tag_der (p, der, &counter, &max_len); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + } + switch (type_field (p->type)) + { + case ASN1_ETYPE_NULL: + max_len--; + if (der != NULL && max_len >= 0) + der[counter] = 0; + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + if ((p->type & CONST_DEFAULT) && (p->value == NULL)) + { + counter = counter_old; + max_len = max_len_old; + } + else + { + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, + ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + max_len -= 2; + if (der != NULL && max_len >= 0) + { + der[counter++] = 1; + if (p->value[0] == 'F') + der[counter++] = 0; + else + der[counter++] = 0xFF; + } + else + counter += 2; + } + move = RIGHT; + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + if ((p->type & CONST_DEFAULT) && (p->value == NULL)) + { + counter = counter_old; + max_len = max_len_old; + } + else + { + 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 (der != NULL && max_len >= 0) + memcpy (der + counter, p->value, len3 + len2); + counter += len3 + len2; + } + move = RIGHT; + break; + case ASN1_ETYPE_OBJECT_ID: + if ((p->type & CONST_DEFAULT) && (p->value == NULL)) + { + counter = counter_old; + max_len = max_len_old; + } + else + { + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, + ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = max_len; + err = _asn1_object_id_der ((char*)p->value, der ? der + counter : &dummy, &len2); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + + max_len -= len2; + counter += len2; + } + move = RIGHT; + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + if (p->value == NULL) + { + _asn1_error_description_value_not_found (p, ErrorDescription); + err = ASN1_VALUE_NOT_FOUND; + goto error; + } + len2 = max_len; + err = _asn1_time_der (p->value, p->value_len, der ? der + counter : &dummy, &len2); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + + max_len -= len2; + counter += len2; + move = RIGHT; + break; + case ASN1_ETYPE_OCTET_STRING: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_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 (der != NULL && max_len >= 0) + memcpy (der + counter, p->value, len3 + len2); + counter += len3 + len2; + move = RIGHT; + break; + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SET: + if (move != UP) + { + p->tmp_ival = counter; + if (p->down == NULL) + { + move = UP; + continue; + } + else + { + p2 = p->down; + while (p2 && (type_field (p2->type) == ASN1_ETYPE_TAG)) + p2 = p2->right; + if (p2) + { + p = p2; + move = RIGHT; + continue; + } + move = UP; + continue; + } + } + else + { /* move==UP */ + len2 = p->tmp_ival; + p->tmp_ival = 0; + if ((type_field (p->type) == ASN1_ETYPE_SET) && (max_len >= 0)) + { + err = _asn1_ordering_set (der ? der + len2 : &dummy, counter - len2, p); + if (err != ASN1_SUCCESS) + goto error; + } + asn1_length_der (counter - len2, temp, &len3); + max_len -= len3; + if (der != NULL && max_len >= 0) + { + memmove (der + len2 + len3, der + len2, counter - len2); + memcpy (der + len2, temp, len3); + } + counter += len3; + move = RIGHT; + } + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (move != UP) + { + p->tmp_ival = counter; + p = p->down; + while ((type_field (p->type) == ASN1_ETYPE_TAG) + || (type_field (p->type) == ASN1_ETYPE_SIZE)) + p = p->right; + if (p->right) + { + p = p->right; + move = RIGHT; + continue; + } + else + p = _asn1_find_up (p); + move = UP; + } + if (move == UP) + { + len2 = p->tmp_ival; + p->tmp_ival = 0; + if ((type_field (p->type) == ASN1_ETYPE_SET_OF) + && (counter - len2 > 0) && (max_len >= 0)) + { + err = _asn1_ordering_set_of (der ? der + len2 : &dummy, counter - len2, p); + if (err != ASN1_SUCCESS) + goto error; + } + asn1_length_der (counter - len2, temp, &len3); + max_len -= len3; + if (der != NULL && max_len >= 0) + { + memmove (der + len2 + len3, der + len2, counter - len2); + memcpy (der + len2, temp, len3); + } + counter += len3; + move = RIGHT; + } + break; + case ASN1_ETYPE_ANY: + 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; + if (der != NULL && max_len >= 0) + memcpy (der + counter, p->value + len3, len2); + counter += len2; + move = RIGHT; + break; + default: + move = (move == UP) ? RIGHT : DOWN; + break; + } + + if ((move != DOWN) && (counter != counter_old)) + { + p->end = counter - 1; + err = _asn1_complete_explicit_tag (p, der, &counter, &max_len); + if (err != ASN1_SUCCESS && err != ASN1_MEM_ERROR) + goto error; + } + + if (p == node && move != DOWN) + break; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + if (move == RIGHT) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + *len = counter; + + if (max_len < 0) + { + err = ASN1_MEM_ERROR; + goto error; + } + + err = ASN1_SUCCESS; + +error: + asn1_delete_structure (&node); + return err; +} diff --git a/lib/minitasn1/decoding.c b/lib/minitasn1/decoding.c new file mode 100644 index 0000000..378219c --- /dev/null +++ b/lib/minitasn1/decoding.c @@ -0,0 +1,2478 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/*****************************************************/ +/* File: decoding.c */ +/* Description: Functions to manage DER decoding */ +/*****************************************************/ + +#include <int.h> +#include <parser_aux.h> +#include <gstr.h> +#include <structure.h> +#include <element.h> +#include <limits.h> +#include <intprops.h> +#include "c-ctype.h" + +#ifdef DEBUG +# define warn() fprintf(stderr, "%s: %d\n", __func__, __LINE__) +#else +# define warn() +#endif + +#define IS_ERR(len, flags) (len < -1 || ((flags & ASN1_DECODE_FLAG_STRICT_DER) && len < 0)) + +#define HAVE_TWO(x) (x>=2?1:0) + +/* Decoding flags (dflags) used in several decoding functions. + * DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag + * DECODE_FLAG_CONSTRUCTED: The provided buffer is of indefinite encoding (useful + * when no tags are present). + * DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings. + * DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings. + * DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings. + * This is the maximum levels of recursion possible to prevent stack + * exhaustion. + */ + +#define DECODE_FLAG_HAVE_TAG 1 +#define DECODE_FLAG_CONSTRUCTED (1<<1) +#define DECODE_FLAG_LEVEL1 (1<<2) +#define DECODE_FLAG_LEVEL2 (1<<3) +#define DECODE_FLAG_LEVEL3 (1<<4) + +#define DECR_LEN(l, s) do { \ + l -= s; \ + if (l < 0) { \ + warn(); \ + result = ASN1_DER_ERROR; \ + goto cleanup; \ + } \ + } while (0) + +static int +_asn1_get_indefinite_length_string (const unsigned char *der, int der_len, int *len); + +static int +_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len, + unsigned dflags); + +static int +_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len, unsigned dflags); + +static void +_asn1_error_description_tag_error (asn1_node node, char *ErrorDescription) +{ + + Estrcpy (ErrorDescription, ":: tag error near element '"); + _asn1_hierarchical_name (node, ErrorDescription + strlen (ErrorDescription), + ASN1_MAX_ERROR_DESCRIPTION_SIZE - 40); + Estrcat (ErrorDescription, "'"); + +} + +/** + * asn1_get_length_der: + * @der: DER data to decode. + * @der_len: Length of DER data to decode. + * @len: Output variable containing the length of the DER length field. + * + * 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 to fit in a int, or -4 + * when the decoded length value plus @len would exceed @der_len. + **/ +long +asn1_get_length_der (const unsigned char *der, int der_len, int *len) +{ + unsigned int ans; + int k, punt, sum; + + *len = 0; + if (der_len <= 0) + return 0; + + if (!(der[0] & 128)) + { + /* short form */ + *len = 1; + ans = der[0]; + } + else + { + /* Long form */ + k = der[0] & 0x7F; + punt = 1; + if (k) + { /* definite length method */ + ans = 0; + while (punt <= k && punt < der_len) + { + if (INT_MULTIPLY_OVERFLOW (ans, 256)) + return -2; + ans *= 256; + + if (INT_ADD_OVERFLOW (ans, ((unsigned) der[punt]))) + return -2; + ans += der[punt]; + punt++; + } + } + else + { /* indefinite length method */ + *len = punt; + return -1; + } + + *len = punt; + } + + sum = ans; + if (ans >= INT_MAX || INT_ADD_OVERFLOW (sum, (*len))) + return -2; + sum += *len; + + if (sum > der_len) + return -4; + + return ans; +} + +/** + * asn1_get_tag_der: + * @der: DER data to decode. + * @der_len: Length of DER data to decode. + * @cls: Output variable containing decoded class. + * @len: Output variable containing the length of the DER TAG data. + * @tag: Output variable containing the decoded tag (may be %NULL). + * + * Decode the class and TAG from DER code. + * + * Returns: Returns %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_tag_der (const unsigned char *der, int der_len, + unsigned char *cls, int *len, unsigned long *tag) +{ + unsigned int ris; + int punt; + + if (der == NULL || der_len < 2 || len == NULL) + return ASN1_DER_ERROR; + + *cls = der[0] & 0xE0; + if ((der[0] & 0x1F) != 0x1F) + { + /* short form */ + *len = 1; + ris = der[0] & 0x1F; + } + else + { + /* Long form */ + punt = 1; + ris = 0; + while (punt < der_len && der[punt] & 128) + { + + 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; + + 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; +} + +/** + * asn1_get_length_ber: + * @ber: BER data to decode. + * @ber_len: Length of BER data to decode. + * @len: Output variable containing the length of the BER length field. + * + * Extract a length field from BER data. The difference to + * asn1_get_length_der() is that this function will return a length + * even if the value has indefinite encoding. + * + * Returns: Return the decoded length value, or negative value when + * the value was too big. + * + * Since: 2.0 + **/ +long +asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len) +{ + int ret; + long err; + + ret = asn1_get_length_der (ber, ber_len, len); + + if (ret == -1 && ber_len > 1) + { /* indefinite length method */ + err = _asn1_get_indefinite_length_string (ber + 1, ber_len-1, &ret); + if (err != ASN1_SUCCESS) + return -3; + } + + return ret; +} + +/** + * asn1_get_octet_der: + * @der: DER data to decode containing the OCTET SEQUENCE. + * @der_len: The length of the @der data to decode. + * @ret_len: Output variable containing the encoded length of the DER data. + * @str: Pre-allocated output buffer to put decoded OCTET SEQUENCE in. + * @str_size: Length of pre-allocated output buffer. + * @str_len: Output variable containing the length of the contents of the OCTET SEQUENCE. + * + * Extract an OCTET SEQUENCE from DER data. Note that this function + * expects the DER data past the tag field, i.e., the length and + * content octets. + * + * Returns: Returns %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_octet_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, int str_size, + int *str_len) +{ + int len_len = 0; + + if (der_len <= 0) + return ASN1_GENERIC_ERROR; + + *str_len = asn1_get_length_der (der, der_len, &len_len); + + if (*str_len < 0) + return ASN1_DER_ERROR; + + *ret_len = *str_len + len_len; + if (str_size >= *str_len) + { + if (*str_len > 0 && str != NULL) + memcpy (str, der + len_len, *str_len); + } + else + { + return ASN1_MEM_ERROR; + } + + return ASN1_SUCCESS; +} + + +/*- + * _asn1_get_time_der: + * @type: %ASN1_ETYPE_GENERALIZED_TIME or %ASN1_ETYPE_UTC_TIME + * @der: DER data to decode containing the time + * @der_len: Length of DER data to decode. + * @ret_len: Output variable containing the length of the DER data. + * @str: Pre-allocated output buffer to put the textual time in. + * @str_size: Length of pre-allocated output buffer. + * @flags: Zero or %ASN1_DECODE_FLAG_STRICT_DER + * + * Performs basic checks in the DER encoded time object and returns its textual form. + * The textual form will be in the YYYYMMDD000000Z format for GeneralizedTime + * and YYMMDD000000Z for UTCTime. + * + * Returns: %ASN1_SUCCESS on success, or an error. + -*/ +static int +_asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *ret_len, + char *str, int str_size, unsigned flags) +{ + int len_len, str_len; + unsigned i; + unsigned sign_count = 0; + unsigned dot_count = 0; + const unsigned char *p; + + 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) + return ASN1_DER_ERROR; + + /* perform some sanity checks on the data */ + if (str_len < 8) + { + warn(); + return ASN1_TIME_ENCODING_ERROR; + } + + if ((flags & ASN1_DECODE_FLAG_STRICT_DER) && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME)) + { + p = &der[len_len]; + for (i=0;i<(unsigned)(str_len-1);i++) + { + if (c_isdigit(p[i]) == 0) + { + if (type == ASN1_ETYPE_GENERALIZED_TIME) + { + /* tolerate lax encodings */ + if (p[i] == '.' && dot_count == 0) + { + dot_count++; + continue; + } + + /* This is not really valid DER, but there are + * structures using that */ + if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && + (p[i] == '+' || p[i] == '-') && sign_count == 0) + { + sign_count++; + continue; + } + } + + warn(); + return ASN1_TIME_ENCODING_ERROR; + } + } + + if (sign_count == 0 && p[str_len-1] != 'Z') + { + warn(); + return ASN1_TIME_ENCODING_ERROR; + } + } + memcpy (str, der + len_len, str_len); + str[str_len] = 0; + *ret_len = str_len + len_len; + + return ASN1_SUCCESS; +} + +/** + * asn1_get_object_id_der: + * @der: DER data to decode containing the OBJECT IDENTIFIER + * @der_len: Length of DER data to decode. + * @ret_len: Output variable containing the length of the DER data. + * @str: Pre-allocated output buffer to put the textual object id in. + * @str_size: Length of pre-allocated output buffer. + * + * Converts a DER encoded object identifier to its textual form. This + * function expects the DER object identifier without the tag. + * + * Returns: %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len, + char *str, int str_size) +{ + int len_len, len, k; + int leading, parsed; + char temp[LTOSTR_MAX_SIZE]; + uint64_t val, val1, val0; + + *ret_len = 0; + if (str && str_size > 0) + str[0] = 0; /* no oid */ + + if (str == NULL || der_len <= 0) + return ASN1_GENERIC_ERROR; + + len = asn1_get_length_der (der, der_len, &len_len); + + if (len <= 0 || len + len_len > der_len) + return ASN1_DER_ERROR; + + /* leading octet can never be 0x80 */ + if (der[len_len] == 0x80) + return ASN1_DER_ERROR; + + val0 = 0; + + for (k = 0; k < len; k++) + { + if (INT_LEFT_SHIFT_OVERFLOW (val0, 7)) + return ASN1_DER_ERROR; + + val0 <<= 7; + val0 |= der[len_len + k] & 0x7F; + if (!(der[len_len + k] & 0x80)) + break; + } + parsed = ++k; + + /* val0 = (X*40) + Y, X={0,1,2}, Y<=39 when X={0,1} */ + /* X = val, Y = val1 */ + + /* check if X == 0 */ + val = 0; + val1 = val0; + if (val1 > 39) + { + val = 1; + val1 = val0 - 40; + if (val1 > 39) + { + val = 2; + val1 = val0 - 80; + } + } + + _asn1_str_cpy (str, str_size, _asn1_ltostr (val, temp)); + _asn1_str_cat (str, str_size, "."); + _asn1_str_cat (str, str_size, _asn1_ltostr (val1, temp)); + + val = 0; + leading = 1; + for (k = parsed; k < len; k++) + { + /* X.690 mandates that the leading byte must never be 0x80 + */ + if (leading != 0 && der[len_len + k] == 0x80) + return ASN1_DER_ERROR; + leading = 0; + + /* check for wrap around */ + if (INT_LEFT_SHIFT_OVERFLOW (val, 7)) + return ASN1_DER_ERROR; + + 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; + leading = 1; + } + } + + if (INT_ADD_OVERFLOW (len, len_len)) + return ASN1_DER_ERROR; + + *ret_len = len + len_len; + + return ASN1_SUCCESS; +} + +/** + * asn1_get_bit_der: + * @der: DER data to decode containing the BIT SEQUENCE. + * @der_len: Length of DER data to decode. + * @ret_len: Output variable containing the length of the DER data. + * @str: Pre-allocated output buffer to put decoded BIT SEQUENCE in. + * @str_size: Length of pre-allocated output buffer. + * @bit_len: Output variable containing the size of the BIT SEQUENCE. + * + * Extract a BIT SEQUENCE from DER data. + * + * Returns: %ASN1_SUCCESS on success, or an error. + **/ +int +asn1_get_bit_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, int str_size, + int *bit_len) +{ + int len_len = 0, len_byte; + + 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; + + *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) + { + if (len_byte > 0 && str) + memcpy (str, der + len_len + 1, len_byte); + } + else + { + return ASN1_MEM_ERROR; + } + + return ASN1_SUCCESS; +} + +/* tag_len: the total tag length (explicit+inner) + * inner_tag_len: the inner_tag length + */ +static int +_asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, + int *tag_len, int *inner_tag_len, unsigned flags) +{ + asn1_node p; + int counter, len2, len3, is_tag_implicit; + int result; + unsigned long tag, tag_implicit = 0; + unsigned char class, class2, class_implicit = 0; + + if (der_len <= 0) + return ASN1_GENERIC_ERROR; + + counter = is_tag_implicit = 0; + + if (node->type & CONST_TAG) + { + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if (p->type & CONST_APPLICATION) + class2 = ASN1_CLASS_APPLICATION; + else if (p->type & CONST_UNIVERSAL) + class2 = ASN1_CLASS_UNIVERSAL; + else if (p->type & CONST_PRIVATE) + class2 = ASN1_CLASS_PRIVATE; + else + class2 = ASN1_CLASS_CONTEXT_SPECIFIC; + + if (p->type & CONST_EXPLICIT) + { + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + counter += len2; + + if (flags & ASN1_DECODE_FLAG_STRICT_DER) + len3 = + asn1_get_length_der (der + counter, der_len, + &len2); + else + len3 = + asn1_get_length_ber (der + counter, der_len, + &len2); + if (len3 < 0) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + counter += len2; + + if (!is_tag_implicit) + { + if ((class != (class2 | ASN1_CLASS_STRUCTURED)) || + (tag != strtoul ((char *) p->value, NULL, 10))) + return ASN1_TAG_ERROR; + } + else + { /* ASN1_TAG_IMPLICIT */ + if ((class != class_implicit) || (tag != tag_implicit)) + return ASN1_TAG_ERROR; + } + is_tag_implicit = 0; + } + else + { /* ASN1_TAG_IMPLICIT */ + if (!is_tag_implicit) + { + if ((type_field (node->type) == ASN1_ETYPE_SEQUENCE) || + (type_field (node->type) == ASN1_ETYPE_SEQUENCE_OF) + || (type_field (node->type) == ASN1_ETYPE_SET) + || (type_field (node->type) == ASN1_ETYPE_SET_OF)) + class2 |= ASN1_CLASS_STRUCTURED; + class_implicit = class2; + tag_implicit = strtoul ((char *) p->value, NULL, 10); + is_tag_implicit = 1; + } + } + } + p = p->right; + } + } + + if (is_tag_implicit) + { + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + + if ((class != class_implicit) || (tag != tag_implicit)) + { + if (type_field (node->type) == ASN1_ETYPE_OCTET_STRING) + { + class_implicit |= ASN1_CLASS_STRUCTURED; + if ((class != class_implicit) || (tag != tag_implicit)) + return ASN1_TAG_ERROR; + } + else + return ASN1_TAG_ERROR; + } + } + else + { + unsigned type = type_field (node->type); + if (type == ASN1_ETYPE_TAG) + { + *tag_len = 0; + if (inner_tag_len) + *inner_tag_len = 0; + return ASN1_SUCCESS; + } + + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + + switch (type) + { + case ASN1_ETYPE_NULL: + case ASN1_ETYPE_BOOLEAN: + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + case ASN1_ETYPE_OBJECT_ID: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_STRING: + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET: + case ASN1_ETYPE_SET_OF: + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + if ((class != _asn1_tags[type].class) + || (tag != _asn1_tags[type].tag)) + return ASN1_DER_ERROR; + break; + + case ASN1_ETYPE_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 ASN1_ETYPE_ANY: + counter -= len2; + break; + case ASN1_ETYPE_CHOICE: + counter -= len2; + break; + default: + return ASN1_DER_ERROR; + break; + } + } + + counter += len2; + *tag_len = counter; + if (inner_tag_len) + *inner_tag_len = len2; + return ASN1_SUCCESS; + +cleanup: + return result; +} + +static int +extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, + int *ret_len, int *inner_len, unsigned flags) +{ +asn1_node p; +int ris = ASN1_DER_ERROR; + + if (type_field (node->type) == ASN1_ETYPE_CHOICE) + { + p = node->down; + while (p) + { + ris = _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len, flags); + 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, inner_len, flags); +} + +static int +_asn1_delete_not_used (asn1_node node) +{ + asn1_node p, p2; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if (p->type & CONST_NOT_USED) + { + p2 = NULL; + if (p != node) + { + p2 = _asn1_find_left (p); + if (!p2) + p2 = _asn1_find_up (p); + } + asn1_delete_structure (&p); + p = p2; + } + + if (!p) + break; /* reach node */ + + if (p->down) + { + p = p->down; + } + else + { + if (p == node) + p = NULL; + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p->right) + { + p = p->right; + break; + } + } + } + } + } + return ASN1_SUCCESS; +} + +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; + + counter = indefinite = 0; + + while (1) + { + if (HAVE_TWO(der_len) && (der[counter] == 0) && (der[counter + 1] == 0)) + { + counter += 2; + DECR_LEN(der_len, 2); + + indefinite--; + if (indefinite <= 0) + break; + else + continue; + } + + if (asn1_get_tag_der + (der + counter, der_len, &class, &len2, + &tag) != ASN1_SUCCESS) + return ASN1_DER_ERROR; + + DECR_LEN(der_len, len2); + counter += len2; + + 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_node p) +{ + asn1_node p2; + + while (p->right) + { + p2 = p->right; + asn1_delete_structure (&p2); + } +} + + +/** + * asn1_der_decoding2 + * @element: pointer to an ASN1 structure. + * @ider: vector that contains the DER encoding. + * @max_ider_len: pointer to an integer giving the information about the + * maximal number of bytes occupied by *@ider. The real size of the DER + * encoding is returned through this pointer. + * @flags: flags controlling the behaviour of the function. + * @errorDescription: null-terminated string contains details when an + * error occurred. + * + * Fill the structure *@element with values of a DER encoding string. The + * structure must just be created with function asn1_create_element(). + * + * If %ASN1_DECODE_FLAG_ALLOW_PADDING flag is set then the function will ignore + * padding after the decoded DER data. Upon a successful return the value of + * *@max_ider_len will be set to the number of bytes decoded. + * + * If %ASN1_DECODE_FLAG_STRICT_DER flag is set then the function will + * not decode any BER-encoded elements. + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or + * %ASN1_DER_ERROR if the der encoding doesn't match the structure + * name (*@ELEMENT deleted). + **/ +int +asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, + unsigned int flags, char *errorDescription) +{ + asn1_node node, p, p2, p3; + char temp[128]; + int counter, len2, len3, len4, move, ris, tlen; + struct node_tail_cache_st tcache = {NULL, NULL}; + unsigned char class; + unsigned long tag; + int tag_len; + int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len; + int inner_tag_len; + unsigned char *ptmp; + const unsigned char *ptag; + const unsigned char *der = ider; + + node = *element; + + if (errorDescription != NULL) + errorDescription[0] = 0; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if (node->type & CONST_OPTION) + { + result = ASN1_GENERIC_ERROR; + warn(); + goto cleanup; + } + + counter = 0; + move = DOWN; + p = node; + while (1) + { + tag_len = 0; + inner_tag_len = 0; + ris = ASN1_SUCCESS; + if (move != UP) + { + if (p->type & CONST_SET) + { + p2 = _asn1_find_up (p); + len2 = p2->tmp_ival; + if (len2 == -1) + { + if (HAVE_TWO(ider_len) && !der[counter] && !der[counter + 1]) + { + p = p2; + move = UP; + counter += 2; + DECR_LEN(ider_len, 2); + continue; + } + } + else if (counter == len2) + { + p = p2; + move = UP; + continue; + } + else if (counter > len2) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + p2 = p2->down; + while (p2) + { + if ((p2->type & CONST_SET) && (p2->type & CONST_NOT_USED)) + { + ris = + extract_tag_der_recursive (p2, der + counter, + ider_len, &len2, NULL, flags); + if (ris == ASN1_SUCCESS) + { + p2->type &= ~CONST_NOT_USED; + p = p2; + break; + } + } + p2 = p2->right; + } + if (p2 == NULL) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + + /* the position in the DER structure this starts */ + p->start = counter; + p->end = total_len - 1; + + if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) + { + p2 = _asn1_find_up (p); + len2 = p2->tmp_ival; + if (counter == len2) + { + if (p->right) + { + p2 = p->right; + move = RIGHT; + } + else + move = UP; + + if (p->type & CONST_OPTION) + asn1_delete_structure (&p); + + p = p2; + continue; + } + } + + if (type_field (p->type) == ASN1_ETYPE_CHOICE) + { + while (p->down) + { + ris = + extract_tag_der_recursive (p->down, der + counter, + ider_len, &len2, NULL, flags); + + if (ris == ASN1_SUCCESS) + { + delete_unneeded_choice_fields(p->down); + break; + } + else if (ris == ASN1_ERROR_TYPE_ANY) + { + result = ASN1_ERROR_TYPE_ANY; + warn(); + goto cleanup; + } + else + { + p2 = p->down; + asn1_delete_structure (&p2); + } + } + + if (p->down == NULL) + { + if (!(p->type & CONST_OPTION)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + else if (type_field (p->type) != ASN1_ETYPE_CHOICE) + p = p->down; + + p->start = counter; + } + + if ((p->type & CONST_OPTION) || (p->type & CONST_DEFAULT)) + { + p2 = _asn1_find_up (p); + len2 = p2->tmp_ival; + + if ((len2 != -1) && (counter > len2)) + ris = ASN1_TAG_ERROR; + } + + if (ris == ASN1_SUCCESS) + ris = + extract_tag_der_recursive (p, der + counter, ider_len, + &tag_len, &inner_tag_len, flags); + + if (ris != ASN1_SUCCESS) + { + if (p->type & CONST_OPTION) + { + p->type |= CONST_NOT_USED; + move = RIGHT; + } + else if (p->type & CONST_DEFAULT) + { + _asn1_set_value (p, NULL, 0); + move = RIGHT; + } + else + { + if (errorDescription != NULL) + _asn1_error_description_tag_error (p, errorDescription); + + result = ASN1_TAG_ERROR; + warn(); + goto cleanup; + } + } + else + { + DECR_LEN(ider_len, tag_len); + counter += tag_len; + } + } + + if (ris == ASN1_SUCCESS) + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_NULL: + DECR_LEN(ider_len, 1); + if (der[counter]) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + counter++; + move = RIGHT; + break; + case ASN1_ETYPE_BOOLEAN: + DECR_LEN(ider_len, 2); + + if (der[counter++] != 1) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + if (der[counter++] == 0) + _asn1_set_value (p, "F", 1); + else + _asn1_set_value (p, "T", 1); + move = RIGHT; + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + len2 = + asn1_get_length_der (der + counter, ider_len, &len3); + if (len2 < 0) + { + 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 ASN1_ETYPE_OBJECT_ID: + result = + asn1_get_object_id_der (der + counter, ider_len, &len2, + temp, sizeof (temp)); + if (result != ASN1_SUCCESS) + { + 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 ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + result = + _asn1_get_time_der (type_field (p->type), der + counter, ider_len, &len2, temp, + sizeof (temp) - 1, flags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + + tlen = strlen (temp); + if (tlen > 0) + _asn1_set_value (p, temp, tlen); + + counter += len2; + move = RIGHT; + break; + case ASN1_ETYPE_OCTET_STRING: + if (counter < inner_tag_len) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + ptag = der + counter - inner_tag_len; + if ((flags & ASN1_DECODE_FLAG_STRICT_DER) || !(ptag[0] & ASN1_CLASS_STRUCTURED)) + { + if (ptag[0] & ASN1_CLASS_STRUCTURED) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + len2 = + asn1_get_length_der (der + counter, ider_len, &len3); + if (len2 < 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len3+len2); + + _asn1_set_value (p, der + counter, len3 + len2); + counter += len3 + len2; + } + else + { + unsigned dflags = 0, vlen, ber_len; + + if (ptag[0] & ASN1_CLASS_STRUCTURED) + dflags |= DECODE_FLAG_CONSTRUCTED; + + result = _asn1_decode_simple_ber(type_field (p->type), der+counter, ider_len, &ptmp, &vlen, &ber_len, dflags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, ber_len); + + _asn1_set_value_lv (p, ptmp, vlen); + + counter += ber_len; + free(ptmp); + } + move = RIGHT; + break; + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + case ASN1_ETYPE_BIT_STRING: + len2 = + asn1_get_length_der (der + counter, ider_len, &len3); + if (len2 < 0) + { + 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 ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_SET: + if (move == UP) + { + len2 = p->tmp_ival; + p->tmp_ival = 0; + if (len2 == -1) + { /* indefinite length method */ + DECR_LEN(ider_len, 2); + if ((der[counter]) || der[counter + 1]) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + counter += 2; + } + else + { /* definite length method */ + if (len2 != counter) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + move = RIGHT; + } + else + { /* move==DOWN || move==RIGHT */ + len3 = + asn1_get_length_der (der + counter, ider_len, &len2); + if (IS_ERR(len3, flags)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + counter += len2; + + if (len3 > 0) + { + p->tmp_ival = counter + len3; + move = DOWN; + } + else if (len3 == 0) + { + p2 = p->down; + while (p2) + { + if (type_field (p2->type) != ASN1_ETYPE_TAG) + { + p3 = p2->right; + asn1_delete_structure (&p2); + p2 = p3; + } + else + p2 = p2->right; + } + move = RIGHT; + } + else + { /* indefinite length method */ + p->tmp_ival = -1; + move = DOWN; + } + } + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (move == UP) + { + len2 = p->tmp_ival; + if (len2 == -1) + { /* indefinite length method */ + if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1])) + { + result = _asn1_append_sequence_set (p, &tcache); + if (result != 0) + { + warn(); + goto cleanup; + } + p = tcache.tail; + move = RIGHT; + continue; + } + + p->tmp_ival = 0; + tcache.tail = NULL; /* finished decoding this structure */ + tcache.head = NULL; + DECR_LEN(ider_len, 2); + counter += 2; + } + else + { /* definite length method */ + if (len2 > counter) + { + result = _asn1_append_sequence_set (p, &tcache); + if (result != 0) + { + warn(); + goto cleanup; + } + p = tcache.tail; + move = RIGHT; + continue; + } + + p->tmp_ival = 0; + tcache.tail = NULL; /* finished decoding this structure */ + tcache.head = NULL; + + if (len2 != counter) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + } + else + { /* move==DOWN || move==RIGHT */ + len3 = + asn1_get_length_der (der + counter, ider_len, &len2); + if (IS_ERR(len3, flags)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + counter += len2; + if (len3) + { + if (len3 > 0) + { /* definite length method */ + p->tmp_ival = counter + len3; + } + else + { /* indefinite length method */ + p->tmp_ival = -1; + } + + p2 = p->down; + if (p2 == NULL) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + while ((type_field (p2->type) == ASN1_ETYPE_TAG) + || (type_field (p2->type) == ASN1_ETYPE_SIZE)) + p2 = p2->right; + if (p2->right == NULL) + { + result = _asn1_append_sequence_set (p, &tcache); + if (result != 0) + { + warn(); + goto cleanup; + } + } + p = p2; + } + } + move = RIGHT; + break; + case ASN1_ETYPE_ANY: + /* Check indefinite lenth method in an EXPLICIT TAG */ + + if (!(flags & ASN1_DECODE_FLAG_STRICT_DER) && (p->type & CONST_TAG) && + tag_len == 2 && (der[counter - 1] == 0x80)) + indefinite = 1; + else + indefinite = 0; + + if (asn1_get_tag_der + (der + counter, ider_len, &class, &len2, + &tag) != ASN1_SUCCESS) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + DECR_LEN(ider_len, len2); + + len4 = + asn1_get_length_der (der + counter + len2, + ider_len, &len3); + if (IS_ERR(len4, flags)) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + if (len4 != -1) /* definite */ + { + len2 += len4; + + DECR_LEN(ider_len, len4+len3); + _asn1_set_value_lv (p, der + counter, len2 + len3); + counter += len2 + len3; + } + else /* == -1 */ + { /* indefinite length */ + ider_len += len2; /* undo DECR_LEN */ + + if (counter == 0) + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + + result = + _asn1_get_indefinite_length_string (der + counter, ider_len, &len2); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + 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 + { + result = ASN1_DER_ERROR; + warn(); + goto cleanup; + } + } + + move = RIGHT; + break; + default: + move = (move == UP) ? RIGHT : DOWN; + break; + } + } + + if (p) + { + p->end = counter - 1; + } + + if (p == node && move != DOWN) + break; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + if ((move == RIGHT) && !(p->type & CONST_SET)) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + _asn1_delete_not_used (*element); + + if ((ider_len < 0) || + (!(flags & ASN1_DECODE_FLAG_ALLOW_PADDING) && (ider_len != 0))) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + *max_ider_len = total_len - ider_len; + + return ASN1_SUCCESS; + +cleanup: + asn1_delete_structure (element); + return result; +} + + +/** + * asn1_der_decoding: + * @element: pointer to an ASN1 structure. + * @ider: vector that contains the DER encoding. + * @ider_len: number of bytes of *@ider: @ider[0]..@ider[len-1]. + * @errorDescription: null-terminated string contains details when an + * error occurred. + * + * Fill the structure *@element with values of a DER encoding + * string. The structure must just be created with function + * asn1_create_element(). + * + * Note that the *@element variable is provided as a pointer for + * historical reasons. + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if @ELEMENT is %NULL, and %ASN1_TAG_ERROR or + * %ASN1_DER_ERROR if the der encoding doesn't match the structure + * name (*@ELEMENT deleted). + **/ +int +asn1_der_decoding (asn1_node * element, const void *ider, int ider_len, + char *errorDescription) +{ + return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription); +} + +/** + * asn1_der_decoding_element: + * @structure: pointer to an ASN1 structure + * @elementName: name of the element to fill + * @ider: vector that contains the DER encoding of the whole structure. + * @len: number of bytes of *der: der[0]..der[len-1] + * @errorDescription: null-terminated string contains details when an + * error occurred. + * + * Fill the element named @ELEMENTNAME with values of a DER encoding + * string. The structure must just be created with function + * 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 + * %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 %NULL or @elementName == NULL, and + * %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding doesn't + * match the structure @structure (*ELEMENT deleted). + **/ +int +asn1_der_decoding_element (asn1_node * structure, const char *elementName, + const void *ider, int len, char *errorDescription) +{ + return asn1_der_decoding(structure, ider, len, errorDescription); +} + +/** + * asn1_der_decoding_startEnd: + * @element: pointer to an ASN1 element + * @ider: vector that contains the DER encoding. + * @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]) + * @end: the position of the last byte of NAME_ELEMENT decoding + * (@ider[*end]) + * + * Find the start and end point of an element in a DER encoding + * string. I mean that if you have a der encoding and you have already + * used the function asn1_der_decoding() to fill a structure, it may + * happen that you want to find the piece of string concerning an + * element of the structure. + * + * One example is the sequence "tbsCertificate" inside an X509 + * certificate. + * + * Note that since libtasn1 3.7 the @ider and @ider_len parameters + * can be omitted, if the element is already decoded using asn1_der_decoding(). + * + * Returns: %ASN1_SUCCESS if DER encoding OK, %ASN1_ELEMENT_NOT_FOUND + * if ELEMENT is %asn1_node EMPTY or @name_element is not a valid + * element, %ASN1_TAG_ERROR or %ASN1_DER_ERROR if the der encoding + * doesn't match the structure ELEMENT. + **/ +int +asn1_der_decoding_startEnd (asn1_node element, const void *ider, int ider_len, + const char *name_element, int *start, int *end) +{ + asn1_node node, node_to_find; + int result = ASN1_DER_ERROR; + + node = element; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + node_to_find = asn1_find_node (node, name_element); + + if (node_to_find == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + *start = node_to_find->start; + *end = node_to_find->end; + + if (*start == 0 && *end == 0) + { + if (ider == NULL || ider_len == 0) + return ASN1_GENERIC_ERROR; + + /* it seems asn1_der_decoding() wasn't called before. Do it now */ + result = asn1_der_decoding (&node, ider, ider_len, NULL); + if (result != ASN1_SUCCESS) + { + warn(); + return result; + } + + node_to_find = asn1_find_node (node, name_element); + if (node_to_find == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + *start = node_to_find->start; + *end = node_to_find->end; + } + + if (*end < *start) + return ASN1_GENERIC_ERROR; + + return ASN1_SUCCESS; +} + +/** + * asn1_expand_any_defined_by: + * @definitions: ASN1 definitions + * @element: pointer to an ASN1 structure + * + * Expands every "ANY DEFINED BY" element of a structure created from + * a DER decoding process (asn1_der_decoding function). The element + * ANY must be defined by an OBJECT IDENTIFIER. The type used to + * expand the element ANY is the first one following the definition of + * the actual value of the OBJECT IDENTIFIER. + * + * Returns: %ASN1_SUCCESS if Substitution OK, %ASN1_ERROR_TYPE_ANY if + * some "ANY DEFINED BY" element couldn't be expanded due to a + * problem in OBJECT_ID -> TYPE association, or other error codes + * depending on DER decoding. + **/ +int +asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element) +{ + char name[2 * ASN1_MAX_NAME_SIZE + 2], + value[ASN1_MAX_NAME_SIZE]; + int retCode = ASN1_SUCCESS, result; + int len, len2, len3; + asn1_node_const p2; + asn1_node p, p3, aux = NULL; + char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + const char *definitionsName; + + if ((definitions == NULL) || (*element == NULL)) + return ASN1_ELEMENT_NOT_FOUND; + + definitionsName = definitions->name; + + p = *element; + while (p) + { + + switch (type_field (p->type)) + { + case ASN1_ETYPE_ANY: + if ((p->type & CONST_DEFINED_BY) && (p->value)) + { + /* search the "DEF_BY" element */ + p2 = p->down; + while ((p2) && (type_field (p2->type) != ASN1_ETYPE_CONSTANT)) + p2 = p2->right; + + if (!p2) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + p3 = _asn1_find_up (p); + + if (!p3) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + p3 = p3->down; + while (p3) + { + if (!(strcmp (p3->name, p2->name))) + break; + p3 = p3->right; + } + + if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || + (p3->value == NULL)) + { + + p3 = _asn1_find_up (p); + p3 = _asn1_find_up (p3); + + if (!p3) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + p3 = p3->down; + + while (p3) + { + if (!(strcmp (p3->name, p2->name))) + break; + p3 = p3->right; + } + + if ((!p3) || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || (p3->value == NULL)) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + } + + /* search the OBJECT_ID into definitions */ + p2 = definitions->down; + while (p2) + { + if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && + (p2->type & CONST_ASSIGN)) + { + 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) + && (!_asn1_strcmp (p3->value, value))) + { + p2 = p2->right; /* pointer to the structure to + use for expansion */ + while ((p2) && (p2->type & CONST_ASSIGN)) + p2 = p2->right; + + if (p2) + { + snprintf(name, sizeof(name), "%s.%s", definitionsName, p2->name); + + result = + asn1_create_element (definitions, name, &aux); + if (result == ASN1_SUCCESS) + { + _asn1_cpy_name (aux, p); + len2 = + asn1_get_length_der (p->value, + p->value_len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + + result = + asn1_der_decoding (&aux, p->value + len3, + len2, + errorDescription); + if (result == ASN1_SUCCESS) + { + + _asn1_set_right (aux, p->right); + _asn1_set_right (p, aux); + + result = asn1_delete_structure (&p); + if (result == ASN1_SUCCESS) + { + p = aux; + aux = NULL; + break; + } + else + { /* error with asn1_delete_structure */ + asn1_delete_structure (&aux); + retCode = result; + break; + } + } + else + { /* error with asn1_der_decoding */ + retCode = result; + break; + } + } + else + { /* error with asn1_create_element */ + retCode = result; + break; + } + } + else + { /* error with the pointer to the structure to exapand */ + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + } + } + p2 = p2->right; + } /* end while */ + + if (!p2) + { + retCode = ASN1_ERROR_TYPE_ANY; + break; + } + + } + break; + default: + break; + } + + + if (p->down) + { + p = p->down; + } + else if (p == *element) + { + p = NULL; + break; + } + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == *element) + { + p = NULL; + break; + } + if (p->right) + { + p = p->right; + break; + } + } + } + } + + return retCode; +} + +/** + * asn1_expand_octet_string: + * @definitions: ASN1 definitions + * @element: pointer to an ASN1 structure + * @octetName: name of the OCTECT STRING field to expand. + * @objectName: name of the OBJECT IDENTIFIER field to use to define + * the type for expansion. + * + * Expands an "OCTET STRING" element of a structure created from a DER + * decoding process (the asn1_der_decoding() function). The type used + * for expansion is the first one following the definition of the + * actual value of the OBJECT IDENTIFIER indicated by OBJECTNAME. + * + * Returns: %ASN1_SUCCESS if substitution OK, %ASN1_ELEMENT_NOT_FOUND + * if @objectName or @octetName are not correct, + * %ASN1_VALUE_NOT_VALID if it wasn't possible to find the type to + * use for expansion, or other errors depending on DER decoding. + **/ +int +asn1_expand_octet_string (asn1_node_const definitions, asn1_node * element, + const char *octetName, const char *objectName) +{ + char name[2 * ASN1_MAX_NAME_SIZE + 1], value[ASN1_MAX_NAME_SIZE]; + int retCode = ASN1_SUCCESS, result; + int len, len2, len3; + asn1_node_const p2; + asn1_node aux = NULL; + asn1_node octetNode = NULL, objectNode = NULL; + char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + if ((definitions == NULL) || (*element == NULL)) + return ASN1_ELEMENT_NOT_FOUND; + + octetNode = asn1_find_node (*element, octetName); + if (octetNode == NULL) + return ASN1_ELEMENT_NOT_FOUND; + if (type_field (octetNode->type) != ASN1_ETYPE_OCTET_STRING) + return ASN1_ELEMENT_NOT_FOUND; + if (octetNode->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + objectNode = asn1_find_node (*element, objectName); + if (objectNode == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + if (type_field (objectNode->type) != ASN1_ETYPE_OBJECT_ID) + return ASN1_ELEMENT_NOT_FOUND; + + if (objectNode->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + + /* search the OBJECT_ID into definitions */ + p2 = definitions->down; + while (p2) + { + if ((type_field (p2->type) == ASN1_ETYPE_OBJECT_ID) && + (p2->type & CONST_ASSIGN)) + { + strcpy (name, definitions->name); + strcat (name, "."); + strcat (name, p2->name); + + len = sizeof (value); + result = asn1_read_value (definitions, name, value, &len); + + if ((result == ASN1_SUCCESS) + && (!_asn1_strcmp (objectNode->value, value))) + { + + p2 = p2->right; /* pointer to the structure to + use for expansion */ + while ((p2) && (p2->type & CONST_ASSIGN)) + p2 = p2->right; + + if (p2) + { + strcpy (name, definitions->name); + strcat (name, "."); + strcat (name, p2->name); + + result = asn1_create_element (definitions, name, &aux); + if (result == ASN1_SUCCESS) + { + _asn1_cpy_name (aux, octetNode); + len2 = + asn1_get_length_der (octetNode->value, + octetNode->value_len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + + result = + asn1_der_decoding (&aux, octetNode->value + len3, + len2, errorDescription); + if (result == ASN1_SUCCESS) + { + + _asn1_set_right (aux, octetNode->right); + _asn1_set_right (octetNode, aux); + + result = asn1_delete_structure (&octetNode); + if (result == ASN1_SUCCESS) + { + aux = NULL; + break; + } + else + { /* error with asn1_delete_structure */ + asn1_delete_structure (&aux); + retCode = result; + break; + } + } + else + { /* error with asn1_der_decoding */ + retCode = result; + break; + } + } + else + { /* error with asn1_create_element */ + retCode = result; + break; + } + } + else + { /* error with the pointer to the structure to exapand */ + retCode = ASN1_VALUE_NOT_VALID; + break; + } + } + } + + p2 = p2->right; + + } + + if (!p2) + retCode = ASN1_VALUE_NOT_VALID; + + return retCode; +} + +/*- + * _asn1_decode_simple_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @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 + * @dflags: DECODE_FLAG_* + * + * 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. + -*/ +static int +_asn1_decode_simple_der (unsigned int etype, const unsigned char *der, + unsigned int _der_len, const unsigned char **str, + unsigned int *str_len, unsigned dflags) +{ + int tag_len, len_len; + const unsigned char *p; + int der_len = _der_len; + unsigned char class; + unsigned long tag; + long ret; + + if (der == NULL || der_len == 0) + return ASN1_VALUE_NOT_VALID; + + if (ETYPE_OK (etype) == 0 || ETYPE_IS_STRING(etype) == 0) + return ASN1_VALUE_NOT_VALID; + + /* doesn't handle constructed classes */ + class = ETYPE_CLASS(etype); + if (class != ASN1_CLASS_UNIVERSAL) + return ASN1_VALUE_NOT_VALID; + + p = der; + + if (dflags & DECODE_FLAG_HAVE_TAG) + { + 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)) + { + warn(); + return ASN1_DER_ERROR; + } + + p += tag_len; + der_len -= tag_len; + if (der_len <= 0) + return ASN1_DER_ERROR; + } + + ret = asn1_get_length_der (p, der_len, &len_len); + if (ret < 0) + return ASN1_DER_ERROR; + + p += len_len; + der_len -= len_len; + if (der_len <= 0) + return ASN1_DER_ERROR; + + *str_len = ret; + *str = p; + + return ASN1_SUCCESS; +} + +/** + * asn1_decode_simple_der: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @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) +{ + return _asn1_decode_simple_der(etype, der, _der_len, str, str_len, DECODE_FLAG_HAVE_TAG); +} + +static int append(uint8_t **dst, unsigned *dst_size, const unsigned char *src, unsigned src_size) +{ + if (src_size == 0) + return ASN1_SUCCESS; + + *dst = _asn1_realloc(*dst, *dst_size+src_size); + if (*dst == NULL) + return ASN1_MEM_ALLOC_ERROR; + memcpy(*dst + *dst_size, src, src_size); + *dst_size += src_size; + return ASN1_SUCCESS; +} + +/*- + * _asn1_decode_simple_ber: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @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 + * @ber_len: the total length occupied by BER (may be %NULL) + * @have_tag: whether a DER tag is included + * + * Decodes a BER encoded type. The output is an allocated value + * of the data. This decodes BER STRINGS only. Other types are + * decoded as DER. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + -*/ +static int +_asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len, + unsigned dflags) +{ + int tag_len, len_len; + const unsigned char *p; + int der_len = _der_len; + uint8_t *total = NULL; + unsigned total_size = 0; + unsigned char class; + unsigned long tag; + unsigned char *out = NULL; + const unsigned char *cout = NULL; + unsigned out_len; + long result; + + if (ber_len) *ber_len = 0; + + if (der == NULL || der_len == 0) + { + warn(); + return ASN1_VALUE_NOT_VALID; + } + + if (ETYPE_OK (etype) == 0) + { + warn(); + return ASN1_VALUE_NOT_VALID; + } + + /* doesn't handle constructed + definite classes */ + class = ETYPE_CLASS (etype); + if (class != ASN1_CLASS_UNIVERSAL) + { + warn(); + return ASN1_VALUE_NOT_VALID; + } + + p = der; + + if (dflags & DECODE_FLAG_HAVE_TAG) + { + result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag); + if (result != ASN1_SUCCESS) + { + warn(); + return result; + } + + if (tag != ETYPE_TAG (etype)) + { + warn(); + return ASN1_DER_ERROR; + } + + p += tag_len; + + DECR_LEN(der_len, tag_len); + + if (ber_len) *ber_len += tag_len; + } + + /* indefinite constructed */ + if ((((dflags & DECODE_FLAG_CONSTRUCTED) || class == ASN1_CLASS_STRUCTURED) && ETYPE_IS_STRING(etype)) && + !(dflags & DECODE_FLAG_LEVEL3)) + { + if (der_len == 0) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + if (der_len > 0 && p[0] == 0x80) /* indefinite */ + { + len_len = 1; + DECR_LEN(der_len, len_len); + p += len_len; + + if (ber_len) *ber_len += len_len; + + /* decode the available octet strings */ + do + { + unsigned tmp_len; + unsigned flags = DECODE_FLAG_HAVE_TAG; + + if (dflags & DECODE_FLAG_LEVEL1) + flags |= DECODE_FLAG_LEVEL2; + else if (dflags & DECODE_FLAG_LEVEL2) + flags |= DECODE_FLAG_LEVEL3; + else + flags |= DECODE_FLAG_LEVEL1; + + result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, + flags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + p += tmp_len; + DECR_LEN(der_len, tmp_len); + + if (ber_len) *ber_len += tmp_len; + + DECR_LEN(der_len, 2); /* we need the EOC */ + + result = append(&total, &total_size, out, out_len); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + free(out); + out = NULL; + + if (p[0] == 0 && p[1] == 0) /* EOC */ + { + if (ber_len) *ber_len += 2; + break; + } + + /* no EOC */ + der_len += 2; + + if (der_len == 2) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + } + while(1); + } + else /* constructed */ + { + long const_len; + + result = asn1_get_length_ber(p, der_len, &len_len); + if (result < 0) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + DECR_LEN(der_len, len_len); + p += len_len; + + const_len = result; + + if (ber_len) *ber_len += len_len; + + /* decode the available octet strings */ + while(const_len > 0) + { + unsigned tmp_len; + unsigned flags = DECODE_FLAG_HAVE_TAG; + + if (dflags & DECODE_FLAG_LEVEL1) + flags |= DECODE_FLAG_LEVEL2; + else if (dflags & DECODE_FLAG_LEVEL2) + flags |= DECODE_FLAG_LEVEL3; + else + flags |= DECODE_FLAG_LEVEL1; + + result = _asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len, + flags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + p += tmp_len; + DECR_LEN(der_len, tmp_len); + DECR_LEN(const_len, tmp_len); + + if (ber_len) *ber_len += tmp_len; + + result = append(&total, &total_size, out, out_len); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + free(out); + out = NULL; + } + } + } + else if (class == ETYPE_CLASS(etype)) + { + if (ber_len) + { + result = asn1_get_length_der (p, der_len, &len_len); + if (result < 0) + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + *ber_len += result + len_len; + } + + /* non-string values are decoded as DER */ + result = _asn1_decode_simple_der(etype, der, _der_len, &cout, &out_len, dflags); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + + result = append(&total, &total_size, cout, out_len); + if (result != ASN1_SUCCESS) + { + warn(); + goto cleanup; + } + } + else + { + warn(); + result = ASN1_DER_ERROR; + goto cleanup; + } + + *str = total; + *str_len = total_size; + + return ASN1_SUCCESS; +cleanup: + free(out); + free(total); + return result; +} + +/** + * asn1_decode_simple_ber: + * @etype: The type of the string to be encoded (ASN1_ETYPE_) + * @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 + * @ber_len: the total length occupied by BER (may be %NULL) + * + * Decodes a BER encoded type. The output is an allocated value + * of the data. This decodes BER STRINGS only. Other types are + * decoded as DER. + * + * Returns: %ASN1_SUCCESS if successful or an error value. + **/ +int +asn1_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, unsigned char **str, + unsigned int *str_len, unsigned int *ber_len) +{ + return _asn1_decode_simple_ber(etype, der, _der_len, str, str_len, ber_len, DECODE_FLAG_HAVE_TAG); +} diff --git a/lib/minitasn1/element.c b/lib/minitasn1/element.c new file mode 100644 index 0000000..550fdb2 --- /dev/null +++ b/lib/minitasn1/element.c @@ -0,0 +1,1111 @@ +/* + * Copyright (C) 2000-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +/*****************************************************/ +/* File: element.c */ +/* Description: Functions with the read and write */ +/* functions. */ +/*****************************************************/ + + +#include <int.h> +#include "parser_aux.h" +#include <gstr.h> +#include "structure.h" +#include "c-ctype.h" +#include "element.h" + +void +_asn1_hierarchical_name (asn1_node_const node, char *name, int name_size) +{ + asn1_node_const p; + char tmp_name[64]; + + p = node; + + name[0] = 0; + + while (p != NULL) + { + if (p->name[0] != 0) + { + _asn1_str_cpy (tmp_name, sizeof (tmp_name), name), + _asn1_str_cpy (name, name_size, p->name); + _asn1_str_cat (name, name_size, "."); + _asn1_str_cat (name, name_size, tmp_name); + } + p = _asn1_find_up (p); + } + + if (name[0] == 0) + _asn1_str_cpy (name, name_size, "ROOT"); +} + + +/******************************************************************/ +/* Function : _asn1_convert_integer */ +/* Description: converts an integer from a null terminated string */ +/* to der decoding. The convertion from a null */ +/* terminated string to an integer is made with */ +/* the 'strtol' function. */ +/* Parameters: */ +/* value: null terminated string to convert. */ +/* value_out: convertion result (memory must be already */ +/* allocated). */ +/* value_out_size: number of bytes of value_out. */ +/* len: number of significant byte of value_out. */ +/* Return: ASN1_MEM_ERROR or ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_convert_integer (const unsigned char *value, unsigned char *value_out, + int value_out_size, int *len) +{ + char negative; + unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; + long valtmp; + int k, k2; + + valtmp = _asn1_strtol (value, NULL, 10); + + for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) + { + val[SIZEOF_UNSIGNED_LONG_INT - k - 1] = (valtmp >> (8 * k)) & 0xFF; + } + + if (val[0] & 0x80) + negative = 1; + else + negative = 0; + + for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT - 1; k++) + { + if (negative && (val[k] != 0xFF)) + break; + else if (!negative && val[k]) + break; + } + + if ((negative && !(val[k] & 0x80)) || (!negative && (val[k] & 0x80))) + k--; + + *len = SIZEOF_UNSIGNED_LONG_INT - k; + + if (SIZEOF_UNSIGNED_LONG_INT - k > value_out_size) + /* VALUE_OUT is too short to contain the value conversion */ + return ASN1_MEM_ERROR; + + 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); + for (k = 0; k < SIZEOF_UNSIGNED_LONG_INT; k++) + printf (", vOut[%d]=%d", k, value_out[k]); + printf ("\n"); +#endif + + return ASN1_SUCCESS; +} + +/* Appends a new element into the sequence (or set) defined by this + * node. The new element will have a name of '?number', where number + * is a monotonically increased serial number. + * + * The last element in the list may be provided in @pcache, to avoid + * traversing the list, an expensive operation in long lists. + * + * On success it returns in @pcache the added element (which is the + * tail in the list of added elements). + */ +int +_asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcache) +{ + asn1_node p, p2; + char temp[LTOSTR_MAX_SIZE+1]; + long n; + + if (!node || !(node->down)) + return ASN1_GENERIC_ERROR; + + p = node->down; + while ((type_field (p->type) == ASN1_ETYPE_TAG) + || (type_field (p->type) == ASN1_ETYPE_SIZE)) + p = p->right; + + p2 = _asn1_copy_structure3 (p); + if (p2 == NULL) + return ASN1_GENERIC_ERROR; + + if (pcache == NULL || pcache->tail == NULL || pcache->head != node) + { + while (p->right) + { + p = p->right; + } + } + else + { + p = pcache->tail; + } + + _asn1_set_right (p, p2); + if (pcache) + { + pcache->head = node; + pcache->tail = p2; + } + + if (p->name[0] == 0) + _asn1_str_cpy (temp, sizeof (temp), "?1"); + else + { + n = strtol (p->name + 1, NULL, 0); + n++; + temp[0] = '?'; + _asn1_ltostr (n, temp + 1); + } + _asn1_set_name (p2, temp); + /* p2->type |= CONST_OPTION; */ + + return ASN1_SUCCESS; +} + + +/** + * asn1_write_value: + * @node_root: pointer to a structure + * @name: the name of the element inside the structure that you want to set. + * @ivalue: vector used to specify the value to set. If len is >0, + * VALUE must be a two's complement form integer. if len=0 *VALUE + * must be a null terminated string with an integer value. + * @len: number of bytes of *value to use to set the value: + * value[0]..value[len-1] or 0 if value is a null terminated string + * + * Set the value of one element inside a structure. + * + * If an element is OPTIONAL and you want to delete it, you must use + * the value=NULL and len=0. Using "pkix.asn": + * + * result=asn1_write_value(cert, "tbsCertificate.issuerUniqueID", + * NULL, 0); + * + * Description for each type: + * + * INTEGER: VALUE must contain a two's complement form integer. + * + * value[0]=0xFF , len=1 -> integer=-1. + * value[0]=0xFF value[1]=0xFF , len=2 -> integer=-1. + * value[0]=0x01 , len=1 -> integer= 1. + * value[0]=0x00 value[1]=0x01 , len=2 -> integer= 1. + * value="123" , len=0 -> integer= 123. + * + * ENUMERATED: As INTEGER (but only with not negative numbers). + * + * BOOLEAN: VALUE must be the null terminated string "TRUE" or + * "FALSE" and LEN != 0. + * + * value="TRUE" , len=1 -> boolean=TRUE. + * value="FALSE" , len=1 -> boolean=FALSE. + * + * OBJECT IDENTIFIER: VALUE must be a null terminated string with + * each number separated by a dot (e.g. "1.2.3.543.1"). LEN != 0. + * + * value="1 2 840 10040 4 3" , len=1 -> OID=dsa-with-sha. + * + * UTCTime: VALUE must be a null terminated string in one of these + * formats: "YYMMDDhhmmssZ", "YYMMDDhhmmssZ", + * "YYMMDDhhmmss+hh'mm'", "YYMMDDhhmmss-hh'mm'", + * "YYMMDDhhmm+hh'mm'", or "YYMMDDhhmm-hh'mm'". LEN != 0. + * + * value="9801011200Z" , len=1 -> time=Jannuary 1st, 1998 + * at 12h 00m Greenwich Mean Time + * + * GeneralizedTime: VALUE must be in one of this format: + * "YYYYMMDDhhmmss.sZ", "YYYYMMDDhhmmss.sZ", + * "YYYYMMDDhhmmss.s+hh'mm'", "YYYYMMDDhhmmss.s-hh'mm'", + * "YYYYMMDDhhmm+hh'mm'", or "YYYYMMDDhhmm-hh'mm'" where ss.s + * indicates the seconds with any precision like "10.1" or "01.02". + * LEN != 0 + * + * value="2001010112001.12-0700" , len=1 -> time=Jannuary + * 1st, 2001 at 12h 00m 01.12s Pacific Daylight Time + * + * OCTET STRING: VALUE contains the octet string and LEN is the + * number of octets. + * + * value="$\backslash$x01$\backslash$x02$\backslash$x03" , + * len=3 -> three bytes octet string + * + * GeneralString: VALUE contains the generalstring and LEN is the + * number of octets. + * + * value="$\backslash$x01$\backslash$x02$\backslash$x03" , + * len=3 -> three bytes generalstring + * + * BIT STRING: VALUE contains the bit string organized by bytes and + * LEN is the number of bits. + * + * value="$\backslash$xCF" , len=6 -> bit string="110011" (six + * bits) + * + * CHOICE: if NAME indicates a choice type, VALUE must specify one of + * the alternatives with a null terminated string. LEN != 0. Using + * "pkix.asn"\: + * + * result=asn1_write_value(cert, + * "certificate1.tbsCertificate.subject", "rdnSequence", + * 1); + * + * ANY: VALUE indicates the der encoding of a structure. LEN != 0. + * + * SEQUENCE OF: VALUE must be the null terminated string "NEW" and + * LEN != 0. With this instruction another element is appended in + * the sequence. The name of this element will be "?1" if it's the + * first one, "?2" for the second and so on. + * + * Using "pkix.asn"\: + * + * result=asn1_write_value(cert, + * "certificate1.tbsCertificate.subject.rdnSequence", "NEW", 1); + * + * SET OF: the same as SEQUENCE OF. Using "pkix.asn": + * + * result=asn1_write_value(cert, + * "tbsCertificate.subject.rdnSequence.?LAST", "NEW", 1); + * + * 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. + **/ +int +asn1_write_value (asn1_node node_root, const char *name, + const void *ivalue, int len) +{ + asn1_node node, p, p2; + unsigned char *temp, *value_temp = NULL, *default_temp = NULL; + 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) + return ASN1_ELEMENT_NOT_FOUND; + + if ((node->type & CONST_OPTION) && (value == NULL) && (len == 0)) + { + asn1_delete_structure (&node); + return ASN1_SUCCESS; + } + + type = type_field (node->type); + + if ((type == ASN1_ETYPE_SEQUENCE_OF || type == ASN1_ETYPE_SET_OF) && (value == NULL) && (len == 0)) + { + p = node->down; + while ((type_field (p->type) == ASN1_ETYPE_TAG) + || (type_field (p->type) == ASN1_ETYPE_SIZE)) + p = p->right; + + while (p->right) + asn1_delete_structure (&p->right); + + return ASN1_SUCCESS; + } + + /* Don't allow element deletion for other types */ + if (value == NULL) + { + return ASN1_VALUE_NOT_VALID; + } + + switch (type) + { + case ASN1_ETYPE_BOOLEAN: + if (!_asn1_strcmp (value, "TRUE")) + { + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (p->type & CONST_TRUE) + _asn1_set_value (node, NULL, 0); + else + _asn1_set_value (node, "T", 1); + } + else + _asn1_set_value (node, "T", 1); + } + else if (!_asn1_strcmp (value, "FALSE")) + { + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (p->type & CONST_FALSE) + _asn1_set_value (node, NULL, 0); + else + _asn1_set_value (node, "F", 1); + } + else + _asn1_set_value (node, "F", 1); + } + else + return ASN1_VALUE_NOT_VALID; + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + if (len == 0) + { + if ((c_isdigit (value[0])) || (value[0] == '-')) + { + value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (value_temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + _asn1_convert_integer (value, value_temp, + SIZEOF_UNSIGNED_LONG_INT, &len); + } + else + { /* is an identifier like v1 */ + if (!(node->type & CONST_LIST)) + return ASN1_VALUE_NOT_VALID; + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_CONSTANT) + { + if (!_asn1_strcmp (p->name, value)) + { + value_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (value_temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + _asn1_convert_integer (p->value, + value_temp, + SIZEOF_UNSIGNED_LONG_INT, + &len); + break; + } + } + p = p->right; + } + if (p == NULL) + return ASN1_VALUE_NOT_VALID; + } + } + else + { /* len != 0 */ + 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 + negative = 0; + + if (negative && (type_field (node->type) == ASN1_ETYPE_ENUMERATED)) + { + free (value_temp); + return ASN1_VALUE_NOT_VALID; + } + + for (k = 0; k < len - 1; k++) + if (negative && (value_temp[k] != 0xFF)) + break; + else if (!negative && value_temp[k]) + break; + + if ((negative && !(value_temp[k] & 0x80)) || + (!negative && (value_temp[k] & 0x80))) + k--; + + _asn1_set_value_lv (node, value_temp + k, len - k); + + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if ((c_isdigit (p->value[0])) || (p->value[0] == '-')) + { + default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (default_temp == NULL) + { + free (value_temp); + return ASN1_MEM_ALLOC_ERROR; + } + + _asn1_convert_integer (p->value, default_temp, + SIZEOF_UNSIGNED_LONG_INT, &len2); + } + else + { /* is an identifier like v1 */ + if (!(node->type & CONST_LIST)) + { + free (value_temp); + return ASN1_VALUE_NOT_VALID; + } + p2 = node->down; + while (p2) + { + if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) + { + if (!_asn1_strcmp (p2->name, p->value)) + { + default_temp = malloc (SIZEOF_UNSIGNED_LONG_INT); + if (default_temp == NULL) + { + free (value_temp); + return ASN1_MEM_ALLOC_ERROR; + } + + _asn1_convert_integer (p2->value, + default_temp, + SIZEOF_UNSIGNED_LONG_INT, + &len2); + break; + } + } + p2 = p2->right; + } + if (p2 == NULL) + { + free (value_temp); + return ASN1_VALUE_NOT_VALID; + } + } + + + if ((len - k) == len2) + { + for (k2 = 0; k2 < len2; k2++) + if (value_temp[k + k2] != default_temp[k2]) + { + break; + } + if (k2 == len2) + _asn1_set_value (node, NULL, 0); + } + free (default_temp); + } + free (value_temp); + break; + case ASN1_ETYPE_OBJECT_ID: + for (i = 0; i < _asn1_strlen (value); i++) + if ((!c_isdigit (value[i])) && (value[i] != '.') && (value[i] != '+')) + return ASN1_VALUE_NOT_VALID; + if (node->type & CONST_DEFAULT) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (!_asn1_strcmp (value, p->value)) + { + _asn1_set_value (node, NULL, 0); + break; + } + } + _asn1_set_value (node, value, _asn1_strlen (value) + 1); + break; + case ASN1_ETYPE_UTC_TIME: + { + len = _asn1_strlen (value); + if (len < 11) + return ASN1_VALUE_NOT_VALID; + for (k = 0; k < 10; k++) + if (!c_isdigit (value[k])) + return ASN1_VALUE_NOT_VALID; + switch (len) + { + case 11: + if (value[10] != 'Z') + return ASN1_VALUE_NOT_VALID; + break; + case 13: + if ((!c_isdigit (value[10])) || (!c_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 (!c_isdigit (value[k])) + return ASN1_VALUE_NOT_VALID; + break; + case 17: + if ((!c_isdigit (value[10])) || (!c_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 (!c_isdigit (value[k])) + return ASN1_VALUE_NOT_VALID; + break; + default: + return ASN1_VALUE_NOT_FOUND; + } + _asn1_set_value (node, value, len); + } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + len = _asn1_strlen (value); + _asn1_set_value (node, value, len); + break; + case ASN1_ETYPE_OCTET_STRING: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + if (len == 0) + len = _asn1_strlen (value); + _asn1_set_value_lv (node, value, len); + break; + case ASN1_ETYPE_BIT_STRING: + if (len == 0) + len = _asn1_strlen (value); + asn1_length_der ((len >> 3) + 2, NULL, &len2); + temp = malloc ((len >> 3) + 2 + len2); + if (temp == NULL) + return ASN1_MEM_ALLOC_ERROR; + + asn1_bit_der (value, len, temp, &len2); + _asn1_set_value_m (node, temp, len2); + temp = NULL; + break; + case ASN1_ETYPE_CHOICE: + p = node->down; + while (p) + { + if (!_asn1_strcmp (p->name, value)) + { + p2 = node->down; + while (p2) + { + if (p2 != p) + { + asn1_delete_structure (&p2); + p2 = node->down; + } + else + p2 = p2->right; + } + break; + } + p = p->right; + } + if (!p) + return ASN1_ELEMENT_NOT_FOUND; + break; + case ASN1_ETYPE_ANY: + _asn1_set_value_lv (node, value, len); + break; + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SET_OF: + if (_asn1_strcmp (value, "NEW")) + return ASN1_VALUE_NOT_VALID; + _asn1_append_sequence_set (node, NULL); + break; + default: + return ASN1_ELEMENT_NOT_FOUND; + break; + } + + return ASN1_SUCCESS; +} + + +#define PUT_VALUE( ptr, ptr_size, data, data_size) \ + *len = data_size; \ + if (ptr_size < data_size) { \ + return ASN1_MEM_ERROR; \ + } else { \ + if (ptr && data_size > 0) \ + memcpy (ptr, data, data_size); \ + } + +#define PUT_STR_VALUE( ptr, ptr_size, data) \ + *len = _asn1_strlen (data) + 1; \ + if (ptr_size < *len) { \ + return ASN1_MEM_ERROR; \ + } else { \ + /* this strcpy is checked */ \ + if (ptr) { \ + _asn1_strcpy (ptr, data); \ + } \ + } + +#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 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. + * @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. + * + * 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. If the @root provided is a node to specific sequence element, + * then the keyword "?CURRENT" is also acceptable and indicates the + * current sequence element of this node. + * + * 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. + * + * 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. + * + * 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. On the occasion that the stored data are of zero-length + * this function may return %ASN1_SUCCESS even if the provided @len is zero. + **/ +int +asn1_read_value (asn1_node_const 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 (ASN1_ETYPE) + * + * Returns the type and 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. If the @root provided is a node to specific sequence element, + * then the keyword "?CURRENT" is also acceptable and indicates the + * current sequence element of this node. + * + * 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. + * + * 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. + * + * 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. On the occasion that the stored data are of zero-length + * this function may return %ASN1_SUCCESS even if the provided @len is zero. + **/ +int +asn1_read_value_type (asn1_node_const root, const char *name, void *ivalue, + int *len, unsigned int *etype) +{ + asn1_node_const node, p, p2; + 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; + + type = type_field (node->type); + + if ((type != ASN1_ETYPE_NULL) && + (type != ASN1_ETYPE_CHOICE) && + !(node->type & CONST_DEFAULT) && !(node->type & CONST_ASSIGN) && + (node->value == NULL)) + return ASN1_VALUE_NOT_FOUND; + + if (etype) + *etype = type; + switch (type) + { + case ASN1_ETYPE_NULL: + PUT_STR_VALUE (value, value_size, "NULL"); + break; + case ASN1_ETYPE_BOOLEAN: + if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if (p->type & CONST_TRUE) + { + PUT_STR_VALUE (value, value_size, "TRUE"); + } + else + { + PUT_STR_VALUE (value, value_size, "FALSE"); + } + } + else if (node->value[0] == 'T') + { + PUT_STR_VALUE (value, value_size, "TRUE"); + } + else + { + PUT_STR_VALUE (value, value_size, "FALSE"); + } + break; + case ASN1_ETYPE_INTEGER: + case ASN1_ETYPE_ENUMERATED: + if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + if ((c_isdigit (p->value[0])) || (p->value[0] == '-') + || (p->value[0] == '+')) + { + result = _asn1_convert_integer + (p->value, value, value_size, len); + if (result != ASN1_SUCCESS) + return result; + } + else + { /* is an identifier like v1 */ + p2 = node->down; + while (p2) + { + if (type_field (p2->type) == ASN1_ETYPE_CONSTANT) + { + if (!_asn1_strcmp (p2->name, p->value)) + { + result = _asn1_convert_integer + (p2->value, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + break; + } + } + p2 = p2->right; + } + } + } + else + { + len2 = -1; + result = asn1_get_octet_der + (node->value, node->value_len, &len2, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + } + break; + case ASN1_ETYPE_OBJECT_ID: + if (node->type & CONST_ASSIGN) + { + *len = 0; + if (value) + value[0] = 0; + p = node->down; + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_CONSTANT) + { + ADD_STR_VALUE (value, value_size, p->value); + if (p->right) + { + ADD_STR_VALUE (value, value_size, "."); + } + } + p = p->right; + } + (*len)++; + } + else if ((node->type & CONST_DEFAULT) && (node->value == NULL)) + { + p = node->down; + while (type_field (p->type) != ASN1_ETYPE_DEFAULT) + p = p->right; + PUT_STR_VALUE (value, value_size, p->value); + } + else + { + PUT_STR_VALUE (value, value_size, node->value); + } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + PUT_AS_STR_VALUE (value, value_size, node->value, node->value_len); + break; + case ASN1_ETYPE_OCTET_STRING: + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + len2 = -1; + result = asn1_get_octet_der + (node->value, node->value_len, &len2, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + break; + case ASN1_ETYPE_BIT_STRING: + len2 = -1; + result = asn1_get_bit_der + (node->value, node->value_len, &len2, value, value_size, + len); + if (result != ASN1_SUCCESS) + return result; + break; + case ASN1_ETYPE_CHOICE: + PUT_STR_VALUE (value, value_size, node->down->name); + break; + case ASN1_ETYPE_ANY: + len3 = -1; + len2 = asn1_get_length_der (node->value, node->value_len, &len3); + if (len2 < 0) + return ASN1_DER_ERROR; + PUT_VALUE (value, value_size, node->value + len3, len2); + break; + default: + return ASN1_ELEMENT_NOT_FOUND; + break; + } + return ASN1_SUCCESS; +} + + +/** + * asn1_read_tag: + * @root: pointer to a structure + * @name: the name of the element inside a structure. + * @tagValue: variable that will contain the TAG value. + * @classValue: variable that will specify the TAG type. + * + * Returns the TAG and the CLASS of one element inside a structure. + * CLASS can have one of these constants: %ASN1_CLASS_APPLICATION, + * %ASN1_CLASS_UNIVERSAL, %ASN1_CLASS_PRIVATE or + * %ASN1_CLASS_CONTEXT_SPECIFIC. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * @name is not a valid element. + **/ +int +asn1_read_tag (asn1_node_const root, const char *name, int *tagValue, + int *classValue) +{ + asn1_node node, p, pTag; + + node = asn1_find_node (root, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node->down; + + /* pTag will points to the IMPLICIT TAG */ + pTag = NULL; + if (node->type & CONST_TAG) + { + while (p) + { + if (type_field (p->type) == ASN1_ETYPE_TAG) + { + if ((p->type & CONST_IMPLICIT) && (pTag == NULL)) + pTag = p; + else if (p->type & CONST_EXPLICIT) + pTag = NULL; + } + p = p->right; + } + } + + if (pTag) + { + *tagValue = _asn1_strtoul (pTag->value, NULL, 10); + + if (pTag->type & CONST_APPLICATION) + *classValue = ASN1_CLASS_APPLICATION; + else if (pTag->type & CONST_UNIVERSAL) + *classValue = ASN1_CLASS_UNIVERSAL; + else if (pTag->type & CONST_PRIVATE) + *classValue = ASN1_CLASS_PRIVATE; + else + *classValue = ASN1_CLASS_CONTEXT_SPECIFIC; + } + else + { + unsigned type = type_field (node->type); + *classValue = ASN1_CLASS_UNIVERSAL; + + switch (type) + { + CASE_HANDLED_ETYPES: + *tagValue = _asn1_tags[type].tag; + break; + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_CHOICE: + case ASN1_ETYPE_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_node structure. + * The data returned should be handled as constant values. + * + * Returns: %ASN1_SUCCESS if the node exists. + **/ +int +asn1_read_node_value (asn1_node_const 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; +} diff --git a/lib/minitasn1/element.h b/lib/minitasn1/element.h new file mode 100644 index 0000000..717bfaf --- /dev/null +++ b/lib/minitasn1/element.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2000-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef _ELEMENT_H +#define _ELEMENT_H + + +struct node_tail_cache_st +{ + asn1_node head; /* the first element of the sequence */ + asn1_node tail; +}; + +int _asn1_append_sequence_set (asn1_node node, struct node_tail_cache_st *pcached); + +int _asn1_convert_integer (const unsigned char *value, + unsigned char *value_out, + int value_out_size, int *len); + +void _asn1_hierarchical_name (asn1_node_const node, char *name, int name_size); + +#endif diff --git a/lib/minitasn1/errors.c b/lib/minitasn1/errors.c new file mode 100644 index 0000000..a3daad4 --- /dev/null +++ b/lib/minitasn1/errors.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include <int.h> +#ifdef STDC_HEADERS +#include <stdarg.h> +#endif + +#define LIBTASN1_ERROR_ENTRY(name) { #name, name } + +struct libtasn1_error_entry +{ + const char *name; + int number; +}; +typedef struct libtasn1_error_entry libtasn1_error_entry; + +static const libtasn1_error_entry error_algorithms[] = { + LIBTASN1_ERROR_ENTRY (ASN1_SUCCESS), + LIBTASN1_ERROR_ENTRY (ASN1_FILE_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_IDENTIFIER_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_DER_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_FOUND), + LIBTASN1_ERROR_ENTRY (ASN1_GENERIC_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_VALUE_NOT_VALID), + LIBTASN1_ERROR_ENTRY (ASN1_TAG_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_TAG_IMPLICIT), + LIBTASN1_ERROR_ENTRY (ASN1_ERROR_TYPE_ANY), + LIBTASN1_ERROR_ENTRY (ASN1_SYNTAX_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_MEM_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_MEM_ALLOC_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_DER_OVERFLOW), + LIBTASN1_ERROR_ENTRY (ASN1_NAME_TOO_LONG), + LIBTASN1_ERROR_ENTRY (ASN1_ARRAY_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_ELEMENT_NOT_EMPTY), + LIBTASN1_ERROR_ENTRY (ASN1_TIME_ENCODING_ERROR), + LIBTASN1_ERROR_ENTRY (ASN1_RECURSION), + {0, 0} +}; + +/** + * asn1_perror: + * @error: is an error returned by a libtasn1 function. + * + * Prints a string to stderr with a description of an error. This + * function is like perror(). The only difference is that it accepts + * an error returned by a libtasn1 function. + * + * Since: 1.6 + **/ +void +asn1_perror (int error) +{ + const char *str = asn1_strerror (error); + fprintf (stderr, "LIBTASN1 ERROR: %s\n", str ? str : "(null)"); +} + +/** + * asn1_strerror: + * @error: is an error returned by a libtasn1 function. + * + * Returns a string with a description of an error. This function is + * similar to strerror. The only difference is that it accepts an + * error (number) returned by a libtasn1 function. + * + * Returns: Pointer to static zero-terminated string describing error + * code. + * + * Since: 1.6 + **/ +const char * +asn1_strerror (int error) +{ + const libtasn1_error_entry *p; + + for (p = error_algorithms; p->name != NULL; p++) + if (p->number == error) + return p->name + sizeof ("ASN1_") - 1; + + return NULL; +} diff --git a/lib/minitasn1/gstr.c b/lib/minitasn1/gstr.c new file mode 100644 index 0000000..1475ed5 --- /dev/null +++ b/lib/minitasn1/gstr.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include <int.h> +#include "gstr.h" + +/* These function are like strcat, strcpy. They only + * do bounds checking (they shouldn't cause buffer overruns), + * and they always produce null terminated strings. + * + * They should be used only with null terminated strings. + */ +void +_asn1_str_cat (char *dest, size_t dest_tot_size, const char *src) +{ + size_t str_size = strlen (src); + size_t dest_size = strlen (dest); + + if (dest_tot_size - dest_size > str_size) + { + strcat (dest, src); + } + else + { + if (dest_tot_size > dest_size) + { + strncat (dest, src, (dest_tot_size - dest_size) - 1); + dest[dest_tot_size - 1] = 0; + } + } +} + +/* 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); + + if (dest_tot_size > str_size) + { + strcpy (dest, src); + return str_size; + } + else + { + if (dest_tot_size > 0) + { + str_size = dest_tot_size - 1; + memcpy (dest, src, str_size); + dest[str_size] = 0; + return str_size; + } + else + return 0; + } +} diff --git a/lib/minitasn1/gstr.h b/lib/minitasn1/gstr.h new file mode 100644 index 0000000..e549c77 --- /dev/null +++ b/lib/minitasn1/gstr.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef GSTR_H +# define GSTR_H + +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. + */ + + if (size > 0) do { + memset(data, c, size); + } while(vdata[volatile_zero] != c); +} + +#endif /* GSTR_H */ diff --git a/lib/minitasn1/int.h b/lib/minitasn1/int.h new file mode 100644 index 0000000..57f1efd --- /dev/null +++ b/lib/minitasn1/int.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef INT_H +#define INT_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdint.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#include <libtasn1.h> + +#define ASN1_SMALL_VALUE_SIZE 16 + +/* This structure is also in libtasn1.h, but then contains less + fields. You cannot make any modifications to these first fields + without breaking ABI. */ +struct asn1_node_st +{ + /* public fields: */ + 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; + asn1_node down; /* Pointer to the son node */ + asn1_node right; /* Pointer to the brother node */ + asn1_node left; /* Pointer to the next list element */ + /* private fields: */ + unsigned char small_value[ASN1_SMALL_VALUE_SIZE]; /* For small values */ + + /* values used during decoding/coding */ + int tmp_ival; + unsigned start; /* the start of the DER sequence - if decoded */ + unsigned end; /* the end of the DER sequence - if decoded */ +}; + +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 ASN1_ETYPE_NULL: \ + case ASN1_ETYPE_BOOLEAN: \ + case ASN1_ETYPE_INTEGER: \ + case ASN1_ETYPE_ENUMERATED: \ + case ASN1_ETYPE_OBJECT_ID: \ + case ASN1_ETYPE_OCTET_STRING: \ + case ASN1_ETYPE_GENERALSTRING: \ + case ASN1_ETYPE_NUMERIC_STRING: \ + case ASN1_ETYPE_IA5_STRING: \ + case ASN1_ETYPE_TELETEX_STRING: \ + case ASN1_ETYPE_PRINTABLE_STRING: \ + case ASN1_ETYPE_UNIVERSAL_STRING: \ + case ASN1_ETYPE_BMP_STRING: \ + case ASN1_ETYPE_UTF8_STRING: \ + case ASN1_ETYPE_VISIBLE_STRING: \ + case ASN1_ETYPE_BIT_STRING: \ + case ASN1_ETYPE_SEQUENCE: \ + case ASN1_ETYPE_SEQUENCE_OF: \ + case ASN1_ETYPE_SET: \ + case ASN1_ETYPE_UTC_TIME: \ + case ASN1_ETYPE_GENERALIZED_TIME: \ + case ASN1_ETYPE_SET_OF + +#define ETYPE_TAG(etype) (_asn1_tags[etype].tag) +#define ETYPE_CLASS(etype) (_asn1_tags[etype].class) +#define ETYPE_OK(etype) (((etype) != ASN1_ETYPE_INVALID && \ + (etype) <= _asn1_tags_size && \ + _asn1_tags[(etype)].desc != NULL)?1:0) + +#define ETYPE_IS_STRING(etype) ((etype == ASN1_ETYPE_GENERALSTRING || \ + etype == ASN1_ETYPE_NUMERIC_STRING || etype == ASN1_ETYPE_IA5_STRING || \ + etype == ASN1_ETYPE_TELETEX_STRING || etype == ASN1_ETYPE_PRINTABLE_STRING || \ + etype == ASN1_ETYPE_UNIVERSAL_STRING || etype == ASN1_ETYPE_BMP_STRING || \ + etype == ASN1_ETYPE_UTF8_STRING || etype == ASN1_ETYPE_VISIBLE_STRING || \ + etype == ASN1_ETYPE_OCTET_STRING)?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) + +#if SIZEOF_UNSIGNED_LONG_INT == 8 +# define _asn1_strtou64(n,e,b) strtoul((const char *) n, e, b) +#else +# define _asn1_strtou64(n,e,b) strtoull((const char *) n, e, b) +#endif + +#define MAX_LOG_SIZE 1024 /* maximum number of characters of a log message */ + +/* Define used for visiting trees. */ +#define UP 1 +#define RIGHT 2 +#define DOWN 3 + +/***********************************************************************/ +/* List of constants to better specify the type of typedef asn1_node_st. */ +/***********************************************************************/ +/* Used with TYPE_TAG */ +#define CONST_UNIVERSAL (1U<<8) +#define CONST_PRIVATE (1U<<9) +#define CONST_APPLICATION (1U<<10) +#define CONST_EXPLICIT (1U<<11) +#define CONST_IMPLICIT (1U<<12) + +#define CONST_TAG (1U<<13) /* Used in ASN.1 assignement */ +#define CONST_OPTION (1U<<14) +#define CONST_DEFAULT (1U<<15) +#define CONST_TRUE (1U<<16) +#define CONST_FALSE (1U<<17) + +#define CONST_LIST (1U<<18) /* Used with TYPE_INTEGER and TYPE_BIT_STRING */ +#define CONST_MIN_MAX (1U<<19) + +#define CONST_1_PARAM (1U<<20) + +#define CONST_SIZE (1U<<21) + +#define CONST_DEFINED_BY (1U<<22) + +/* Those two are deprecated and used for backwards compatibility */ +#define CONST_GENERALIZED (1U<<23) +#define CONST_UTC (1U<<24) + +/* #define CONST_IMPORTS (1U<<25) */ + +#define CONST_NOT_USED (1U<<26) +#define CONST_SET (1U<<27) +#define CONST_ASSIGN (1U<<28) + +#define CONST_DOWN (1U<<29) +#define CONST_RIGHT (1U<<30) + + +#define ASN1_ETYPE_TIME 17 +/****************************************/ +/* Returns the first 8 bits. */ +/* Used with the field type of asn1_node_st */ +/****************************************/ +inline static unsigned int +type_field (unsigned int ntype) +{ + return (ntype & 0xff); +} + +/* 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 == ASN1_ETYPE_TIME) + { + if (ntype & CONST_UTC) + type = ASN1_ETYPE_UTC_TIME; + else + type = ASN1_ETYPE_GENERALIZED_TIME; + + ntype &= ~(CONST_UTC | CONST_GENERALIZED); + ntype &= 0xffffff00; + ntype |= type; + + return ntype; + } + else + return ntype; +} + +static inline +void *_asn1_realloc(void *ptr, size_t size) +{ + void *ret; + + if (size == 0) + return ptr; + + ret = realloc(ptr, size); + if (ret == NULL) + { + free(ptr); + } + return ret; +} + +#endif /* INT_H */ diff --git a/lib/minitasn1/libtasn1.h b/lib/minitasn1/libtasn1.h new file mode 100644 index 0000000..c7c937f --- /dev/null +++ b/lib/minitasn1/libtasn1.h @@ -0,0 +1,637 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * LIBTASN1 is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * LIBTASN1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with LIBTASN1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + */ + +/** + * SECTION:libtasn1 + * @short_description: GNU ASN.1 library + * + * The Libtasn1 library provides Abstract Syntax Notation One (ASN.1, as + * specified by the X.680 ITU-T recommendation) parsing and structures + * management, and Distinguished Encoding Rules (DER, as per X.690) + * encoding and decoding functions. + */ + + +#ifndef LIBTASN1_H +#define LIBTASN1_H + +#ifndef ASN1_API +#if defined ASN1_BUILDING && defined HAVE_VISIBILITY && HAVE_VISIBILITY +#define ASN1_API __attribute__((__visibility__("default"))) +#elif defined ASN1_BUILDING && defined _MSC_VER && ! defined ASN1_STATIC +#define ASN1_API __declspec(dllexport) +#elif defined _MSC_VER && ! defined ASN1_STATIC +#define ASN1_API __declspec(dllimport) +#else +#define ASN1_API +#endif +#endif + +#ifdef __GNUC__ +# define __LIBTASN1_CONST__ __attribute__((const)) +# define __LIBTASN1_PURE__ __attribute__((pure)) +#else +# define __LIBTASN1_CONST__ +# define __LIBTASN1_PURE__ +#endif + +#include <sys/types.h> +#include <time.h> +#include <stdio.h> /* for FILE* */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * ASN1_VERSION: + * + * Version of the library as a string. + */ +#define ASN1_VERSION "4.17.0" + +/** + * ASN1_VERSION_MAJOR: + * + * Major version number of the library. + */ +#define ASN1_VERSION_MAJOR @MAJOR_VERSION@ + +/** + * ASN1_VERSION_MINOR: + * + * Minor version number of the library. + */ +#define ASN1_VERSION_MINOR @MINOR_VERSION@ + +/** + * ASN1_VERSION_PATCH: + * + * Patch version number of the library. + */ +#define ASN1_VERSION_PATCH @PATCH_VERSION@ + +/** + * ASN1_VERSION_NUMBER: + * + * Version number of the library as a number. + */ +#define ASN1_VERSION_NUMBER @NUMBER_VERSION@ + + +#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 + +/*****************************************/ +/* Errors returned by libtasn1 functions */ +/*****************************************/ +#define ASN1_SUCCESS 0 +#define ASN1_FILE_NOT_FOUND 1 +#define ASN1_ELEMENT_NOT_FOUND 2 +#define ASN1_IDENTIFIER_NOT_FOUND 3 +#define ASN1_DER_ERROR 4 +#define ASN1_VALUE_NOT_FOUND 5 +#define ASN1_GENERIC_ERROR 6 +#define ASN1_VALUE_NOT_VALID 7 +#define ASN1_TAG_ERROR 8 +#define ASN1_TAG_IMPLICIT 9 +#define ASN1_ERROR_TYPE_ANY 10 +#define ASN1_SYNTAX_ERROR 11 +#define ASN1_MEM_ERROR 12 +#define ASN1_MEM_ALLOC_ERROR 13 +#define ASN1_DER_OVERFLOW 14 +#define ASN1_NAME_TOO_LONG 15 +#define ASN1_ARRAY_ERROR 16 +#define ASN1_ELEMENT_NOT_EMPTY 17 +#define ASN1_TIME_ENCODING_ERROR 18 +#define ASN1_RECURSION 19 + +/*************************************/ +/* Constants used in asn1_visit_tree */ +/*************************************/ +#define ASN1_PRINT_NAME 1 +#define ASN1_PRINT_NAME_TYPE 2 +#define ASN1_PRINT_NAME_TYPE_VALUE 3 +#define ASN1_PRINT_ALL 4 + +/*****************************************/ +/* Constants returned by asn1_read_tag */ +/*****************************************/ +#define ASN1_CLASS_UNIVERSAL 0x00 /* old: 1 */ +#define ASN1_CLASS_APPLICATION 0x40 /* old: 2 */ +#define ASN1_CLASS_CONTEXT_SPECIFIC 0x80 /* old: 3 */ +#define ASN1_CLASS_PRIVATE 0xC0 /* old: 4 */ +#define ASN1_CLASS_STRUCTURED 0x20 + +/*****************************************/ +/* Constants returned by asn1_read_tag */ +/*****************************************/ +#define ASN1_TAG_BOOLEAN 0x01 +#define ASN1_TAG_INTEGER 0x02 +#define ASN1_TAG_SEQUENCE 0x10 +#define ASN1_TAG_SET 0x11 +#define ASN1_TAG_OCTET_STRING 0x04 +#define ASN1_TAG_BIT_STRING 0x03 +#define ASN1_TAG_UTCTime 0x17 +#define ASN1_TAG_GENERALIZEDTime 0x18 +#define ASN1_TAG_OBJECT_ID 0x06 +#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 + +/** + * asn1_node: + * + * Structure definition used for the node of the tree + * that represents an ASN.1 DEFINITION. + */ +typedef struct asn1_node_st asn1_node_st; + +typedef asn1_node_st *asn1_node; +typedef const asn1_node_st *asn1_node_const; + +/** + * ASN1_MAX_NAME_SIZE: + * + * Maximum number of characters of a name + * inside a file with ASN1 definitions. + */ +#define ASN1_MAX_NAME_SIZE 64 + + +/** + * asn1_static_node: + * @name: Node name + * @type: Node typ + * @value: Node value + * + * For the on-disk format of ASN.1 trees, created by asn1_parser2array(). + */ +typedef struct asn1_static_node_st +{ + const char *name; /* Node name */ + unsigned int type; /* Node type */ + const void *value; /* Node value */ +} asn1_static_node; + +/* List of constants for field type of asn1_static_node */ +#define ASN1_ETYPE_INVALID 0 +#define ASN1_ETYPE_CONSTANT 1 +#define ASN1_ETYPE_IDENTIFIER 2 +#define ASN1_ETYPE_INTEGER 3 +#define ASN1_ETYPE_BOOLEAN 4 +#define ASN1_ETYPE_SEQUENCE 5 +#define ASN1_ETYPE_BIT_STRING 6 +#define ASN1_ETYPE_OCTET_STRING 7 +#define ASN1_ETYPE_TAG 8 +#define ASN1_ETYPE_DEFAULT 9 +#define ASN1_ETYPE_SIZE 10 +#define ASN1_ETYPE_SEQUENCE_OF 11 +#define ASN1_ETYPE_OBJECT_ID 12 +#define ASN1_ETYPE_ANY 13 +#define ASN1_ETYPE_SET 14 +#define ASN1_ETYPE_SET_OF 15 +#define ASN1_ETYPE_DEFINITIONS 16 +#define ASN1_ETYPE_CHOICE 18 +#define ASN1_ETYPE_IMPORTS 19 +#define ASN1_ETYPE_NULL 20 +#define ASN1_ETYPE_ENUMERATED 21 +#define ASN1_ETYPE_GENERALSTRING 27 +#define ASN1_ETYPE_NUMERIC_STRING 28 +#define ASN1_ETYPE_IA5_STRING 29 +#define ASN1_ETYPE_TELETEX_STRING 30 +#define ASN1_ETYPE_PRINTABLE_STRING 31 +#define ASN1_ETYPE_UNIVERSAL_STRING 32 +#define ASN1_ETYPE_BMP_STRING 33 +#define ASN1_ETYPE_UTF8_STRING 34 +#define ASN1_ETYPE_VISIBLE_STRING 35 +#define ASN1_ETYPE_UTC_TIME 36 +#define ASN1_ETYPE_GENERALIZED_TIME 37 + +/** + * ASN1_DELETE_FLAG_ZEROIZE: + * + * Used by: asn1_delete_structure2() + * + * Zeroize values prior to deinitialization. + */ +#define ASN1_DELETE_FLAG_ZEROIZE 1 + +/** + * ASN1_DECODE_FLAG_ALLOW_PADDING: + * + * Used by: asn1_der_decoding2() + * + * This flag would allow arbitrary data past the DER data. + */ +#define ASN1_DECODE_FLAG_ALLOW_PADDING 1 +/** + * ASN1_DECODE_FLAG_STRICT_DER: + * + * Used by: asn1_der_decoding2() + * + * This flag would ensure that no BER decoding takes place. + */ +#define ASN1_DECODE_FLAG_STRICT_DER (1<<1) +/** + * ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME: + * + * Used by: asn1_der_decoding2() + * + * This flag will tolerate Time encoding errors when in strict DER. + */ +#define ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME (1<<2) + + +/** + * asn1_data_node_st: + * @name: Node name + * @value: Node value + * @value_len: Node value size + * @type: Node value type (ASN1_ETYPE_*) + * + * Data node inside a #asn1_node structure. + */ +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 (ASN1_ETYPE_*) */ +}; +typedef struct asn1_data_node_st asn1_data_node_st; + +/***********************************/ +/* Fixed constants */ +/***********************************/ + +/** + * ASN1_MAX_ERROR_DESCRIPTION_SIZE: + * + * Maximum number of characters + * of a description message + * (null character included). + */ +#define ASN1_MAX_ERROR_DESCRIPTION_SIZE 128 + +/***********************************/ +/* Functions definitions */ +/***********************************/ + +extern ASN1_API int + asn1_parser2tree (const char *file, + asn1_node * definitions, char *error_desc); + +extern ASN1_API int + asn1_parser2array (const char *inputFileName, + const char *outputFileName, + const char *vectorName, char *error_desc); + +extern ASN1_API int + asn1_array2tree (const asn1_static_node * array, + asn1_node * definitions, char *errorDescription); + +extern ASN1_API void + asn1_print_structure (FILE * out, asn1_node_const structure, + const char *name, int mode); + +extern ASN1_API int + asn1_create_element (asn1_node_const definitions, + const char *source_name, asn1_node * element); + +extern ASN1_API int asn1_delete_structure (asn1_node * structure); + +extern ASN1_API int asn1_delete_structure2 (asn1_node * structure, unsigned int flags); + +extern ASN1_API int + asn1_delete_element (asn1_node structure, const char *element_name); + +extern ASN1_API int + asn1_write_value (asn1_node node_root, const char *name, + const void *ivalue, int len); + +extern ASN1_API int + asn1_read_value (asn1_node_const root, const char *name, + void *ivalue, int *len); + +extern ASN1_API int + asn1_read_value_type (asn1_node_const root, const char *name, + void *ivalue, int *len, unsigned int *etype); + +extern ASN1_API int + asn1_read_node_value (asn1_node_const node, asn1_data_node_st * data); + +extern ASN1_API int + asn1_number_of_elements (asn1_node_const element, const char *name, int *num); + +extern ASN1_API int + asn1_der_coding (asn1_node_const element, const char *name, + void *ider, int *len, char *ErrorDescription); + +extern ASN1_API int + asn1_der_decoding2 (asn1_node *element, const void *ider, + int *max_ider_len, unsigned int flags, + char *errorDescription); + +extern ASN1_API int + asn1_der_decoding (asn1_node * element, const void *ider, + int ider_len, char *errorDescription); + +/* Do not use. Use asn1_der_decoding() instead. */ +extern ASN1_API int + asn1_der_decoding_element (asn1_node * structure, + const char *elementName, + const void *ider, int len, + char *errorDescription) _ASN1_GCC_ATTR_DEPRECATED; + +extern ASN1_API int + asn1_der_decoding_startEnd (asn1_node element, + const void *ider, int ider_len, + const char *name_element, + int *start, int *end); + +extern ASN1_API int + asn1_expand_any_defined_by (asn1_node_const definitions, asn1_node * element); + +extern ASN1_API int + asn1_expand_octet_string (asn1_node_const definitions, + asn1_node * element, + const char *octetName, const char *objectName); + +extern ASN1_API int + asn1_read_tag (asn1_node_const root, const char *name, + int *tagValue, int *classValue); + +extern ASN1_API const char *asn1_find_structure_from_oid (asn1_node_const + definitions, + const char + *oidValue); + +__LIBTASN1_PURE__ +extern ASN1_API const char *asn1_check_version (const char *req_version); + +__LIBTASN1_PURE__ +extern ASN1_API const char *asn1_strerror (int error); + +extern ASN1_API void asn1_perror (int 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) +extern ASN1_API long + asn1_get_length_der (const unsigned char *der, int der_len, int *len); + +extern ASN1_API long + asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len); + +extern ASN1_API void + asn1_length_der (unsigned long int len, unsigned char *der, int *der_len); + +/* 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_decode_simple_ber (unsigned int etype, const unsigned char *der, + unsigned int _der_len, + unsigned char **str, + unsigned int *str_len, + unsigned int *ber_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_node + asn1_find_node (asn1_node_const pointer, const char *name); + +extern ASN1_API int + asn1_copy_node (asn1_node dst, const char *dst_name, + asn1_node_const src, const char *src_name); +extern ASN1_API asn1_node + asn1_dup_node (asn1_node_const src, const char *src_name); + +/* Internal and low-level DER utility functions. */ + +extern ASN1_API int + asn1_get_tag_der (const unsigned char *der, int der_len, + unsigned char *cls, int *len, unsigned long *tag); + +extern ASN1_API void + asn1_octet_der (const unsigned char *str, int str_len, + unsigned char *der, int *der_len); + +extern ASN1_API int + asn1_get_octet_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, + int str_size, int *str_len); + +extern ASN1_API void asn1_bit_der (const unsigned char *str, int bit_len, + unsigned char *der, int *der_len); + +extern ASN1_API int + asn1_get_bit_der (const unsigned char *der, int der_len, + int *ret_len, unsigned char *str, + int str_size, int *bit_len); + +extern ASN1_API int + asn1_get_object_id_der (const unsigned char *der, + int der_len, int *ret_len, + char *str, int str_size); + +extern ASN1_API int + asn1_object_id_der (const char *str, unsigned char *der, int *der_len, + unsigned flags); + +/* Compatibility types */ + +/** + * asn1_retCode: + * + * Type formerly returned by libtasn1 functions. + * + * Deprecated: 3.0: Use int instead. + */ +typedef int asn1_retCode _ASN1_GCC_ATTR_DEPRECATED; + +/** + * node_asn_struct: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_node instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define node_asn_struct _Pragma ("GCC warning \"'node_asn_struct' macro is deprecated, use 'asn1_node' instead.\"") asn1_node_st +#else +#define node_asn_struct asn1_node_st +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * node_asn: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_node instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define node_asn _Pragma ("GCC warning \"'node_asn' macro is deprecated, use 'asn1_node' instead.\"") asn1_node_st +#else +#define node_asn asn1_node_st +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * ASN1_TYPE: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_node instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define ASN1_TYPE _Pragma ("GCC warning \"'ASN1_TYPE' macro is deprecated, use 'asn1_node' instead.\"") asn1_node +#else +#define ASN1_TYPE asn1_node +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * ASN1_TYPE_EMPTY: + * + * Compat #define. + * + * Deprecated: 3.0: Use NULL instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define ASN1_TYPE_EMPTY _Pragma ("GCC warning \"'ASN1_TYPE_EMPTY' macro is deprecated, use 'NULL' instead.\"") NULL +#else +#define ASN1_TYPE_EMPTY NULL +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * static_struct_asn: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_static_node instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define static_struct_asn _Pragma ("GCC warning \"'static_struct_asn' macro is deprecated, use 'asn1_static_node_st' instead.\"") asn1_static_node_st +#else +#define static_struct_asn asn1_static_node_st +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * ASN1_ARRAY_TYPE: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_static_node instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define ASN1_ARRAY_TYPE _Pragma ("GCC warning \"'ASN1_ARRAY_TYPE' macro is deprecated, use 'asn1_static_node' instead.\"") asn1_static_node +#else +#define ASN1_ARRAY_TYPE asn1_static_node +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * asn1_static_node_t: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_static_node instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define asn1_static_node_t _Pragma ("GCC warning \"'asn1_static_node_t' macro is deprecated, use 'asn1_static_node' instead.\"") asn1_static_node +#else +#define asn1_static_node_t asn1_static_node +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * node_data_struct: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_data_node_st instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define node_data_struct _Pragma ("GCC warning \"'node_data_struct' macro is deprecated, use 'asn1_data_node_st' instead.\"") asn1_data_node_st +#else +#define node_data_struct asn1_data_node_st +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +/** + * ASN1_DATA_NODE: + * + * Compat #define. + * + * Deprecated: 3.0: Use #asn1_data_node_st instead. + */ +#ifndef ASN1_DISABLE_DEPRECATED +#if _ASN1_GCC_VERSION >= 30100 +#define ASN1_DATA_NODE _Pragma ("GCC warning \"'asn1_static_node_t' macro is deprecated, use 'asn1_static_node' instead.\"") asn1_data_node_st +#else +#define ASN1_DATA_NODE asn1_data_node_st +#endif +#endif /* !ASN1_DISABLE_DEPRECATED */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIBTASN1_H */ diff --git a/lib/minitasn1/parser_aux.c b/lib/minitasn1/parser_aux.c new file mode 100644 index 0000000..bb88ab9 --- /dev/null +++ b/lib/minitasn1/parser_aux.c @@ -0,0 +1,1173 @@ +/* + * Copyright (C) 2000-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#include <limits.h> // WORD_BIT + +#include "int.h" +#include "parser_aux.h" +#include "gstr.h" +#include "structure.h" +#include "element.h" +#include "c-ctype.h" + +char _asn1_identifierMissing[ASN1_MAX_NAME_SIZE + 1]; /* identifier name not found */ + +/* Return a hash of the N bytes of X using the method described by + Bruno Haible in https://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. + + This implementation has been changed from size_t -> unsigned int. */ + +#ifdef __clang__ +__attribute__((no_sanitize("integer"))) +#endif +_GL_ATTRIBUTE_PURE +static unsigned int +_asn1_hash_name (const char *x) +{ + const unsigned char *s = (unsigned char *) x; + unsigned h = 0; + + while (*s) + h = (*s++) + ((h << 9) | (h >> (WORD_BIT - 9))); + + return h; +} + +/******************************************************/ +/* Function : _asn1_add_static_node */ +/* Description: creates a new NODE_ASN element and */ +/* puts it in the list pointed by e_list. */ +/* Parameters: */ +/* e_list: of type list_type; must be NULL initially */ +/* type: type of the new element (see ASN1_ETYPE_ */ +/* and CONST_ constants). */ +/* Return: pointer to the new element. */ +/******************************************************/ +asn1_node +_asn1_add_static_node (list_type **e_list, unsigned int type) +{ + list_type *p; + asn1_node punt; + + punt = calloc (1, sizeof (struct asn1_node_st)); + if (punt == NULL) + return NULL; + + p = malloc (sizeof (list_type)); + if (p == NULL) + { + free (punt); + return NULL; + } + + p->node = punt; + p->next = *e_list; + *e_list = p; + + punt->type = type; + + return punt; +} + +static +int _asn1_add_static_node2 (list_type **e_list, asn1_node node) +{ + list_type *p; + + p = malloc (sizeof (list_type)); + if (p == NULL) + { + return -1; + } + + p->node = node; + p->next = *e_list; + *e_list = p; + + return 0; +} + +/** + * asn1_find_node: + * @pointer: NODE_ASN element pointer. + * @name: null terminated string with the element's name to find. + * + * Searches for an element called @name starting from @pointer. The + * name is composed by different identifiers separated by dots. When + * *@pointer has a name, the first identifier must be the name of + * *@pointer, otherwise it must be the name of one child of *@pointer. + * + * Returns: the search result, or %NULL if not found. + **/ +asn1_node +asn1_find_node (asn1_node_const pointer, const char *name) +{ + asn1_node_const 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; + + if (name == NULL) + return NULL; + + p = pointer; + n_start = name; + + if (name[0] == '?' && name[1] == 'C' && p->name[0] == '?') + { /* ?CURRENT */ + n_start = strchr(n_start, '.'); + if (n_start) + n_start++; + } + else if (p->name[0] != 0) + { /* has *pointer got a name ? */ + n_end = strchr (n_start, '.'); /* search the first dot */ + if (n_end) + { + nsize = n_end - n_start; + if (nsize >= sizeof(n)) + return NULL; + + memcpy (n, n_start, nsize); + n[nsize] = 0; + n_start = n_end; + n_start++; + + nhash = _asn1_hash_name (n); + } + else + { + _asn1_str_cpy (n, sizeof (n), n_start); + nhash = _asn1_hash_name (n); + + n_start = NULL; + } + + while (p) + { + if (nhash == p->name_hash && (!strcmp (p->name, n))) + break; + else + p = p->right; + } /* while */ + + if (p == NULL) + return NULL; + } + else + { /* *pointer doesn't have a name */ + if (n_start[0] == 0) + return (asn1_node) p; + } + + while (n_start) + { /* Has the end of NAME been reached? */ + n_end = strchr (n_start, '.'); /* search the next dot */ + if (n_end) + { + nsize = n_end - n_start; + if (nsize >= sizeof(n)) + return NULL; + + memcpy (n, n_start, nsize); + n[nsize] = 0; + n_start = n_end; + n_start++; + + nhash = _asn1_hash_name (n); + } + else + { + _asn1_str_cpy (n, sizeof (n), n_start); + nhash = _asn1_hash_name (n); + n_start = NULL; + } + + if (p->down == NULL) + return NULL; + + p = p->down; + if (p == NULL) + return NULL; + + /* The identifier "?LAST" indicates the last element + in the right chain. */ + if (n[0] == '?' && n[1] == 'L') /* ?LAST */ + { + while (p->right) + p = p->right; + } + else + { /* no "?LAST" */ + while (p) + { + if (p->name_hash == nhash && !strcmp (p->name, n)) + break; + else + p = p->right; + } + } + if (p == NULL) + return NULL; + } /* while */ + + return (asn1_node) p; +} + + +/******************************************************************/ +/* Function : _asn1_set_value */ +/* Description: sets the field VALUE in a NODE_ASN element. The */ +/* previous value (if exist) will be lost */ +/* Parameters: */ +/* node: element pointer. */ +/* value: pointer to the value that you want to set. */ +/* len: character number of value. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_set_value (asn1_node node, const void *value, unsigned int len) +{ + if (node == NULL) + return node; + if (node->value) + { + if (node->value != node->small_value) + free (node->value); + node->value = NULL; + node->value_len = 0; + } + + if (!len) + return node; + + if (len < sizeof (node->small_value)) + { + node->value = node->small_value; + } + else + { + node->value = malloc (len); + if (node->value == NULL) + return NULL; + } + node->value_len = len; + + memcpy (node->value, value, len); + return node; +} + +/******************************************************************/ +/* 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 length-value format (LV */ +/* Parameters: */ +/* node: element pointer. */ +/* value: pointer to the value that you want to set. */ +/* len: character number of value. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len) +{ + int len2; + void *temp; + + if (node == NULL) + return node; + + asn1_length_der (len, NULL, &len2); + temp = malloc (len + len2); + if (temp == NULL) + return NULL; + + asn1_octet_der (value, len, temp, &len2); + return _asn1_set_value_m (node, temp, len2); +} + +/* the same as _asn1_set_value except that it sets an already malloc'ed + * value. + */ +asn1_node +_asn1_set_value_m (asn1_node node, void *value, unsigned int len) +{ + if (node == NULL) + return node; + + if (node->value) + { + if (node->value != node->small_value) + free (node->value); + node->value = NULL; + node->value_len = 0; + } + + if (!len) + return node; + + node->value = value; + node->value_len = len; + + return node; +} + +/******************************************************************/ +/* Function : _asn1_append_value */ +/* Description: appends to the field VALUE in a NODE_ASN element. */ +/* */ +/* Parameters: */ +/* node: element pointer. */ +/* value: pointer to the value that you want to be appended. */ +/* len: character number of value. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_append_value (asn1_node node, const void *value, unsigned int len) +{ + if (node == NULL) + return node; + + if (node->value == NULL) + return _asn1_set_value (node, value, len); + + if (len == 0) + return node; + + if (node->value == node->small_value) + { + /* value is in node */ + int prev_len = node->value_len; + node->value_len += len; + node->value = malloc (node->value_len); + if (node->value == NULL) + { + node->value_len = 0; + return NULL; + } + + if (prev_len > 0) + memcpy (node->value, node->small_value, prev_len); + + memcpy (&node->value[prev_len], value, len); + + return node; + } + else /* if (node->value != NULL && node->value != node->small_value) */ + { + /* value is allocated */ + int prev_len = node->value_len; + node->value_len += len; + + node->value = _asn1_realloc (node->value, node->value_len); + if (node->value == NULL) + { + node->value_len = 0; + return NULL; + } + + memcpy (&node->value[prev_len], value, len); + + return node; + } +} + +/******************************************************************/ +/* Function : _asn1_set_name */ +/* Description: sets the field NAME in a NODE_ASN element. The */ +/* previous value (if exist) will be lost */ +/* Parameters: */ +/* node: element pointer. */ +/* name: a null terminated string with the name that you want */ +/* to set. */ +/* Return: pointer to the NODE_ASN element. */ +/******************************************************************/ +asn1_node +_asn1_set_name (asn1_node node, const char *name) +{ + if (node == NULL) + return node; + + _asn1_str_cpy (node->name, sizeof (node->name), name ? name : ""); + node->name_hash = _asn1_hash_name (node->name); + + return node; +} + +/******************************************************************/ +/* 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_node +_asn1_cpy_name (asn1_node dst, asn1_node_const src) +{ + if (dst == NULL) + return dst; + + if (src == NULL) + { + dst->name[0] = 0; + dst->name_hash = _asn1_hash_name (dst->name); + return dst; + } + + _asn1_str_cpy (dst->name, sizeof (dst->name), src->name); + dst->name_hash = src->name_hash; + + return dst; +} + +/******************************************************************/ +/* Function : _asn1_set_right */ +/* Description: sets the field RIGHT in a NODE_ASN element. */ +/* Parameters: */ +/* node: element pointer. */ +/* right: pointer to a NODE_ASN element that you want be pointed*/ +/* by NODE. */ +/* Return: pointer to *NODE. */ +/******************************************************************/ +asn1_node +_asn1_set_right (asn1_node node, asn1_node right) +{ + if (node == NULL) + return node; + node->right = right; + if (right) + right->left = node; + return node; +} + + +/******************************************************************/ +/* Function : _asn1_get_last_right */ +/* Description: return the last element along the right chain. */ +/* Parameters: */ +/* node: starting element pointer. */ +/* Return: pointer to the last element along the right chain. */ +/******************************************************************/ +asn1_node +_asn1_get_last_right (asn1_node_const node) +{ + asn1_node_const p; + + if (node == NULL) + return NULL; + p = node; + while (p->right) + p = p->right; + return (asn1_node) p; +} + +/******************************************************************/ +/* 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_node node, unsigned int flags) +{ + if (node == NULL) + return; + + 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); +} + +/******************************************************************/ +/* Function : _asn1_find_up */ +/* Description: return the father of the NODE_ASN element. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: Null if not found. */ +/******************************************************************/ +asn1_node +_asn1_find_up (asn1_node_const node) +{ + asn1_node_const p; + + if (node == NULL) + return NULL; + + p = node; + + while ((p->left != NULL) && (p->left->right == p)) + p = p->left; + + return p->left; +} + +static +unsigned _asn1_is_up (asn1_node_const up_cand, asn1_node_const down) +{ + asn1_node_const d, u; + + if (up_cand == NULL || down == NULL) + return 0; + + d = down; + + while ((u = _asn1_find_up(d)) != NULL && u != d) + { + if (u == up_cand) + return 1; + d = u; + } + + return 0; +} + +/******************************************************************/ +/* Function : _asn1_delete_node_from_list */ +/* Description: deletes the list element given */ +/******************************************************************/ +void +_asn1_delete_node_from_list (list_type *list, asn1_node node) +{ + list_type *p = list; + + while (p) + { + if (p->node == node) + p->node = NULL; + p = p->next; + } +} + +/******************************************************************/ +/* Function : _asn1_delete_list */ +/* Description: deletes the list elements (not the elements */ +/* pointed by them). */ +/******************************************************************/ +void +_asn1_delete_list (list_type *e_list) +{ + list_type *p; + + while (e_list) + { + p = e_list; + e_list = e_list->next; + free (p); + } +} + +/******************************************************************/ +/* Function : _asn1_delete_list_and nodes */ +/* Description: deletes the list elements and the elements */ +/* pointed by them. */ +/******************************************************************/ +void +_asn1_delete_list_and_nodes (list_type *e_list) +{ + list_type *p; + + while (e_list) + { + p = e_list; + e_list = e_list->next; + _asn1_remove_node (p->node, 0); + free (p); + } +} + + +char * +_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]) +{ + uint64_t d, r; + char temp[LTOSTR_MAX_SIZE]; + int count, k, start; + uint64_t val; + + if (v < 0) + { + str[0] = '-'; + start = 1; + val = -((uint64_t)v); + } + else + { + val = v; + start = 0; + } + + count = 0; + do + { + d = val / 10; + r = val - d * 10; + temp[start + count] = '0' + (char) r; + count++; + val = d; + } + while (val && ((start+count) < LTOSTR_MAX_SIZE-1)); + + for (k = 0; k < count; k++) + str[k + start] = temp[start + count - k - 1]; + str[count + start] = 0; + return str; +} + + +/******************************************************************/ +/* Function : _asn1_change_integer_value */ +/* Description: converts into DER coding the value assign to an */ +/* INTEGER constant. */ +/* Parameters: */ +/* node: root of an ASN1element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_change_integer_value (asn1_node node) +{ + asn1_node p; + unsigned char val[SIZEOF_UNSIGNED_LONG_INT]; + unsigned char val2[SIZEOF_UNSIGNED_LONG_INT + 1]; + int len; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if ((type_field (p->type) == ASN1_ETYPE_INTEGER) + && (p->type & CONST_ASSIGN)) + { + if (p->value) + { + _asn1_convert_integer (p->value, val, sizeof (val), &len); + asn1_octet_der (val, len, val2, &len); + _asn1_set_value (p, val2, len); + } + } + + if (p->down) + { + p = p->down; + } + else + { + if (p == node) + p = NULL; + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p && p->right) + { + p = p->right; + break; + } + } + } + } + } + + return ASN1_SUCCESS; +} + +#define MAX_CONSTANTS 1024 +/******************************************************************/ +/* Function : _asn1_expand_object_id */ +/* Description: expand the IDs of an OBJECT IDENTIFIER constant. */ +/* Parameters: */ +/* list: root of an object list */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_expand_object_id (list_type **list, asn1_node node) +{ + asn1_node p, p2, p3, p4, p5; + char name_root[ASN1_MAX_NAME_SIZE], name2[2 * ASN1_MAX_NAME_SIZE + 1]; + int move, tlen, tries; + unsigned max_constants; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + _asn1_str_cpy (name_root, sizeof (name_root), node->name); + + p = node; + move = DOWN; + tries = 0; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) + && (p->type & CONST_ASSIGN)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) + { + if (p2->value && !c_isdigit (p2->value[0])) + { + _asn1_str_cpy (name2, sizeof (name2), name_root); + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + p3 = asn1_find_node (node, name2); + if (!p3 || _asn1_is_up(p2, p3) || + (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) || + !(p3->type & CONST_ASSIGN)) + return ASN1_ELEMENT_NOT_FOUND; + + _asn1_set_down (p, p2->right); + if (p2->down) + _asn1_delete_structure (*list, &p2->down, 0); + _asn1_delete_node_from_list(*list, p2); + _asn1_remove_node (p2, 0); + p2 = p; + p4 = p3->down; + max_constants = 0; + while (p4) + { + if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) + { + max_constants++; + if (max_constants == MAX_CONSTANTS) + return ASN1_RECURSION; + + p5 = + _asn1_add_single_node (ASN1_ETYPE_CONSTANT); + _asn1_set_name (p5, p4->name); + if (p4->value) + { + tlen = _asn1_strlen (p4->value); + if (tlen > 0) + _asn1_set_value (p5, p4->value, tlen + 1); + } + _asn1_add_static_node2(list, p5); + + if (p2 == p) + { + _asn1_set_right (p5, p->down); + _asn1_set_down (p, p5); + } + else + { + _asn1_set_right (p5, p2->right); + _asn1_set_right (p2, p5); + } + p2 = p5; + } + p4 = p4->right; + } + move = DOWN; + + tries++; + if (tries >= EXPAND_OBJECT_ID_MAX_RECURSION) + return ASN1_RECURSION; + + continue; + } + } + } + move = DOWN; + } + else + move = RIGHT; + + tries = 0; + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p && p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + /*******************************/ + /* expand DEFAULT */ + /*******************************/ + p = node; + move = DOWN; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_DEFAULT)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) + { + _asn1_str_cpy (name2, sizeof (name2), name_root); + _asn1_str_cat (name2, sizeof (name2), "."); + if (p2->value) + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + p3 = asn1_find_node (node, name2); + if (!p3 || (type_field (p3->type) != ASN1_ETYPE_OBJECT_ID) + || !(p3->type & CONST_ASSIGN)) + return ASN1_ELEMENT_NOT_FOUND; + p4 = p3->down; + name2[0] = 0; + while (p4) + { + if (type_field (p4->type) == ASN1_ETYPE_CONSTANT) + { + if (p4->value == NULL) + return ASN1_VALUE_NOT_FOUND; + + if (name2[0]) + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), + (char *) p4->value); + } + p4 = p4->right; + } + tlen = strlen (name2); + if (tlen > 0) + _asn1_set_value (p2, name2, tlen + 1); + } + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p && p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_type_set_config */ +/* Description: sets the CONST_SET and CONST_NOT_USED properties */ +/* in the fields of the SET elements. */ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_type_set_config (asn1_node node) +{ + asn1_node p, p2; + int move; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + move = DOWN; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if (type_field (p->type) == ASN1_ETYPE_SET) + { + p2 = p->down; + while (p2) + { + if (type_field (p2->type) != ASN1_ETYPE_TAG) + p2->type |= CONST_SET | CONST_NOT_USED; + p2 = p2->right; + } + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p && p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_check_identifier */ +/* Description: checks the definitions of all the identifiers */ +/* and the first element of an OBJECT_ID (e.g. {pkix 0 4}). */ +/* The _asn1_identifierMissing global variable is filled if */ +/* necessary. */ +/* Parameters: */ +/* node: root of an ASN1 element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL, */ +/* ASN1_IDENTIFIER_NOT_FOUND if an identifier is not defined, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_check_identifier (asn1_node_const node) +{ + asn1_node_const p, p2; + char name2[ASN1_MAX_NAME_SIZE * 2 + 2]; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if (p->value && type_field (p->type) == ASN1_ETYPE_IDENTIFIER) + { + _asn1_str_cpy (name2, sizeof (name2), node->name); + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p->value); + p2 = asn1_find_node (node, name2); + if (p2 == NULL) + { + if (p->value) + _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p->value); + else + _asn1_strcpy (_asn1_identifierMissing, "(null)"); + return ASN1_IDENTIFIER_NOT_FOUND; + } + } + else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_DEFAULT)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_DEFAULT)) + { + _asn1_str_cpy (name2, sizeof (name2), node->name); + if (p2->value) + { + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); + } + else + _asn1_strcpy (_asn1_identifierMissing, "(null)"); + + p2 = asn1_find_node (node, name2); + if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) || + !(p2->type & CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + _asn1_identifierMissing[0] = 0; + } + } + else if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_ASSIGN)) + { + p2 = p->down; + if (p2 && (type_field (p2->type) == ASN1_ETYPE_CONSTANT)) + { + if (p2->value && !c_isdigit (p2->value[0])) + { + _asn1_str_cpy (name2, sizeof (name2), node->name); + _asn1_str_cat (name2, sizeof (name2), "."); + _asn1_str_cat (name2, sizeof (name2), (char *) p2->value); + _asn1_str_cpy (_asn1_identifierMissing, sizeof(_asn1_identifierMissing), (char*)p2->value); + + p2 = asn1_find_node (node, name2); + if (!p2 || (type_field (p2->type) != ASN1_ETYPE_OBJECT_ID) + || !(p2->type & CONST_ASSIGN)) + return ASN1_IDENTIFIER_NOT_FOUND; + else + _asn1_identifierMissing[0] = 0; + } + } + } + + if (p->down) + { + p = p->down; + } + else if (p->right) + p = p->right; + else + { + while (p) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p && p->right) + { + p = p->right; + break; + } + } + } + } + + return ASN1_SUCCESS; +} + + +/******************************************************************/ +/* Function : _asn1_set_default_tag */ +/* Description: sets the default IMPLICIT or EXPLICIT property in */ +/* the tagged elements that don't have this declaration. */ +/* Parameters: */ +/* node: pointer to a DEFINITIONS element. */ +/* Return: */ +/* ASN1_ELEMENT_NOT_FOUND if NODE is NULL or not a pointer to */ +/* a DEFINITIONS element, */ +/* otherwise ASN1_SUCCESS */ +/******************************************************************/ +int +_asn1_set_default_tag (asn1_node node) +{ + asn1_node p; + + if ((node == NULL) || (type_field (node->type) != ASN1_ETYPE_DEFINITIONS)) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + while (p) + { + if ((type_field (p->type) == ASN1_ETYPE_TAG) && + !(p->type & CONST_EXPLICIT) && !(p->type & CONST_IMPLICIT)) + { + if (node->type & CONST_EXPLICIT) + p->type |= CONST_EXPLICIT; + else + p->type |= CONST_IMPLICIT; + } + + if (p->down) + { + p = p->down; + } + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == node) + { + p = NULL; + break; + } + if (p && p->right) + { + p = p->right; + break; + } + } + } + } + + return ASN1_SUCCESS; +} diff --git a/lib/minitasn1/parser_aux.h b/lib/minitasn1/parser_aux.h new file mode 100644 index 0000000..0e8621b --- /dev/null +++ b/lib/minitasn1/parser_aux.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2000-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifndef _PARSER_AUX_H +#define _PARSER_AUX_H + +/***********************************************/ +/* Type: list_type */ +/* Description: type used in the list during */ +/* the structure creation. */ +/***********************************************/ +typedef struct list_struct +{ + asn1_node node; + struct list_struct *next; +} list_type; + +/***************************************/ +/* Functions used by ASN.1 parser */ +/***************************************/ +asn1_node _asn1_add_static_node (list_type **e_list, unsigned int type); + +void _asn1_delete_list (list_type *e_list); + +void _asn1_delete_list_and_nodes (list_type *e_list); + +void _asn1_delete_node_from_list (list_type *list, asn1_node node); + +asn1_node +_asn1_set_value (asn1_node node, const void *value, unsigned int len); + +asn1_node _asn1_set_value_m (asn1_node node, void *value, unsigned int len); + +asn1_node +_asn1_set_value_lv (asn1_node node, const void *value, unsigned int len); + +asn1_node +_asn1_append_value (asn1_node node, const void *value, unsigned int len); + +asn1_node _asn1_set_name (asn1_node node, const char *name); + +asn1_node _asn1_cpy_name (asn1_node dst, asn1_node_const src); + +asn1_node _asn1_set_right (asn1_node node, asn1_node right); + +asn1_node _asn1_get_last_right (asn1_node_const node); + +void _asn1_remove_node (asn1_node node, unsigned int flags); + +/* Max 64-bit integer length is 20 chars + 1 for sign + 1 for null termination */ +#define LTOSTR_MAX_SIZE 22 +char *_asn1_ltostr (int64_t v, char str[LTOSTR_MAX_SIZE]); + +asn1_node _asn1_find_up (asn1_node_const node); + +int _asn1_change_integer_value (asn1_node node); + +#define EXPAND_OBJECT_ID_MAX_RECURSION 16 +int _asn1_expand_object_id (list_type **list, asn1_node node); + +int _asn1_type_set_config (asn1_node node); + +int _asn1_check_identifier (asn1_node_const node); + +int _asn1_set_default_tag (asn1_node 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_node +_asn1_get_right (asn1_node_const 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_node +_asn1_set_down (asn1_node node, asn1_node 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_node +_asn1_get_down (asn1_node_const 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_node_const node) +{ + if (node == NULL) + return NULL; + return (char *) 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_node +_asn1_mod_type (asn1_node node, unsigned int value) +{ + if (node == NULL) + return node; + node->type |= value; + return node; +} + +#endif diff --git a/lib/minitasn1/structure.c b/lib/minitasn1/structure.c new file mode 100644 index 0000000..4f43335 --- /dev/null +++ b/lib/minitasn1/structure.c @@ -0,0 +1,1220 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + + +/*****************************************************/ +/* File: structure.c */ +/* Description: Functions to create and delete an */ +/* ASN1 tree. */ +/*****************************************************/ + + +#include <int.h> +#include <structure.h> +#include "parser_aux.h" +#include <gstr.h> + + +extern char _asn1_identifierMissing[]; + + +/******************************************************/ +/* Function : _asn1_add_single_node */ +/* Description: creates a new NODE_ASN element. */ +/* Parameters: */ +/* type: type of the new element (see ASN1_ETYPE_ */ +/* and CONST_ constants). */ +/* Return: pointer to the new element. */ +/******************************************************/ +asn1_node +_asn1_add_single_node (unsigned int type) +{ + asn1_node punt; + + punt = calloc (1, sizeof (struct asn1_node_st)); + if (punt == NULL) + return NULL; + + punt->type = type; + + return punt; +} + + +/******************************************************************/ +/* Function : _asn1_find_left */ +/* Description: returns the NODE_ASN element with RIGHT field that*/ +/* points the element NODE. */ +/* Parameters: */ +/* node: NODE_ASN element pointer. */ +/* Return: NULL if not found. */ +/******************************************************************/ +asn1_node +_asn1_find_left (asn1_node_const node) +{ + if ((node == NULL) || (node->left == NULL) || (node->left->down == node)) + return NULL; + + return node->left; +} + + +int +_asn1_create_static_structure (asn1_node_const pointer, char *output_file_name, + char *vector_name) +{ + FILE *file; + asn1_node_const p; + unsigned long t; + + file = fopen (output_file_name, "w"); + + if (file == NULL) + return ASN1_FILE_NOT_FOUND; + + fprintf (file, "#if HAVE_CONFIG_H\n"); + fprintf (file, "# include \"config.h\"\n"); + fprintf (file, "#endif\n\n"); + + fprintf (file, "#include <libtasn1.h>\n\n"); + + fprintf (file, "const asn1_static_node %s[] = {\n", vector_name); + + p = pointer; + + while (p) + { + fprintf (file, " { "); + + if (p->name[0] != 0) + fprintf (file, "\"%s\", ", p->name); + else + fprintf (file, "NULL, "); + + t = p->type; + if (p->down) + t |= CONST_DOWN; + if (p->right) + t |= CONST_RIGHT; + + fprintf (file, "%lu, ", t); + + if (p->value) + fprintf (file, "\"%s\"},\n", p->value); + else + fprintf (file, "NULL },\n"); + + if (p->down) + { + p = p->down; + } + else if (p->right) + { + p = p->right; + } + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == pointer) + { + p = NULL; + break; + } + if (p->right) + { + p = p->right; + break; + } + } + } + } + + fprintf (file, " { NULL, 0, NULL }\n};\n"); + + fclose (file); + + return ASN1_SUCCESS; +} + + +/** + * asn1_array2tree: + * @array: specify the array that contains ASN.1 declarations + * @definitions: return the pointer to the structure created by + * *ARRAY ASN.1 declarations + * @errorDescription: return the error description. + * + * Creates the structures needed to manage the ASN.1 definitions. + * @array is a vector created by asn1_parser2array(). + * + * 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. + **/ +int +asn1_array2tree (const asn1_static_node * array, asn1_node * definitions, + char *errorDescription) +{ + asn1_node p, p_last = NULL; + unsigned long k; + int move; + int result; + unsigned int type; + list_type *e_list = NULL; + + if (errorDescription) + errorDescription[0] = 0; + + if (*definitions != NULL) + return ASN1_ELEMENT_NOT_EMPTY; + + move = UP; + + for (k = 0; array[k].value || array[k].type || array[k].name; k++) + { + type = convert_old_type (array[k].type); + + p = _asn1_add_static_node (&e_list, type & (~CONST_DOWN)); + if (array[k].name) + _asn1_set_name (p, array[k].name); + if (array[k].value) + _asn1_set_value (p, array[k].value, strlen (array[k].value) + 1); + + if (*definitions == NULL) + *definitions = p; + + if (move == DOWN) + { + if (p_last && p_last->down) + _asn1_delete_structure (e_list, &p_last->down, 0); + _asn1_set_down (p_last, p); + } + else if (move == RIGHT) + { + if (p_last && p_last->right) + _asn1_delete_structure (e_list, &p_last->right, 0); + _asn1_set_right (p_last, p); + } + + p_last = p; + + if (type & CONST_DOWN) + move = DOWN; + else if (type & CONST_RIGHT) + move = RIGHT; + else + { + while (p_last != *definitions) + { + p_last = _asn1_find_up (p_last); + + if (p_last == NULL) + break; + + if (p_last->type & CONST_RIGHT) + { + p_last->type &= ~CONST_RIGHT; + move = RIGHT; + break; + } + } /* while */ + } + } /* while */ + + if (p_last == *definitions) + { + result = _asn1_check_identifier (*definitions); + if (result == ASN1_SUCCESS) + { + _asn1_change_integer_value (*definitions); + result = _asn1_expand_object_id (&e_list, *definitions); + } + } + else + { + result = ASN1_ARRAY_ERROR; + } + + if (errorDescription != NULL) + { + if (result == ASN1_IDENTIFIER_NOT_FOUND) + { + Estrcpy (errorDescription, ":: identifier '"); + Estrcat (errorDescription, _asn1_identifierMissing); + Estrcat (errorDescription, "' not found"); + } + else + errorDescription[0] = 0; + } + + if (result != ASN1_SUCCESS) + { + _asn1_delete_list_and_nodes (e_list); + *definitions = NULL; + } + else + _asn1_delete_list (e_list); + + return result; +} + +/** + * asn1_delete_structure: + * @structure: pointer to the structure that you want to delete. + * + * Deletes the structure *@structure. At the end, *@structure is set + * to NULL. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * *@structure was NULL. + **/ +int +asn1_delete_structure (asn1_node * structure) +{ + return _asn1_delete_structure (NULL, structure, 0); +} + +/** + * asn1_delete_structure2: + * @structure: pointer to the structure that you want to delete. + * @flags: additional flags (see %ASN1_DELETE_FLAG) + * + * Deletes the structure *@structure. At the end, *@structure is set + * to NULL. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * *@structure was NULL. + **/ +int +asn1_delete_structure2 (asn1_node * structure, unsigned int flags) +{ + return _asn1_delete_structure (NULL, structure, flags); +} + +int +_asn1_delete_structure (list_type *e_list, asn1_node * structure, unsigned int flags) +{ + asn1_node p, p2, p3; + + if (*structure == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = *structure; + while (p) + { + if (p->down) + { + p = p->down; + } + else + { /* no down */ + p2 = p->right; + if (p != *structure) + { + p3 = _asn1_find_up (p); + _asn1_set_down (p3, p2); + if (e_list) + _asn1_delete_node_from_list (e_list, p); + _asn1_remove_node (p, flags); + p = p3; + } + else + { /* p==root */ + p3 = _asn1_find_left (p); + if (!p3) + { + p3 = _asn1_find_up (p); + if (p3) + _asn1_set_down (p3, p2); + else + { + if (p->right) + p->right->left = NULL; + } + } + else + _asn1_set_right (p3, p2); + if (e_list) + _asn1_delete_node_from_list (e_list, p); + _asn1_remove_node (p, flags); + p = NULL; + } + } + } + + *structure = NULL; + return ASN1_SUCCESS; +} + + +/** + * asn1_delete_element: + * @structure: pointer to the structure that contains the element you + * want to delete. + * @element_name: element's name you want to delete. + * + * Deletes the element named *@element_name inside *@structure. + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * the @element_name was not found. + **/ +int +asn1_delete_element (asn1_node structure, const char *element_name) +{ + asn1_node p2, p3, source_node; + + source_node = asn1_find_node (structure, element_name); + + if (source_node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p2 = source_node->right; + p3 = _asn1_find_left (source_node); + if (!p3) + { + p3 = _asn1_find_up (source_node); + if (p3) + _asn1_set_down (p3, p2); + else if (source_node->right) + source_node->right->left = NULL; + } + else + _asn1_set_right (p3, p2); + + return asn1_delete_structure (&source_node); +} + +#ifndef __clang_analyzer__ +asn1_node +_asn1_copy_structure3 (asn1_node_const source_node) +{ + asn1_node_const p_s; + asn1_node dest_node, p_d, p_d_prev; + int move; + + if (source_node == NULL) + return NULL; + + dest_node = _asn1_add_single_node (source_node->type); + + p_s = source_node; + p_d = dest_node; + + move = DOWN; + + do + { + if (move != UP) + { + 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); + if (p_s->down) + { + p_s = p_s->down; + p_d_prev = p_d; + p_d = _asn1_add_single_node (p_s->type); + _asn1_set_down (p_d_prev, p_d); + continue; + } + p_d->start = p_s->start; + p_d->end = p_s->end; + } + + if (p_s == source_node) + break; + + if (p_s->right) + { + 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); + } + else + { + move = UP; + p_s = _asn1_find_up (p_s); + p_d = _asn1_find_up (p_d); + } + } + while (p_s != source_node); + return dest_node; +} +#else + +/* Non-production code */ +asn1_node +_asn1_copy_structure3 (asn1_node_const source_node) +{ + return NULL; +} +#endif /* __clang_analyzer__ */ + + +static asn1_node +_asn1_copy_structure2 (asn1_node_const root, const char *source_name) +{ + asn1_node source_node; + + source_node = asn1_find_node (root, source_name); + + return _asn1_copy_structure3 (source_node); + +} + + +static int +_asn1_type_choice_config (asn1_node node) +{ + asn1_node p, p2, p3, p4; + int move, tlen; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node; + move = DOWN; + + while (!((p == node) && (move == UP))) + { + if (move != UP) + { + if ((type_field (p->type) == ASN1_ETYPE_CHOICE) + && (p->type & CONST_TAG)) + { + p2 = p->down; + while (p2) + { + if (type_field (p2->type) != ASN1_ETYPE_TAG) + { + p2->type |= CONST_TAG; + p3 = _asn1_find_left (p2); + while (p3) + { + if (type_field (p3->type) == ASN1_ETYPE_TAG) + { + 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); + _asn1_set_down (p2, p4); + } + p3 = _asn1_find_left (p3); + } + } + p2 = p2->right; + } + p->type &= ~(CONST_TAG); + p2 = p->down; + while (p2) + { + p3 = p2->right; + if (type_field (p2->type) == ASN1_ETYPE_TAG) + asn1_delete_structure (&p2); + p2 = p3; + } + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +static int +_asn1_expand_identifier (asn1_node * node, asn1_node_const root) +{ + asn1_node p, p2, p3; + char name2[ASN1_MAX_NAME_SIZE + 2]; + int move; + + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = *node; + move = DOWN; + + while (!((p == *node) && (move == UP))) + { + if (move != UP) + { + if (type_field (p->type) == ASN1_ETYPE_IDENTIFIER) + { + 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_cpy_name (p2, p); + p2->right = p->right; + p2->left = p->left; + if (p->right) + p->right->left = p2; + p3 = p->down; + if (p3) + { + while (p3->right) + p3 = p3->right; + _asn1_set_right (p3, p2->down); + _asn1_set_down (p2, p->down); + } + + p3 = _asn1_find_left (p); + if (p3) + _asn1_set_right (p3, p2); + else + { + p3 = _asn1_find_up (p); + if (p3) + _asn1_set_down (p3, p2); + else + { + p2->left = NULL; + } + } + + if (p->type & CONST_SIZE) + p2->type |= CONST_SIZE; + if (p->type & CONST_TAG) + p2->type |= CONST_TAG; + if (p->type & CONST_OPTION) + p2->type |= CONST_OPTION; + if (p->type & CONST_DEFAULT) + p2->type |= CONST_DEFAULT; + if (p->type & CONST_SET) + p2->type |= CONST_SET; + if (p->type & CONST_NOT_USED) + p2->type |= CONST_NOT_USED; + + if (p == *node) + *node = p2; + _asn1_remove_node (p, 0); + p = p2; + move = DOWN; + continue; + } + move = DOWN; + } + else + move = RIGHT; + + if (move == DOWN) + { + if (p->down) + p = p->down; + else + move = RIGHT; + } + + if (p == *node) + { + move = UP; + continue; + } + + if (move == RIGHT) + { + if (p->right) + p = p->right; + else + move = UP; + } + if (move == UP) + p = _asn1_find_up (p); + } + + return ASN1_SUCCESS; +} + + +/** + * asn1_create_element: + * @definitions: pointer to the structure returned by "parser_asn1" function + * @source_name: the name of the type of the new structure (must be + * inside p_structure). + * @element: pointer to the structure created. + * + * Creates a structure of type @source_name. Example using + * "pkix.asn": + * + * rc = asn1_create_element(cert_def, "PKIX1.Certificate", certptr); + * + * Returns: %ASN1_SUCCESS if creation OK, %ASN1_ELEMENT_NOT_FOUND if + * @source_name is not known. + **/ +int +asn1_create_element (asn1_node_const definitions, const char *source_name, + asn1_node * element) +{ + asn1_node dest_node; + int res; + + dest_node = _asn1_copy_structure2 (definitions, source_name); + + if (dest_node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + _asn1_set_name (dest_node, ""); + + res = _asn1_expand_identifier (&dest_node, definitions); + _asn1_type_choice_config (dest_node); + + *element = dest_node; + + return res; +} + + +/** + * asn1_print_structure: + * @out: pointer to the output file (e.g. stdout). + * @structure: pointer to the structure that you want to visit. + * @name: an element of the structure + * @mode: specify how much of the structure to print, can be + * %ASN1_PRINT_NAME, %ASN1_PRINT_NAME_TYPE, + * %ASN1_PRINT_NAME_TYPE_VALUE, or %ASN1_PRINT_ALL. + * + * Prints on the @out file descriptor the structure's tree starting + * from the @name element inside the structure @structure. + **/ +void +asn1_print_structure (FILE * out, asn1_node_const structure, const char *name, + int mode) +{ + asn1_node_const p, root; + int k, indent = 0, len, len2, len3; + + if (out == NULL) + return; + + root = asn1_find_node (structure, name); + + if (root == NULL) + return; + + p = root; + while (p) + { + if (mode == ASN1_PRINT_ALL) + { + for (k = 0; k < indent; k++) + fprintf (out, " "); + fprintf (out, "name:"); + if (p->name[0] != 0) + fprintf (out, "%s ", p->name); + else + fprintf (out, "NULL "); + } + else + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_CONSTANT: + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_SIZE: + break; + default: + for (k = 0; k < indent; k++) + fprintf (out, " "); + fprintf (out, "name:"); + if (p->name[0] != 0) + fprintf (out, "%s ", p->name); + else + fprintf (out, "NULL "); + } + } + + if (mode != ASN1_PRINT_NAME) + { + unsigned type = type_field (p->type); + switch (type) + { + case ASN1_ETYPE_CONSTANT: + if (mode == ASN1_PRINT_ALL) + fprintf (out, "type:CONST"); + break; + case ASN1_ETYPE_TAG: + if (mode == ASN1_PRINT_ALL) + fprintf (out, "type:TAG"); + break; + case ASN1_ETYPE_SIZE: + if (mode == ASN1_PRINT_ALL) + fprintf (out, "type:SIZE"); + break; + case ASN1_ETYPE_DEFAULT: + fprintf (out, "type:DEFAULT"); + break; + case ASN1_ETYPE_IDENTIFIER: + fprintf (out, "type:IDENTIFIER"); + break; + case ASN1_ETYPE_ANY: + fprintf (out, "type:ANY"); + break; + case ASN1_ETYPE_CHOICE: + fprintf (out, "type:CHOICE"); + break; + case ASN1_ETYPE_DEFINITIONS: + fprintf (out, "type:DEFINITIONS"); + break; + CASE_HANDLED_ETYPES: + fprintf (out, "%s", _asn1_tags[type].desc); + break; + default: + break; + } + } + + if ((mode == ASN1_PRINT_NAME_TYPE_VALUE) || (mode == ASN1_PRINT_ALL)) + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_CONSTANT: + if (mode == ASN1_PRINT_ALL) + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_TAG: + if (mode == ASN1_PRINT_ALL) + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_SIZE: + if (mode == ASN1_PRINT_ALL) + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_DEFAULT: + if (p->value) + fprintf (out, " value:%s", p->value); + else if (p->type & CONST_TRUE) + fprintf (out, " value:TRUE"); + else if (p->type & CONST_FALSE) + fprintf (out, " value:FALSE"); + break; + case ASN1_ETYPE_IDENTIFIER: + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_INTEGER: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:0x"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_ENUMERATED: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:0x"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_BOOLEAN: + if (p->value) + { + if (p->value[0] == 'T') + fprintf (out, " value:TRUE"); + else if (p->value[0] == 'F') + fprintf (out, " value:FALSE"); + } + break; + case ASN1_ETYPE_BIT_STRING: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + if (len > 0) + { + fprintf (out, " value(%i):", + (len - 1) * 8 - (p->value[len2])); + for (k = 1; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + } + break; + case ASN1_ETYPE_GENERALIZED_TIME: + case ASN1_ETYPE_UTC_TIME: + if (p->value) + { + fprintf (out, " value:"); + for (k = 0; k < p->value_len; k++) + fprintf (out, "%c", (p->value)[k]); + } + break; + case ASN1_ETYPE_GENERALSTRING: + case ASN1_ETYPE_NUMERIC_STRING: + case ASN1_ETYPE_IA5_STRING: + case ASN1_ETYPE_TELETEX_STRING: + case ASN1_ETYPE_PRINTABLE_STRING: + case ASN1_ETYPE_UNIVERSAL_STRING: + case ASN1_ETYPE_UTF8_STRING: + case ASN1_ETYPE_VISIBLE_STRING: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%c", (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_BMP_STRING: + case ASN1_ETYPE_OCTET_STRING: + if (p->value) + { + len2 = -1; + len = asn1_get_length_der (p->value, p->value_len, &len2); + fprintf (out, " value:"); + if (len > 0) + for (k = 0; k < len; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len2]); + } + break; + case ASN1_ETYPE_OBJECT_ID: + if (p->value) + fprintf (out, " value:%s", p->value); + break; + case ASN1_ETYPE_ANY: + if (p->value) + { + len3 = -1; + len2 = asn1_get_length_der (p->value, p->value_len, &len3); + fprintf (out, " value:"); + if (len2 > 0) + for (k = 0; k < len2; k++) + fprintf (out, "%02x", (unsigned) (p->value)[k + len3]); + } + break; + case ASN1_ETYPE_SET: + case ASN1_ETYPE_SET_OF: + case ASN1_ETYPE_CHOICE: + case ASN1_ETYPE_DEFINITIONS: + case ASN1_ETYPE_SEQUENCE_OF: + case ASN1_ETYPE_SEQUENCE: + case ASN1_ETYPE_NULL: + break; + default: + break; + } + } + + if (mode == ASN1_PRINT_ALL) + { + if (p->type & 0x1FFFFF00) + { + fprintf (out, " attr:"); + if (p->type & CONST_UNIVERSAL) + fprintf (out, "UNIVERSAL,"); + if (p->type & CONST_PRIVATE) + fprintf (out, "PRIVATE,"); + if (p->type & CONST_APPLICATION) + fprintf (out, "APPLICATION,"); + if (p->type & CONST_EXPLICIT) + fprintf (out, "EXPLICIT,"); + if (p->type & CONST_IMPLICIT) + fprintf (out, "IMPLICIT,"); + if (p->type & CONST_TAG) + fprintf (out, "TAG,"); + if (p->type & CONST_DEFAULT) + fprintf (out, "DEFAULT,"); + if (p->type & CONST_TRUE) + fprintf (out, "TRUE,"); + if (p->type & CONST_FALSE) + fprintf (out, "FALSE,"); + if (p->type & CONST_LIST) + fprintf (out, "LIST,"); + if (p->type & CONST_MIN_MAX) + fprintf (out, "MIN_MAX,"); + if (p->type & CONST_OPTION) + fprintf (out, "OPTION,"); + if (p->type & CONST_1_PARAM) + fprintf (out, "1_PARAM,"); + if (p->type & CONST_SIZE) + fprintf (out, "SIZE,"); + if (p->type & CONST_DEFINED_BY) + fprintf (out, "DEF_BY,"); + if (p->type & CONST_GENERALIZED) + fprintf (out, "GENERALIZED,"); + if (p->type & CONST_UTC) + fprintf (out, "UTC,"); + if (p->type & CONST_SET) + fprintf (out, "SET,"); + if (p->type & CONST_NOT_USED) + fprintf (out, "NOT_USED,"); + if (p->type & CONST_ASSIGN) + fprintf (out, "ASSIGNMENT,"); + } + } + + if (mode == ASN1_PRINT_ALL) + { + fprintf (out, "\n"); + } + else + { + switch (type_field (p->type)) + { + case ASN1_ETYPE_CONSTANT: + case ASN1_ETYPE_TAG: + case ASN1_ETYPE_SIZE: + break; + default: + fprintf (out, "\n"); + } + } + + if (p->down) + { + p = p->down; + indent += 2; + } + else if (p == root) + { + p = NULL; + break; + } + else if (p->right) + p = p->right; + else + { + while (1) + { + p = _asn1_find_up (p); + if (p == root) + { + p = NULL; + break; + } + indent -= 2; + if (p->right) + { + p = p->right; + break; + } + } + } + } +} + + + +/** + * asn1_number_of_elements: + * @element: pointer to the root of an ASN1 structure. + * @name: the name of a sub-structure of ROOT. + * @num: pointer to an integer where the result will be stored + * + * Counts the number of elements of a sub-structure called NAME with + * names equal to "?1","?2", ... + * + * Returns: %ASN1_SUCCESS if successful, %ASN1_ELEMENT_NOT_FOUND if + * @name is not known, %ASN1_GENERIC_ERROR if pointer @num is %NULL. + **/ +int +asn1_number_of_elements (asn1_node_const element, const char *name, int *num) +{ + asn1_node_const node, p; + + if (num == NULL) + return ASN1_GENERIC_ERROR; + + *num = 0; + + node = asn1_find_node (element, name); + if (node == NULL) + return ASN1_ELEMENT_NOT_FOUND; + + p = node->down; + + while (p) + { + if (p->name[0] == '?') + (*num)++; + p = p->right; + } + + return ASN1_SUCCESS; +} + + +/** + * asn1_find_structure_from_oid: + * @definitions: ASN1 definitions + * @oidValue: value of the OID to search (e.g. "1.2.3.4"). + * + * Search the structure that is defined just after an OID definition. + * + * Returns: %NULL when @oidValue not found, otherwise the pointer to a + * constant string that contains the element name defined just after + * the OID. + **/ +const char * +asn1_find_structure_from_oid (asn1_node_const definitions, const char *oidValue) +{ + char name[2 * ASN1_MAX_NAME_SIZE + 2]; + char value[ASN1_MAX_NAME_SIZE]; + asn1_node p; + int len; + int result; + const char *definitionsName; + + if ((definitions == NULL) || (oidValue == NULL)) + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ + + definitionsName = definitions->name; + + /* search the OBJECT_ID into definitions */ + p = definitions->down; + while (p) + { + if ((type_field (p->type) == ASN1_ETYPE_OBJECT_ID) && + (p->type & CONST_ASSIGN)) + { + snprintf(name, sizeof(name), "%s.%s", definitionsName, p->name); + + len = ASN1_MAX_NAME_SIZE; + result = asn1_read_value (definitions, name, value, &len); + + if ((result == ASN1_SUCCESS) && (!strcmp (oidValue, value))) + { + p = p->right; + if (p == NULL) /* reach the end of ASN1 definitions */ + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ + + return p->name; + } + } + p = p->right; + } + + return NULL; /* ASN1_ELEMENT_NOT_FOUND; */ +} + +/** + * asn1_copy_node: + * @dst: Destination asn1 node. + * @dst_name: Field name in destination node. + * @src: Source asn1 node. + * @src_name: Field name in source node. + * + * Create a deep copy of a asn1_node variable. That + * function requires @dst to be expanded using asn1_create_element(). + * + * Returns: Return %ASN1_SUCCESS on success. + **/ +int +asn1_copy_node (asn1_node dst, const char *dst_name, + asn1_node_const src, const char *src_name) +{ + int result; + asn1_node dst_node; + void *data = NULL; + int size = 0; + + result = asn1_der_coding (src, src_name, NULL, &size, NULL); + if (result != ASN1_MEM_ERROR) + return result; + + data = malloc (size); + if (data == NULL) + return ASN1_MEM_ERROR; + + result = asn1_der_coding (src, src_name, data, &size, NULL); + if (result != ASN1_SUCCESS) + { + free (data); + return result; + } + + dst_node = asn1_find_node (dst, dst_name); + if (dst_node == NULL) + { + free (data); + return ASN1_ELEMENT_NOT_FOUND; + } + + result = asn1_der_decoding (&dst_node, data, size, NULL); + + free (data); + + return result; +} + +/** + * asn1_dup_node: + * @src: Source asn1 node. + * @src_name: Field name in source node. + * + * Create a deep copy of a asn1_node variable. This function + * will return an exact copy of the provided structure. + * + * Returns: Return %NULL on failure. + **/ +asn1_node +asn1_dup_node (asn1_node_const src, const char *src_name) +{ + return _asn1_copy_structure2(src, src_name); +} diff --git a/lib/minitasn1/structure.h b/lib/minitasn1/structure.h new file mode 100644 index 0000000..f06298f --- /dev/null +++ b/lib/minitasn1/structure.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2002-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +/*************************************************/ +/* File: structure.h */ +/* Description: list of exported object by */ +/* "structure.c" */ +/*************************************************/ + +#ifndef _STRUCTURE_H +#define _STRUCTURE_H + +#include "parser_aux.h" // list_type + +int _asn1_create_static_structure (asn1_node_const pointer, + char *output_file_name, char *vector_name); + +asn1_node _asn1_copy_structure3 (asn1_node_const source_node); + +asn1_node _asn1_add_single_node (unsigned int type); + +asn1_node _asn1_find_left (asn1_node_const node); + +int +_asn1_delete_structure (list_type *e_list, asn1_node *structure, unsigned int flags); + +#endif diff --git a/lib/minitasn1/version.c b/lib/minitasn1/version.c new file mode 100644 index 0000000..83e69d8 --- /dev/null +++ b/lib/minitasn1/version.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2000-2021 Free Software Foundation, Inc. + * + * This file is part of LIBTASN1. + * + * The LIBTASN1 library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> /* for strverscmp */ + +#include "libtasn1.h" + +/** + * asn1_check_version: + * @req_version: Required version number, or %NULL. + * + * Check that the version of the library is at minimum the + * requested one and return the version string; return %NULL if the + * condition is not satisfied. If a %NULL is passed to this function, + * no check is done, but the version string is simply returned. + * + * See %ASN1_VERSION for a suitable @req_version string. + * + * Returns: Version string of run-time library, or %NULL if the + * run-time library does not meet the required version number. + */ +const char * +asn1_check_version (const char *req_version) +{ + if (!req_version || strverscmp (req_version, ASN1_VERSION) <= 0) + return ASN1_VERSION; + + return NULL; +} |