diff options
Diffstat (limited to '')
64 files changed, 16092 insertions, 0 deletions
diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am new file mode 100644 index 0000000..81efdbc --- /dev/null +++ b/lib/ext/Makefile.am @@ -0,0 +1,63 @@ +## Process this file with automake to produce Makefile.in +# Copyright (C) 2002-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 3 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 this program. If not, see <https://www.gnu.org/licenses/> + +include $(top_srcdir)/lib/common.mk + +AM_CPPFLAGS = \ + -I$(srcdir)/../../gl \ + -I$(builddir)/../../gl \ + -I$(srcdir)/../includes \ + -I$(builddir)/../includes \ + -I$(builddir)/../../gl \ + -I$(srcdir)/.. + +if ENABLE_MINITASN1 +AM_CPPFLAGS += -I$(srcdir)/../minitasn1 +endif + +noinst_LTLIBRARIES = libgnutls_ext.la + +libgnutls_ext_la_SOURCES = max_record.c \ + server_name.c signature.c safe_renegotiation.c \ + max_record.h server_name.h srp.h \ + session_ticket.h signature.h safe_renegotiation.h \ + session_ticket.c srp.c heartbeat.c heartbeat.h \ + status_request.h status_request.c dumbfw.c dumbfw.h \ + ext_master_secret.c ext_master_secret.h etm.h etm.c \ + supported_versions.c supported_versions.h \ + post_handshake.c post_handshake.h key_share.c key_share.h \ + cookie.c cookie.h \ + psk_ke_modes.c psk_ke_modes.h pre_shared_key.c pre_shared_key.h \ + supported_groups.c supported_groups.h \ + ec_point_formats.c ec_point_formats.h \ + early_data.c early_data.h \ + record_size_limit.c record_size_limit.h \ + client_cert_type.c client_cert_type.h \ + server_cert_type.c server_cert_type.h \ + cert_types.h \ + compress_certificate.c compress_certificate.h + +if ENABLE_ALPN +libgnutls_ext_la_SOURCES += alpn.c alpn.h +endif + +if ENABLE_DTLS_SRTP +libgnutls_ext_la_SOURCES += srtp.c srtp.h +endif diff --git a/lib/ext/Makefile.in b/lib/ext/Makefile.in new file mode 100644 index 0000000..47c4abc --- /dev/null +++ b/lib/ext/Makefile.in @@ -0,0 +1,2517 @@ +# 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-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 3 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 this program. If not, see <https://www.gnu.org/licenses/> + +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@ +@ENABLE_MINITASN1_TRUE@am__append_1 = -I$(srcdir)/../minitasn1 +@ENABLE_ALPN_TRUE@am__append_2 = alpn.c alpn.h +@ENABLE_DTLS_SRTP_TRUE@am__append_3 = srtp.c srtp.h +subdir = lib/ext +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) +libgnutls_ext_la_LIBADD = +am__libgnutls_ext_la_SOURCES_DIST = max_record.c server_name.c \ + signature.c safe_renegotiation.c max_record.h server_name.h \ + srp.h session_ticket.h signature.h safe_renegotiation.h \ + session_ticket.c srp.c heartbeat.c heartbeat.h \ + status_request.h status_request.c dumbfw.c dumbfw.h \ + ext_master_secret.c ext_master_secret.h etm.h etm.c \ + supported_versions.c supported_versions.h post_handshake.c \ + post_handshake.h key_share.c key_share.h cookie.c cookie.h \ + psk_ke_modes.c psk_ke_modes.h pre_shared_key.c \ + pre_shared_key.h supported_groups.c supported_groups.h \ + ec_point_formats.c ec_point_formats.h early_data.c \ + early_data.h record_size_limit.c record_size_limit.h \ + client_cert_type.c client_cert_type.h server_cert_type.c \ + server_cert_type.h cert_types.h compress_certificate.c \ + compress_certificate.h alpn.c alpn.h srtp.c srtp.h +@ENABLE_ALPN_TRUE@am__objects_1 = alpn.lo +@ENABLE_DTLS_SRTP_TRUE@am__objects_2 = srtp.lo +am_libgnutls_ext_la_OBJECTS = max_record.lo server_name.lo \ + signature.lo safe_renegotiation.lo session_ticket.lo srp.lo \ + heartbeat.lo status_request.lo dumbfw.lo ext_master_secret.lo \ + etm.lo supported_versions.lo post_handshake.lo key_share.lo \ + cookie.lo psk_ke_modes.lo pre_shared_key.lo \ + supported_groups.lo ec_point_formats.lo early_data.lo \ + record_size_limit.lo client_cert_type.lo server_cert_type.lo \ + compress_certificate.lo $(am__objects_1) $(am__objects_2) +libgnutls_ext_la_OBJECTS = $(am_libgnutls_ext_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)/alpn.Plo \ + ./$(DEPDIR)/client_cert_type.Plo \ + ./$(DEPDIR)/compress_certificate.Plo ./$(DEPDIR)/cookie.Plo \ + ./$(DEPDIR)/dumbfw.Plo ./$(DEPDIR)/early_data.Plo \ + ./$(DEPDIR)/ec_point_formats.Plo ./$(DEPDIR)/etm.Plo \ + ./$(DEPDIR)/ext_master_secret.Plo ./$(DEPDIR)/heartbeat.Plo \ + ./$(DEPDIR)/key_share.Plo ./$(DEPDIR)/max_record.Plo \ + ./$(DEPDIR)/post_handshake.Plo ./$(DEPDIR)/pre_shared_key.Plo \ + ./$(DEPDIR)/psk_ke_modes.Plo ./$(DEPDIR)/record_size_limit.Plo \ + ./$(DEPDIR)/safe_renegotiation.Plo \ + ./$(DEPDIR)/server_cert_type.Plo ./$(DEPDIR)/server_name.Plo \ + ./$(DEPDIR)/session_ticket.Plo ./$(DEPDIR)/signature.Plo \ + ./$(DEPDIR)/srp.Plo ./$(DEPDIR)/srtp.Plo \ + ./$(DEPDIR)/status_request.Plo \ + ./$(DEPDIR)/supported_groups.Plo \ + ./$(DEPDIR)/supported_versions.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 = $(libgnutls_ext_la_SOURCES) +DIST_SOURCES = $(am__libgnutls_ext_la_SOURCES_DIST) +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 = -I$(srcdir)/../../gl -I$(builddir)/../../gl \ + -I$(srcdir)/../includes -I$(builddir)/../includes \ + -I$(builddir)/../../gl -I$(srcdir)/.. $(am__append_1) +noinst_LTLIBRARIES = libgnutls_ext.la +libgnutls_ext_la_SOURCES = max_record.c server_name.c signature.c \ + safe_renegotiation.c max_record.h server_name.h srp.h \ + session_ticket.h signature.h safe_renegotiation.h \ + session_ticket.c srp.c heartbeat.c heartbeat.h \ + status_request.h status_request.c dumbfw.c dumbfw.h \ + ext_master_secret.c ext_master_secret.h etm.h etm.c \ + supported_versions.c supported_versions.h post_handshake.c \ + post_handshake.h key_share.c key_share.h cookie.c cookie.h \ + psk_ke_modes.c psk_ke_modes.h pre_shared_key.c \ + pre_shared_key.h supported_groups.c supported_groups.h \ + ec_point_formats.c ec_point_formats.h early_data.c \ + early_data.h record_size_limit.c record_size_limit.h \ + client_cert_type.c client_cert_type.h server_cert_type.c \ + server_cert_type.h cert_types.h compress_certificate.c \ + compress_certificate.h $(am__append_2) $(am__append_3) +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/ext/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/ext/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}; \ + } + +libgnutls_ext.la: $(libgnutls_ext_la_OBJECTS) $(libgnutls_ext_la_DEPENDENCIES) $(EXTRA_libgnutls_ext_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libgnutls_ext_la_OBJECTS) $(libgnutls_ext_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alpn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_cert_type.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compress_certificate.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cookie.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dumbfw.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/early_data.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ec_point_formats.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/etm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ext_master_secret.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heartbeat.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key_share.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/max_record.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/post_handshake.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pre_shared_key.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_ke_modes.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/record_size_limit.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safe_renegotiation.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_cert_type.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_name.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session_ticket.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signature.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srtp.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/status_request.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/supported_groups.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/supported_versions.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)/alpn.Plo + -rm -f ./$(DEPDIR)/client_cert_type.Plo + -rm -f ./$(DEPDIR)/compress_certificate.Plo + -rm -f ./$(DEPDIR)/cookie.Plo + -rm -f ./$(DEPDIR)/dumbfw.Plo + -rm -f ./$(DEPDIR)/early_data.Plo + -rm -f ./$(DEPDIR)/ec_point_formats.Plo + -rm -f ./$(DEPDIR)/etm.Plo + -rm -f ./$(DEPDIR)/ext_master_secret.Plo + -rm -f ./$(DEPDIR)/heartbeat.Plo + -rm -f ./$(DEPDIR)/key_share.Plo + -rm -f ./$(DEPDIR)/max_record.Plo + -rm -f ./$(DEPDIR)/post_handshake.Plo + -rm -f ./$(DEPDIR)/pre_shared_key.Plo + -rm -f ./$(DEPDIR)/psk_ke_modes.Plo + -rm -f ./$(DEPDIR)/record_size_limit.Plo + -rm -f ./$(DEPDIR)/safe_renegotiation.Plo + -rm -f ./$(DEPDIR)/server_cert_type.Plo + -rm -f ./$(DEPDIR)/server_name.Plo + -rm -f ./$(DEPDIR)/session_ticket.Plo + -rm -f ./$(DEPDIR)/signature.Plo + -rm -f ./$(DEPDIR)/srp.Plo + -rm -f ./$(DEPDIR)/srtp.Plo + -rm -f ./$(DEPDIR)/status_request.Plo + -rm -f ./$(DEPDIR)/supported_groups.Plo + -rm -f ./$(DEPDIR)/supported_versions.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)/alpn.Plo + -rm -f ./$(DEPDIR)/client_cert_type.Plo + -rm -f ./$(DEPDIR)/compress_certificate.Plo + -rm -f ./$(DEPDIR)/cookie.Plo + -rm -f ./$(DEPDIR)/dumbfw.Plo + -rm -f ./$(DEPDIR)/early_data.Plo + -rm -f ./$(DEPDIR)/ec_point_formats.Plo + -rm -f ./$(DEPDIR)/etm.Plo + -rm -f ./$(DEPDIR)/ext_master_secret.Plo + -rm -f ./$(DEPDIR)/heartbeat.Plo + -rm -f ./$(DEPDIR)/key_share.Plo + -rm -f ./$(DEPDIR)/max_record.Plo + -rm -f ./$(DEPDIR)/post_handshake.Plo + -rm -f ./$(DEPDIR)/pre_shared_key.Plo + -rm -f ./$(DEPDIR)/psk_ke_modes.Plo + -rm -f ./$(DEPDIR)/record_size_limit.Plo + -rm -f ./$(DEPDIR)/safe_renegotiation.Plo + -rm -f ./$(DEPDIR)/server_cert_type.Plo + -rm -f ./$(DEPDIR)/server_name.Plo + -rm -f ./$(DEPDIR)/session_ticket.Plo + -rm -f ./$(DEPDIR)/signature.Plo + -rm -f ./$(DEPDIR)/srp.Plo + -rm -f ./$(DEPDIR)/srtp.Plo + -rm -f ./$(DEPDIR)/status_request.Plo + -rm -f ./$(DEPDIR)/supported_groups.Plo + -rm -f ./$(DEPDIR)/supported_versions.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/ext/alpn.c b/lib/ext/alpn.c new file mode 100644 index 0000000..7cc7997 --- /dev/null +++ b/lib/ext/alpn.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * Copyright (C) 2017 Red Hat, Inc. + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "num.h" +#include <ext/alpn.h> + +static int _gnutls_alpn_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_alpn_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +static void _gnutls_alpn_deinit_data(gnutls_ext_priv_data_t priv); + + +const hello_ext_entry_st ext_mod_alpn = { + .name = "ALPN", + .tls_id = 16, + .gid = GNUTLS_EXTENSION_ALPN, + /* this extension must be parsed even on resumption */ + .client_parse_point = GNUTLS_EXT_MANDATORY, + .server_parse_point = GNUTLS_EXT_MANDATORY, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | + GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_EE | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_alpn_recv_params, + .send_func = _gnutls_alpn_send_params, + .deinit_func = _gnutls_alpn_deinit_data, + .cannot_be_overriden = 1 +}; + +static int +_gnutls_alpn_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + unsigned int i; + int ret; + const uint8_t *p = data; + unsigned len1, len; + alpn_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int selected_protocol_index; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_ALPN, + &epriv); + if (ret < 0) + return 0; + + priv = epriv; + + DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + len = _gnutls_read_uint16(p); + p += 2; + + if (len == 0 || len > (size_t)data_size) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (session->security_parameters.entity == GNUTLS_SERVER) { + selected_protocol_index = MAX_ALPN_PROTOCOLS+1; + + while (data_size > 0) { + DECR_LENGTH_RET(data_size, 1, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + len1 = *p; + p += 1; + DECR_LENGTH_RET(data_size, len1, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (len1 == 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + for (i = 0; i < priv->size; i++) { + if (priv->protocol_size[i] == len1 + && memcmp(p, priv->protocols[i], + len1) == 0) { + + if (priv->flags & GNUTLS_ALPN_SERVER_PRECEDENCE) { + if (selected_protocol_index > (int)i) { + selected_protocol_index = i; + priv->selected_protocol = + priv->protocols[i]; + priv->selected_protocol_size = + priv->protocol_size[i]; + break; + } + } else { + priv->selected_protocol = + priv->protocols[i]; + priv->selected_protocol_size = + priv->protocol_size[i]; + return 0; + } + } + } + p += len1; + } + } else { + DECR_LENGTH_RET(data_size, 1, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + len1 = *p; + p += 1; + DECR_LENGTH_RET(data_size, len1, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + for (i = 0; i < priv->size; i++) { + if (priv->protocol_size[i] == len1 + && memcmp(p, priv->protocols[i], len1) == 0) { + priv->selected_protocol = + priv->protocols[i]; + priv->selected_protocol_size = + priv->protocol_size[i]; + break; + } + } + /*p += len1;*/ + } + + if (priv->selected_protocol == NULL + && (priv->flags & GNUTLS_ALPN_MAND)) + return gnutls_assert_val(GNUTLS_E_NO_APPLICATION_PROTOCOL); + + return 0; +} + +static int +_gnutls_alpn_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + unsigned i; + int total_size = 0, ret; + alpn_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_ALPN, + &epriv); + if (ret < 0) + return 0; + + priv = epriv; + + if (priv->size == 0) + return 0; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (priv->selected_protocol_size == 0) + return 0; + + ret = + _gnutls_buffer_append_prefix(extdata, 16, + priv-> + selected_protocol_size + + 1); + if (ret < 0) + return gnutls_assert_val(ret); + + total_size += 2; + + ret = + _gnutls_buffer_append_data_prefix(extdata, 8, + priv-> + selected_protocol, + priv-> + selected_protocol_size); + if (ret < 0) + return gnutls_assert_val(ret); + + total_size += 1 + priv->selected_protocol_size; + } else { + int t = 0; + for (i = 0; i < priv->size; i++) + t += priv->protocol_size[i] + 1; + + ret = _gnutls_buffer_append_prefix(extdata, 16, t); + if (ret < 0) + return gnutls_assert_val(ret); + + total_size += 2; + + for (i = 0; i < priv->size; i++) { + ret = + _gnutls_buffer_append_data_prefix(extdata, 8, + priv-> + protocols[i], + priv-> + protocol_size + [i]); + if (ret < 0) + return gnutls_assert_val(ret); + + total_size += 1 + priv->protocol_size[i]; + } + } + + return total_size; +} + +/** + * gnutls_alpn_get_selected_protocol: + * @session: is a #gnutls_session_t type. + * @protocol: will hold the protocol name + * + * This function allows you to get the negotiated protocol name. The + * returned protocol should be treated as opaque, constant value and + * only valid during the session life. + * + * The selected protocol is the first supported by the list sent + * by the client. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.2.0 + **/ +int +gnutls_alpn_get_selected_protocol(gnutls_session_t session, + gnutls_datum_t * protocol) +{ + alpn_ext_st *priv; + int ret; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_ALPN, + &epriv); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + priv = epriv; + + if (priv->selected_protocol_size == 0) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + protocol->data = priv->selected_protocol; + protocol->size = priv->selected_protocol_size; + + return 0; +} + +/** + * gnutls_alpn_set_protocols: + * @session: is a #gnutls_session_t type. + * @protocols: is the protocol names to add. + * @protocols_size: the number of protocols to add. + * @flags: zero or a sequence of %gnutls_alpn_flags_t + * + * This function is to be used by both clients and servers, to declare + * the supported ALPN protocols, which are used during negotiation with peer. + * + * See %gnutls_alpn_flags_t description for the documentation of available + * flags. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.2.0 + **/ +int +gnutls_alpn_set_protocols(gnutls_session_t session, + const gnutls_datum_t * protocols, + unsigned protocols_size, unsigned int flags) +{ + int ret; + alpn_ext_st *priv; + gnutls_ext_priv_data_t epriv; + unsigned i; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_ALPN, + &epriv); + if (ret < 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_ALPN, epriv); + } else + priv = epriv; + + if (protocols_size > MAX_ALPN_PROTOCOLS) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + for (i = 0; i < protocols_size; i++) { + if (protocols[i].size >= MAX_ALPN_PROTOCOL_NAME) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + memcpy(priv->protocols[i], protocols[i].data, + protocols[i].size); + priv->protocol_size[i] = protocols[i].size; + priv->size++; + } + priv->flags = flags; + + return 0; +} + + +static void _gnutls_alpn_deinit_data(gnutls_ext_priv_data_t priv) +{ + gnutls_free(priv); +} diff --git a/lib/ext/alpn.h b/lib/ext/alpn.h new file mode 100644 index 0000000..0b32a32 --- /dev/null +++ b/lib/ext/alpn.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_ALPN_H +#define GNUTLS_LIB_EXT_ALPN_H + +#include <hello_ext.h> + +#define MAX_ALPN_PROTOCOLS 8 +#define MAX_ALPN_PROTOCOL_NAME 32 + +typedef struct { + uint8_t protocols[MAX_ALPN_PROTOCOLS][MAX_ALPN_PROTOCOL_NAME]; + unsigned protocol_size[MAX_ALPN_PROTOCOLS]; + unsigned size; + uint8_t *selected_protocol; + unsigned selected_protocol_size; + unsigned flags; +} alpn_ext_st; + +extern const hello_ext_entry_st ext_mod_alpn; + +#endif /* GNUTLS_LIB_EXT_ALPN_H */ diff --git a/lib/ext/cert_types.h b/lib/ext/cert_types.h new file mode 100644 index 0000000..98dfdef --- /dev/null +++ b/lib/ext/cert_types.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 ARPA2 project + * + * Author: Tom Vrancken (dev@tomvrancken.nl) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + * This file provides common functionality for certificate type + * handling during TLS hello extensions. + * + */ + +#ifndef GNUTLS_LIB_EXT_CERT_TYPES_H +#define GNUTLS_LIB_EXT_CERT_TYPES_H + +/* Maps IANA TLS Certificate Types identifiers to internal + * certificate type representation. + */ +static inline gnutls_certificate_type_t IANA2cert_type(int num) +{ + switch (num) { + case 0: + return GNUTLS_CRT_X509; + case 2: + return GNUTLS_CRT_RAWPK; + default: + return GNUTLS_CRT_UNKNOWN; + } +} + +/* Maps internal certificate type representation to + * IANA TLS Certificate Types identifiers. + */ +static inline int cert_type2IANA(gnutls_certificate_type_t cert_type) +{ + switch (cert_type) { + case GNUTLS_CRT_X509: + return 0; + case GNUTLS_CRT_RAWPK: + return 2; + default: + return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } +} + +/* Checks whether the given cert type is enabled in the application + */ +static inline bool is_cert_type_enabled(gnutls_session_t session, gnutls_certificate_type_t cert_type) +{ + switch(cert_type) { + case GNUTLS_CRT_X509: + // Default cert type, always enabled + return true; + case GNUTLS_CRT_RAWPK: + return session->internals.flags & GNUTLS_ENABLE_RAWPK; + default: + // When not explicitly supported here disable it + return false; + } +} + +/* Checks whether alternative cert types (i.e. other than X.509) + * are enabled in the application + */ +static inline bool are_alternative_cert_types_allowed(gnutls_session_t session) +{ + // OR-ed list of defined cert type init flags + #define CERT_TYPES_FLAGS GNUTLS_ENABLE_RAWPK + + return session->internals.flags & CERT_TYPES_FLAGS; + + #undef CERT_TYPES_FLAGS +} + +#endif /* GNUTLS_LIB_EXT_CERT_TYPES_H */ diff --git a/lib/ext/client_cert_type.c b/lib/ext/client_cert_type.c new file mode 100644 index 0000000..261b56c --- /dev/null +++ b/lib/ext/client_cert_type.c @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2016 - 2018 ARPA2 project + * + * Author: Tom Vrancken (dev@tomvrancken.nl) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + * This file is part of the client_certificate_type extension as + * defined in RFC7250 (https://tools.ietf.org/html/rfc7250). + * + * The client_certificate_type extension in the client hello indicates + * the certificate types the client is able to provide to the server, + * when requested using a certificate_request message. + */ + +#include "gnutls_int.h" +#include <gnutls/gnutls.h> +#include "ext/cert_types.h" +#include "ext/client_cert_type.h" +#include "hello_ext.h" +#include "hello_ext_lib.h" +#include "errors.h" +#include "state.h" +#include "datum.h" + + +static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + const uint8_t* data, + size_t data_size); +static int _gnutls_client_cert_type_send_params(gnutls_session_t session, + gnutls_buffer_st* data); + + +const hello_ext_entry_st ext_mod_client_cert_type = { + .name = "Client Certificate Type", + .tls_id = 19, + .gid = GNUTLS_EXTENSION_CLIENT_CERT_TYPE, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | + GNUTLS_EXT_FLAG_DTLS | + GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | + GNUTLS_EXT_FLAG_EE, + .recv_func = _gnutls_client_cert_type_recv_params, + .send_func = _gnutls_client_cert_type_send_params, + .pack_func = _gnutls_hello_ext_default_pack, + .unpack_func = _gnutls_hello_ext_default_unpack, + .deinit_func = _gnutls_hello_ext_default_deinit, + .cannot_be_overriden = 1 +}; + + +static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + const uint8_t* data, + size_t data_size) +{ + int ret; + gnutls_certificate_type_t cert_type; + size_t i; + bool found = false; + const uint8_t* pdata = data; + + /* Only activate this extension if we have cert credentials set + * and alternative cert types are allowed */ + if (!are_alternative_cert_types_allowed(session) || + (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)) + return 0; + + if (!IS_SERVER(session)) { // client mode + gnutls_datum_t sent_cert_types; // Holds the previously sent cert types + + /* Compare packet length with expected packet length. For the + * client this is a single byte. */ + if (data_size != 1) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + + /* The server picked one of the offered cert types if he supports + * at least one of them and decided to do a client certificate + * request. If both parties play by the rules then we may only + * receive a cert type that we offered, i.e. one that we support. + * Because the world isn't as beautiful as it may seem, we're going + * to check it nevertheless. */ + cert_type = IANA2cert_type(pdata[0]); + + _gnutls_handshake_log("EXT[%p]: Received a %s client certificate type confirmation from the server.\n", + session, gnutls_certificate_type_get_name(cert_type)); + + // Check validity of cert type + if (cert_type == GNUTLS_CRT_UNKNOWN) { + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE); + } + + /* Get the cert types that we sent to the server (they were stored + * in IANA representation. + */ + ret = _gnutls_hello_ext_get_datum(session, + GNUTLS_EXTENSION_CLIENT_CERT_TYPE, + &sent_cert_types); + if (ret < 0) { + /* This should not happen and indicate a memory corruption! + * Assertion are always on in production code so execution + * will halt here. */ + assert(false); + } + + // Check whether what we got back is actually offered by us + for (i = 0; i < sent_cert_types.size; i++) { + if (IANA2cert_type(sent_cert_types.data[i]) == cert_type) + found = true; + } + + if (found) { + // Everything OK, now set the client certificate type + _gnutls_session_client_cert_type_set(session, cert_type); + ret = GNUTLS_E_SUCCESS; + } else { + // No valid cert type found + ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + return ret; + + } else { // server mode + gnutls_datum_t cert_types; // Holds the received cert types + + // Compare packet length with expected packet length. + DECR_LEN(data_size, 1); + if (data[0] != data_size) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + pdata += 1; + + // Assign the contents of our data buffer to a gnutls_datum_t + cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning + cert_types.size = data_size; + + // Store the client certificate types in our session + _gnutls_hello_ext_set_datum(session, + GNUTLS_EXTENSION_CLIENT_CERT_TYPE, + &cert_types); + + /* We receive a list of supported certificate types that the client + * is able to provide when requested via a client certificate + * request. This list is sorted by order of preference. We now check + * in this order of preference whether we support any of these + * certificate types. + */ + for (i = 0; i < cert_types.size; i++) { + // Convert to internal representation + cert_type = IANA2cert_type(cert_types.data[i]); + + // If we have an invalid cert id then continue to the next + if (cert_type == GNUTLS_CRT_UNKNOWN) + continue; + + _gnutls_handshake_log("EXT[%p]: Checking compatibility of a %s client certificate type that was received from the client.\n", + session, gnutls_certificate_type_get_name(cert_type)); + + // Check for support of this cert type + if (_gnutls_session_is_cert_type_supported(session, cert_type, false, GNUTLS_CTYPE_CLIENT) == 0) { + found = true; + break; + } + } + + // We found a matching ctype, we pick this one + if (found) { + _gnutls_session_client_cert_type_set(session, cert_type); + ret = GNUTLS_E_SUCCESS; + } else { + /* If no supported certificate type can be found we terminate + * with a fatal alert of type "unsupported_certificate" + * (according to specification rfc7250). + */ + _gnutls_handshake_log + ("EXT[%p]: No supported client certificate type was found. " + "Aborting connection.\n", session); + ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + return ret; + } +} + +static int _gnutls_client_cert_type_send_params(gnutls_session_t session, + gnutls_buffer_st* data) +{ + int ret; + uint8_t cert_type_IANA; // Holds an IANA cert type ID + gnutls_certificate_type_t cert_type; + + /* Only activate this extension if we have cert credentials set + * and alternative cert types are allowed */ + if (!are_alternative_cert_types_allowed(session) || + (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)) + return 0; + + if (!IS_SERVER(session)) { // Client mode + uint8_t cert_types[GNUTLS_CRT_MAX]; // The list with supported (IANA) cert types. Inv: 0 <= cert type Id < 256 + size_t i, num_cert_types = 0; + priority_st* cert_priorities; + gnutls_datum_t tmp_cert_types; // For type conversion + + // For brevity + cert_priorities = + &session->internals.priorities->client_ctype; + + /* Retrieve client certificate type priorities if any. If no + * priorities are set then the default client certificate type + * initialization values apply. This default is currently set to + * x.509 in which case we don't enable this extension. + */ + if (cert_priorities->num_priorities > 0) { // Priorities are explicitly set + /* If the certificate priority is explicitly set to only + * X.509 (default) then, according to spec we don't send + * this extension. We check this here to avoid further work in + * this routine. We also check it below after pruning supported + * types. + */ + if (cert_priorities->num_priorities == 1 && + cert_priorities->priorities[0] == DEFAULT_CERT_TYPE) { + _gnutls_handshake_log + ("EXT[%p]: Client certificate type was set to default cert type (%s). " + "We therefore do not send this extension.\n", + session, + gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE)); + + // Explicitly set but default ctype, so don't send anything + return 0; + } + + /* We are only allowed to send certificate types that we support, + * i.e. have credentials for. Therefore we check this here and + * prune our original list. + */ + for (i = 0; i < cert_priorities->num_priorities; i++) { + cert_type = cert_priorities->priorities[i]; + + if (_gnutls_session_is_cert_type_supported(session, cert_type, + true, GNUTLS_CTYPE_CLIENT) == 0) { + /* Check whether we are allowed to store another cert type + * in our buffer. In other words, prevent a possible buffer + * overflow. This situation can occur when a user sets + * duplicate cert types in the priority strings. */ + if (num_cert_types >= GNUTLS_CRT_MAX) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + + // Convert to IANA representation + ret = cert_type2IANA(cert_type); + + if (ret < 0) + return gnutls_assert_val(ret); + + cert_type_IANA = ret; // For readability + + // Add this cert type to our list with supported types + cert_types[num_cert_types] = cert_type_IANA; + num_cert_types++; + + _gnutls_handshake_log + ("EXT[%p]: Client certificate type %s (%d) was queued.\n", + session, + gnutls_certificate_type_get_name(cert_type), + cert_type_IANA); + } + } + + /* Check whether there are any supported certificate types left + * after the previous pruning step. If not, we do not send this + * extension. Also, if the only supported type is the default type + * we do not send this extension (according to RFC7250). + */ + if (num_cert_types == 0) { + _gnutls_handshake_log + ("EXT[%p]: Client certificate types were set but none of them is supported. " + "You might want to check your credentials or your priorities. " + "We do not send this extension.\n", + session); + + return 0; + } else if (num_cert_types == 1 && + IANA2cert_type(cert_types[0]) == DEFAULT_CERT_TYPE) { + _gnutls_handshake_log + ("EXT[%p]: The only supported client certificate type is (%s) which is the default. " + "We therefore do not send this extension.\n", + session, + gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE)); + + return 0; + } + + /* We have data to send and store a copy internally. We convert + * our list with supported cert types to a datum_t in order to + * be able to make the ..._set_datum call. + */ + tmp_cert_types.data = cert_types; + tmp_cert_types.size = num_cert_types; + + _gnutls_hello_ext_set_datum(session, + GNUTLS_EXTENSION_CLIENT_CERT_TYPE, + &tmp_cert_types); + + /* Serialize the certificate types into a sequence of octets + * uint8: length of sequence of cert types (1 octet) + * uint8: cert types (0 <= #octets <= 255) + */ + ret = _gnutls_buffer_append_data_prefix(data, 8, + cert_types, + num_cert_types); + + // Check for errors + if (ret < 0) { + return gnutls_assert_val(ret); + } else { + // Number of bytes we are sending + return num_cert_types + 1; + } + } + } else { // Server mode + const version_entry_st* vers = get_version(session); + /* TLS 1.2: + * Check whether we are going to send a certificate request, + * otherwise omit the response. This is conform spec. + * (RFC7250, 4.2 case 3.). + * + * TLS 1.3: + * TLS 1.3 supports post-handshake authentication for the client. + * It means that a server can ask for a client certificate anytime + * after the handshake. In order for this to work we must always + * complete the certificate type negotiation and therefore respond + * with a cert type message. + */ + if (session->internals.send_cert_req != 0 || + vers->tls13_sem) { + /* Retrieve negotiated client certificate type and send it to + * the client. + * The scenario where we want to send a certificate request but + * do not have a matching certificate does not occur because we + * already terminate the connection at reception of this extension + * when we cannot find a matching client certificate. This is conform + * spec (RFC7250, 4.2 case 2.). + */ + cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT); + ret = cert_type2IANA(cert_type); + + if (ret < 0) + return gnutls_assert_val(ret); + + cert_type_IANA = ret; // For readability + + _gnutls_handshake_log("EXT[%p]: Confirming to use a %s client certificate type.\n", + session, gnutls_certificate_type_get_name(cert_type)); + + ret = gnutls_buffer_append_data(data, &cert_type_IANA, 1); + + if (ret < 0) + return gnutls_assert_val(ret); + + return 1; // sent one byte + } + } + + // In all other cases don't enable this extension + return 0; +} + + +/** Extension interface **/ + +/* The interface is defined in state.c: + * Public: + * - gnutls_certificate_type_get2 + * + * Private: + * - _gnutls_session_client_cert_type_set + */ diff --git a/lib/ext/client_cert_type.h b/lib/ext/client_cert_type.h new file mode 100644 index 0000000..7e89ca8 --- /dev/null +++ b/lib/ext/client_cert_type.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 - 2018 ARPA2 project + * + * Author: Tom Vrancken (dev@tomvrancken.nl) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + * This file is part of the client_certificate_type extension as + * defined in RFC7250 (https://tools.ietf.org/html/rfc7250). + * + * The client_certificate_type extension in the client hello indicates + * the certificate types the client is able to provide to the server, + * when requested using a certificate_request message. + */ + +#ifndef GNUTLS_LIB_EXT_CLIENT_CERT_TYPE_H +#define GNUTLS_LIB_EXT_CLIENT_CERT_TYPE_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_client_cert_type; + +#endif /* GNUTLS_LIB_EXT_CLIENT_CERT_TYPE_H */ diff --git a/lib/ext/compress_certificate.c b/lib/ext/compress_certificate.c new file mode 100644 index 0000000..8f8d75c --- /dev/null +++ b/lib/ext/compress_certificate.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2022 Red Hat, Inc. + * + * Author: Zoltan Fridrich + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "errors.h" +#include "gnutls_int.h" +#include "hello_ext_lib.h" +#include "num.h" +#include <ext/compress_certificate.h> + +/* Check whether certificate compression method is valid, ie. supported by gnutls */ +static inline int +is_valid_method(gnutls_compression_method_t method) +{ + switch (method) { +#ifdef HAVE_LIBZ + case GNUTLS_COMP_ZLIB: + return 1; +#endif +#ifdef HAVE_LIBBROTLI + case GNUTLS_COMP_BROTLI: + return 1; +#endif +#ifdef HAVE_LIBZSTD + case GNUTLS_COMP_ZSTD: + return 1; +#endif + default: + return 0; + } +} + +/* Converts compression algorithm number established in RFC8879 to internal compression method type */ +gnutls_compression_method_t +_gnutls_compress_certificate_num2method(uint16_t num) +{ + switch (num) { + case 1: + return GNUTLS_COMP_ZLIB; + case 2: + return GNUTLS_COMP_BROTLI; + case 3: + return GNUTLS_COMP_ZSTD; + default: + return GNUTLS_COMP_UNKNOWN; + } +} + +/* Converts compression method type to compression algorithm number established in RFC8879 */ +int +_gnutls_compress_certificate_method2num(gnutls_compression_method_t method) +{ + switch (method) { + case GNUTLS_COMP_ZLIB: + return 1; + case GNUTLS_COMP_BROTLI: + return 2; + case GNUTLS_COMP_ZSTD: + return 3; + default: + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } +} + +/** + * gnutls_compress_certificate_get_selected_method: + * @session: is a #gnutls_session_t type. + * + * This function returns the certificate compression method that has been + * selected to compress the certificate before sending it to the peer. + * The selection is done based on the local list of supported compression + * methods and the peer's requested compression methods. + * + * Returns: selected certificate compression method. + * + * Since 3.7.4 + **/ +gnutls_compression_method_t +gnutls_compress_certificate_get_selected_method(gnutls_session_t session) +{ + return session->internals.compress_certificate_method; +} + +/** + * gnutls_compress_certificate_set_methods: + * @session: is a #gnutls_session_t type. + * @methods: is a list of supported compression methods. + * @methods_len: number of compression methods in @methods + * + * This function sets the supported compression methods for certificate compression + * for the given session. The list of supported compression methods will be used + * for a) requesting the compression of peer's certificate and b) selecting the + * method to compress the local certificate before sending it to the peer. + * The order of compression methods inside the list does matter as the method + * that appears earlier in the list will be preffered before the later ones. + * Note that even if you set the list of supported compression methods, the + * compression might not be used if the peer does not support any of your chosen + * compression methods. + * + * The list of supported compression methods must meet the following criteria: + * Argument @methods must be an array of valid compression methods of type + * #gnutls_compression_method_t. Argument @methods_len must contain the number of + * compression methods stored in the @methods array and must be within range <1, 127>. + * The length constraints are defined by %MIN_COMPRESS_CERTIFICATE_METHODS + * and %MAX_COMPRESS_CERTIFICATE_METHODS macros located in the header file + * compress_certificate.h. + * + * If either @methods or @methods_len is equal to 0, current list of supported + * compression methods will be unset. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. + * + * Since 3.7.4 + **/ +int +gnutls_compress_certificate_set_methods(gnutls_session_t session, + const gnutls_compression_method_t * methods, + size_t methods_len) +{ + unsigned i; + compress_certificate_ext_st *priv; + + if (methods == NULL || methods_len == 0) { + _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_COMPRESS_CERTIFICATE); + return 0; + } + + if (methods_len > MAX_COMPRESS_CERTIFICATE_METHODS) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + for (i = 0; i < methods_len; ++i) + if (!is_valid_method(methods[i])) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + priv = gnutls_malloc(sizeof(*priv)); + if (priv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + priv->methods_len = methods_len; + memcpy(priv->methods, methods, methods_len * sizeof(*methods)); + _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_COMPRESS_CERTIFICATE, priv); + + return 0; +} + +int +_gnutls_compress_certificate_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size) +{ + int ret; + unsigned i, j; + uint16_t num; + uint8_t bytes_len; + size_t methods_len; + gnutls_compression_method_t methods[MAX_COMPRESS_CERTIFICATE_METHODS]; + gnutls_compression_method_t method = GNUTLS_COMP_UNKNOWN; + compress_certificate_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_COMPRESS_CERTIFICATE, &epriv); + if (ret < 0) + return 0; + priv = epriv; + + DECR_LEN(data_size, 1); + bytes_len = *data; + + if (bytes_len < 2 || bytes_len > 254 || bytes_len % 2 == 1) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + DECR_LEN(data_size, bytes_len); + methods_len = bytes_len / 2; + + for (i = 0; i < methods_len; ++i) { + num = _gnutls_read_uint16(data + i + i + 1); + methods[i] = _gnutls_compress_certificate_num2method(num); + if (methods[i] == GNUTLS_COMP_UNKNOWN) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + for (i = 0; i < methods_len; ++i) + for (j = 0; j < priv->methods_len; ++j) + if (methods[i] == priv->methods[j]) { + method = methods[i]; + goto endloop; + } +endloop: + session->internals.compress_certificate_method = method; + + return 0; +} + +int +_gnutls_compress_certificate_send_params(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret, num; + unsigned i; + uint8_t bytes_len; + uint8_t bytes[2 * MAX_COMPRESS_CERTIFICATE_METHODS]; + compress_certificate_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_COMPRESS_CERTIFICATE, &epriv); + if (ret < 0) + return 0; + priv = epriv; + + bytes_len = 2 * priv->methods_len; + for (i = 0; i < priv->methods_len; ++i) { + num = _gnutls_compress_certificate_method2num(priv->methods[i]); + _gnutls_write_uint16(num, bytes + i + i); + } + + ret = _gnutls_buffer_append_data_prefix(data, 8, bytes, bytes_len); + if (ret < 0) + return gnutls_assert_val(ret); + + return bytes_len + 1; +} + +const hello_ext_entry_st ext_mod_compress_certificate = { + .name = "Compress Certificate", + .tls_id = 27, + .gid = GNUTLS_EXTENSION_COMPRESS_CERTIFICATE, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | + GNUTLS_EXT_FLAG_CLIENT_HELLO, + .recv_func = _gnutls_compress_certificate_recv_params, + .send_func = _gnutls_compress_certificate_send_params, + .deinit_func = _gnutls_hello_ext_default_deinit +}; diff --git a/lib/ext/compress_certificate.h b/lib/ext/compress_certificate.h new file mode 100644 index 0000000..b708374 --- /dev/null +++ b/lib/ext/compress_certificate.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 Red Hat, Inc. + * + * Author: Zoltan Fridrich + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_COMPRESS_CERTIFICATE_H +#define GNUTLS_LIB_EXT_COMPRESS_CERTIFICATE_H + +#include <hello_ext.h> + +#define MIN_COMPRESS_CERTIFICATE_METHODS 1 +#define MAX_COMPRESS_CERTIFICATE_METHODS 127 + +typedef struct { + gnutls_compression_method_t methods[MAX_COMPRESS_CERTIFICATE_METHODS]; + size_t methods_len; +} compress_certificate_ext_st; + +extern const hello_ext_entry_st ext_mod_compress_certificate; + +gnutls_compression_method_t _gnutls_compress_certificate_num2method(uint16_t num); +int _gnutls_compress_certificate_method2num(gnutls_compression_method_t method); + +int +_gnutls_compress_certificate_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +int +_gnutls_compress_certificate_send_params(gnutls_session_t session, + gnutls_buffer_st * data); + +#endif /* GNUTLS_LIB_EXT_COMPRESS_CERTIFICATE_H */ diff --git a/lib/ext/cookie.c b/lib/ext/cookie.c new file mode 100644 index 0000000..b4608f3 --- /dev/null +++ b/lib/ext/cookie.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Max Record Size TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include "hello_ext_lib.h" +#include <ext/cookie.h> + +static int cookie_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int cookie_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_cookie = { + .name = "Cookie", + .tls_id = 44, + .gid = GNUTLS_EXTENSION_COOKIE, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_HRR | GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST, + .client_parse_point = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */ + .server_parse_point = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */ + .recv_func = cookie_recv_params, + .send_func = cookie_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = _gnutls_hello_ext_default_deinit, + .cannot_be_overriden = 0 +}; + +/* Only client sends this extension. */ +static int +cookie_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + size_t csize; + int ret; + gnutls_datum_t tmp; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + /* we don't support it */ + return 0; + } else { /* client */ + if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) { + DECR_LEN(data_size, 2); + + csize = _gnutls_read_uint16(data); + data += 2; + + DECR_LEN(data_size, csize); + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + tmp.data = (void*)data; + tmp.size = csize; + + ret = _gnutls_hello_ext_set_datum(session, GNUTLS_EXTENSION_COOKIE, &tmp); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; + } + + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +cookie_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + gnutls_datum_t tmp; + int ret; + + /* this function sends the client extension data (dnsname) */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + ret = _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_COOKIE, &tmp); + if (ret < 0) + return 0; + + ret = _gnutls_buffer_append_data_prefix(extdata, 16, tmp.data, tmp.size); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; + } + + return 0; +} diff --git a/lib/ext/cookie.h b/lib/ext/cookie.h new file mode 100644 index 0000000..13ea7c7 --- /dev/null +++ b/lib/ext/cookie.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_COOKIE_H +#define GNUTLS_LIB_EXT_COOKIE_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_cookie; + +#endif /* GNUTLS_LIB_EXT_COOKIE_H */ diff --git a/lib/ext/dumbfw.c b/lib/ext/dumbfw.c new file mode 100644 index 0000000..dfd2ee0 --- /dev/null +++ b/lib/ext/dumbfw.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2013-2018 Nikos Mavrogiannopoulos + * Copyright (C) 2018 Red Hat, Inc. + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "num.h" +#include <ext/dumbfw.h> + +/* This extension adds additional padding data in the TLS client hello. + * There is an issue with some firewalls [0] rejecting TLS client hello + * data that are between 256 and 511 bytes, and this extension will + * make sure that client hello isn't in this range. + * + * [0]. https://www.ietf.org/mail-archive/web/tls/current/msg10423.html + */ + +static int _gnutls_dumbfw_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_dumbfw = { + .name = "ClientHello Padding", + .tls_id = 21, + .gid = GNUTLS_EXTENSION_DUMBFW, + .client_parse_point = GNUTLS_EXT_APPLICATION, + .server_parse_point = GNUTLS_EXT_APPLICATION, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO, + .recv_func = NULL, + .send_func = _gnutls_dumbfw_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 0 +}; + +static int +_gnutls_dumbfw_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + int total_size = 0, ret; + uint8_t pad[257]; + unsigned pad_size; + ssize_t len = extdata->length - sizeof(mbuffer_st); + + if (session->security_parameters.entity == GNUTLS_SERVER || + session->internals.dumbfw == 0 || + IS_DTLS(session) != 0 || + (len < 256 || len >= 512)) { + return 0; + } else { + /* 256 <= extdata->length < 512 */ + pad_size = 512 - len; + memset(pad, 0, pad_size); + + ret = + gnutls_buffer_append_data(extdata, pad, + pad_size); + if (ret < 0) + return gnutls_assert_val(ret); + + total_size += pad_size; + } + + return total_size; +} + diff --git a/lib/ext/dumbfw.h b/lib/ext/dumbfw.h new file mode 100644 index 0000000..87bb072 --- /dev/null +++ b/lib/ext/dumbfw.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_DUMBFW_H +#define GNUTLS_LIB_EXT_DUMBFW_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_dumbfw; + +#endif /* GNUTLS_LIB_EXT_DUMBFW_H */ diff --git a/lib/ext/early_data.c b/lib/ext/early_data.c new file mode 100644 index 0000000..28c3182 --- /dev/null +++ b/lib/ext/early_data.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2018 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Early Data TLS 1.3 extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include "hello_ext_lib.h" +#include <ext/early_data.h> + +static int early_data_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int early_data_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_early_data = { + .name = "Early Data", + .tls_id = 42, + .gid = GNUTLS_EXTENSION_EARLY_DATA, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_EE, + .client_parse_point = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */ + .server_parse_point = GNUTLS_EXT_MANDATORY, /* force parsing prior to EXT_TLS extensions */ + .recv_func = early_data_recv_params, + .send_func = early_data_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = _gnutls_hello_ext_default_deinit, + .cannot_be_overriden = 0 +}; + +static int +early_data_recv_params(gnutls_session_t session, + const uint8_t * data, size_t _data_size) +{ + const version_entry_st *vers = get_version(session); + + if (!vers || !vers->tls13_sem) + return gnutls_assert_val(0); + + if (session->security_parameters.entity == GNUTLS_SERVER) { + /* Whether to accept early data is decided during processing the + * pre_shared_key extension in the later phase. + */ + session->internals.hsk_flags |= HSK_EARLY_DATA_IN_FLIGHT; + } else { + if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_EE) + session->internals.hsk_flags |= HSK_EARLY_DATA_ACCEPTED; + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +early_data_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) + return GNUTLS_E_INT_RET_0; + } else { + /* early data is enabled and resuming a TLS 1.3 session */ + if (session->internals.flags & GNUTLS_ENABLE_EARLY_DATA && + !(session->internals.resumption_requested == 0 && + session->internals.premaster_set == 0) && + session->internals.resumed_security_parameters.pversion && + session->internals.resumed_security_parameters.pversion->tls13_sem) { + session->internals.hsk_flags |= HSK_EARLY_DATA_IN_FLIGHT; + return GNUTLS_E_INT_RET_0; + } + } + + return 0; +} + +/** + * gnutls_record_get_max_early_data_size: + * @session: is a #gnutls_session_t type. + * + * This function returns the maximum early data size in this connection. + * This property can only be set to servers. The client may be + * provided with the maximum allowed size through the "early_data" + * extension of the NewSessionTicket handshake message. + * + * Returns: The maximum early data size in this connection. + * + * Since: 3.6.5 + **/ +size_t +gnutls_record_get_max_early_data_size(gnutls_session_t session) +{ + return session->security_parameters.max_early_data_size; +} + +/** + * gnutls_record_set_max_early_data_size: + * @session: is a #gnutls_session_t type. + * @size: is the new size + * + * This function sets the maximum early data size in this connection. + * This property can only be set to servers. The client may be + * provided with the maximum allowed size through the "early_data" + * extension of the NewSessionTicket handshake message. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since: 3.6.4 + **/ +int +gnutls_record_set_max_early_data_size(gnutls_session_t session, + size_t size) +{ + if (session->security_parameters.entity == GNUTLS_CLIENT) + return GNUTLS_E_INVALID_REQUEST; + + /* Reject zero as well, as it is useless. */ + if (size == 0 || size > UINT32_MAX) + return GNUTLS_E_INVALID_REQUEST; + + session->security_parameters.max_early_data_size = (uint32_t) size; + + return 0; +} diff --git a/lib/ext/early_data.h b/lib/ext/early_data.h new file mode 100644 index 0000000..d7178e8 --- /dev/null +++ b/lib/ext/early_data.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_EARLY_DATA_H +#define GNUTLS_LIB_EXT_EARLY_DATA_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_early_data; + +#endif /* GNUTLS_LIB_EXT_EARLY_DATA_H */ diff --git a/lib/ext/ec_point_formats.c b/lib/ext/ec_point_formats.c new file mode 100644 index 0000000..d426580 --- /dev/null +++ b/lib/ext/ec_point_formats.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2011-2012 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Elliptic Curve Point Formats extension. + */ + +#include "ext/ec_point_formats.h" +#include "str.h" +#include "state.h" +#include <gnutls/gnutls.h> + + +static int _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_supported_ec_point_formats_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + + +const hello_ext_entry_st ext_mod_supported_ec_point_formats = { + .name = "Supported EC Point Formats", + .tls_id = 11, + .gid = GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | + GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_supported_ec_point_formats_recv_params, + .send_func = _gnutls_supported_ec_point_formats_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL +}; + + +/* Receive point formats + */ +static int +_gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size) +{ + size_t len, i; + int uncompressed = 0; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (data_size < 1) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + + len = data[0]; + if (len < 1) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + + DECR_LEN(data_size, len + 1); + + for (i = 1; i <= len; i++) + if (data[i] == 0) { /* uncompressed */ + uncompressed = 1; + break; + } + + if (uncompressed == 0) + return + gnutls_assert_val + (GNUTLS_E_UNKNOWN_PK_ALGORITHM); + } else { + /* only sanity check here. We only support uncompressed points + * and a client must support it thus nothing to check. + */ + if (data_size < 1) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_supported_ec_point_formats_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + const uint8_t p[2] = { 0x01, 0x00 }; /* only support uncompressed point format */ + int ret; + + if (session->security_parameters.entity == GNUTLS_SERVER + && !_gnutls_session_is_ecc(session)) + return 0; + + if (session->internals.priorities->groups.size > 0) { + ret = _gnutls_buffer_append_data(extdata, p, 2); + if (ret < 0) + return gnutls_assert_val(ret); + + return 2; + } + return 0; +} diff --git a/lib/ext/ec_point_formats.h b/lib/ext/ec_point_formats.h new file mode 100644 index 0000000..cc65c04 --- /dev/null +++ b/lib/ext/ec_point_formats.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2011-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_EC_POINT_FORMATS_H +#define GNUTLS_LIB_EXT_EC_POINT_FORMATS_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_supported_ec_point_formats; + +#endif /* GNUTLS_LIB_EXT_EC_POINT_FORMATS_H */ diff --git a/lib/ext/etm.c b/lib/ext/etm.c new file mode 100644 index 0000000..273a31a --- /dev/null +++ b/lib/ext/etm.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2014 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Max Record Size TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <hello_ext.h> +#include <ext/etm.h> + +static int _gnutls_ext_etm_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_ext_etm_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_etm = { + .name = "Encrypt-then-MAC", + .tls_id = 22, + .gid = GNUTLS_EXTENSION_ETM, + .client_parse_point = GNUTLS_EXT_MANDATORY, + .server_parse_point = GNUTLS_EXT_MANDATORY, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_ext_etm_recv_params, + .send_func = _gnutls_ext_etm_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + +/* + * In case of a server: if an EXT_MASTER_SECRET extension type is received then it + * sets a flag into the session security parameters. + * + */ +static int +_gnutls_ext_etm_recv_params(gnutls_session_t session, + const uint8_t * data, size_t _data_size) +{ + ssize_t data_size = _data_size; + + if (data_size != 0) { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + if (session->security_parameters.entity == GNUTLS_SERVER) { + gnutls_ext_priv_data_t epriv; + + if (session->internals.no_etm != 0) + return 0; + + epriv = (void*)(intptr_t)1; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_ETM, + epriv); + + /* don't decide now, decide on send */ + return 0; + } else { /* client */ + const gnutls_cipher_suite_entry_st *e = + session->security_parameters.cs; + if (e != NULL) { + const cipher_entry_st *c; + c = cipher_to_entry(e->block_algorithm); + if (c == NULL || (c->type == CIPHER_AEAD || c->type == CIPHER_STREAM)) + return 0; + + session->security_parameters.etm = 1; + } + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_ext_etm_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + if (session->internals.no_etm != 0) + return 0; + + /* this function sends the client extension data */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (session->internals.priorities->have_cbc != 0) + return GNUTLS_E_INT_RET_0; + else + return 0; + } else { /* server side */ + const gnutls_cipher_suite_entry_st *e; + const cipher_entry_st *c; + int ret; + gnutls_ext_priv_data_t epriv; + + e = session->security_parameters.cs; + if (e != NULL) { + c = cipher_to_entry(e->block_algorithm); + if (c == NULL || (c->type == CIPHER_AEAD || c->type == CIPHER_STREAM)) + return 0; + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_ETM, + &epriv); + if (ret < 0 || ((intptr_t)epriv) == 0) + return 0; + + session->security_parameters.etm = 1; + return GNUTLS_E_INT_RET_0; + } + } + + return 0; +} + +/** + * gnutls_session_etm_status: + * @session: is a #gnutls_session_t type. + * + * Get the status of the encrypt-then-mac extension negotiation. + * This is in accordance to rfc7366 + * + * Returns: Non-zero if the negotiation was successful or zero otherwise. + **/ +unsigned gnutls_session_etm_status(gnutls_session_t session) +{ + return session->security_parameters.etm; +} diff --git a/lib/ext/etm.h b/lib/ext/etm.h new file mode 100644 index 0000000..76f9dd5 --- /dev/null +++ b/lib/ext/etm.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_ETM_H +#define GNUTLS_LIB_EXT_ETM_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_etm; + +#endif /* GNUTLS_LIB_EXT_ETM_H */ diff --git a/lib/ext/ext_master_secret.c b/lib/ext/ext_master_secret.c new file mode 100644 index 0000000..bc704e6 --- /dev/null +++ b/lib/ext/ext_master_secret.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2014-2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the RFC7627 (ext master secret) TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <hello_ext.h> +#include <ext/ext_master_secret.h> + +static int _gnutls_ext_master_secret_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_ext_master_secret_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_ext_master_secret = { + .name = "Extended Master Secret", + .tls_id = 23, + .gid = GNUTLS_EXTENSION_EXT_MASTER_SECRET, + .client_parse_point = GNUTLS_EXT_MANDATORY, + .server_parse_point = GNUTLS_EXT_MANDATORY, + .validity = GNUTLS_EXT_FLAG_TLS|GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_ext_master_secret_recv_params, + .send_func = _gnutls_ext_master_secret_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + +#ifdef ENABLE_SSL3 +static inline unsigned have_only_ssl3_enabled(gnutls_session_t session) +{ + if (session->internals.priorities->protocol.num_priorities == 1 && + session->internals.priorities->protocol.priorities[0] == GNUTLS_SSL3) + return 1; + return 0; +} +#endif + +/* + * In case of a server: if an EXT_MASTER_SECRET extension type is received then it + * sets a flag into the session security parameters. + * + */ +static int +_gnutls_ext_master_secret_recv_params(gnutls_session_t session, + const uint8_t * data, size_t _data_size) +{ + ssize_t data_size = _data_size; + + if ((session->internals.flags & GNUTLS_NO_EXTENSIONS) || + session->internals.priorities->no_extensions || + session->internals.no_ext_master_secret != 0) { + return 0; + } + + if (data_size != 0) { + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + +#ifdef ENABLE_SSL3 + if (session->security_parameters.entity == GNUTLS_CLIENT) { + const version_entry_st *ver = get_version(session); + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + if (ver->id != GNUTLS_SSL3) + session->security_parameters.ext_master_secret = 1; + /* do not enable ext master secret if SSL 3.0 is the only protocol supported by server */ + } else if (!have_only_ssl3_enabled(session)) +#endif + session->security_parameters.ext_master_secret = 1; + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_ext_master_secret_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + if ((session->internals.flags & GNUTLS_NO_EXTENSIONS) || + session->internals.priorities->no_extensions != 0 || + session->internals.no_ext_master_secret != 0) { + session->security_parameters.ext_master_secret = 0; + return 0; + } + + /* this function sends the client extension data */ +#ifdef ENABLE_SSL3 + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (have_only_ssl3_enabled(session)) + return 0; /* this extension isn't available for SSL 3.0 */ + + return GNUTLS_E_INT_RET_0; + } else { /* server side */ + const version_entry_st *ver = get_version(session); + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + if (ver->id != GNUTLS_SSL3 && session->security_parameters.ext_master_secret != 0) + return GNUTLS_E_INT_RET_0; + } + + + return 0; +#else + if (session->security_parameters.entity == GNUTLS_CLIENT || + session->security_parameters.ext_master_secret != 0) + return GNUTLS_E_INT_RET_0; + return 0; +#endif +} + +/** + * gnutls_session_ext_master_secret_status: + * @session: is a #gnutls_session_t type. + * + * Get the status of the extended master secret extension negotiation. + * This is in accordance to RFC7627. That information is also + * available to the more generic gnutls_session_get_flags(). + * + * Returns: Non-zero if the negotiation was successful or zero otherwise. + **/ +unsigned gnutls_session_ext_master_secret_status(gnutls_session_t session) +{ + return session->security_parameters.ext_master_secret; +} + diff --git a/lib/ext/ext_master_secret.h b/lib/ext/ext_master_secret.h new file mode 100644 index 0000000..419335b --- /dev/null +++ b/lib/ext/ext_master_secret.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_EXT_MASTER_SECRET_H +#define GNUTLS_LIB_EXT_EXT_MASTER_SECRET_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_ext_master_secret; + +#endif /* GNUTLS_LIB_EXT_EXT_MASTER_SECRET_H */ diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c new file mode 100644 index 0000000..5d9e9f4 --- /dev/null +++ b/lib/ext/heartbeat.c @@ -0,0 +1,574 @@ +/* + * Copyright (C) 2012,2013 Free Software Foundation, Inc. + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file implements the TLS heartbeat extension. + */ + +#include "errors.h" +#include "gnutls_int.h" +#include <dtls.h> +#include <record.h> +#include <ext/heartbeat.h> +#include <hello_ext.h> +#include <random.h> + +#ifdef ENABLE_HEARTBEAT +/** + * gnutls_heartbeat_enable: + * @session: is a #gnutls_session_t type. + * @type: one of the GNUTLS_HB_* flags + * + * If this function is called with the %GNUTLS_HB_PEER_ALLOWED_TO_SEND + * @type, GnuTLS will allow heartbeat messages to be received. Moreover it also + * request the peer to accept heartbeat messages. This function + * must be called prior to TLS handshake. + * + * If the @type used is %GNUTLS_HB_LOCAL_ALLOWED_TO_SEND, then the peer + * will be asked to accept heartbeat messages but not send ones. + * + * The function gnutls_heartbeat_allowed() can be used to test Whether + * locally generated heartbeat messages can be accepted by the peer. + * + * Since: 3.1.2 + **/ +void gnutls_heartbeat_enable(gnutls_session_t session, unsigned int type) +{ + gnutls_ext_priv_data_t epriv; + + epriv = (void*)(intptr_t)type; + _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_HEARTBEAT, + epriv); +} + +/** + * gnutls_heartbeat_allowed: + * @session: is a #gnutls_session_t type. + * @type: one of %GNUTLS_HB_LOCAL_ALLOWED_TO_SEND and %GNUTLS_HB_PEER_ALLOWED_TO_SEND + * + * This function will check whether heartbeats are allowed + * to be sent or received in this session. + * + * Returns: Non zero if heartbeats are allowed. + * + * Since: 3.1.2 + **/ +unsigned gnutls_heartbeat_allowed(gnutls_session_t session, unsigned int type) +{ + gnutls_ext_priv_data_t epriv; + + if (session->internals.handshake_in_progress != 0) + return 0; /* not allowed */ + + if (_gnutls_hello_ext_get_priv + (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) + return 0; /* Not enabled */ + + if (type == GNUTLS_HB_LOCAL_ALLOWED_TO_SEND) { + if (((intptr_t)epriv) & LOCAL_ALLOWED_TO_SEND) + return 1; + } else if (((intptr_t)epriv) & GNUTLS_HB_PEER_ALLOWED_TO_SEND) + return 1; + + return 0; +} + +#define DEFAULT_PADDING_SIZE 16 + +/* + * Sends heartbeat data. + */ +static int +heartbeat_send_data(gnutls_session_t session, const void *data, + size_t data_size, uint8_t type) +{ + int ret, pos; + uint8_t *response; + + response = gnutls_malloc(1 + 2 + data_size + DEFAULT_PADDING_SIZE); + if (response == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + pos = 0; + response[pos++] = type; + + _gnutls_write_uint16(data_size, &response[pos]); + pos += 2; + + memcpy(&response[pos], data, data_size); + pos += data_size; + + ret = + gnutls_rnd(GNUTLS_RND_NONCE, &response[pos], + DEFAULT_PADDING_SIZE); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + pos += DEFAULT_PADDING_SIZE; + + ret = + _gnutls_send_int(session, GNUTLS_HEARTBEAT, -1, + EPOCH_WRITE_CURRENT, response, pos, + MBUFFER_FLUSH); + + cleanup: + gnutls_free(response); + return ret; +} + +/** + * gnutls_heartbeat_ping: + * @session: is a #gnutls_session_t type. + * @data_size: is the length of the ping payload. + * @max_tries: if flags is %GNUTLS_HEARTBEAT_WAIT then this sets the number of retransmissions. Use zero for indefinite (until timeout). + * @flags: if %GNUTLS_HEARTBEAT_WAIT then wait for pong or timeout instead of returning immediately. + * + * This function sends a ping to the peer. If the @flags is set + * to %GNUTLS_HEARTBEAT_WAIT then it waits for a reply from the peer. + * + * Note that it is highly recommended to use this function with the + * flag %GNUTLS_HEARTBEAT_WAIT, or you need to handle retransmissions + * and timeouts manually. + * + * The total TLS data transmitted as part of the ping message are given by + * the following formula: MAX(16, @data_size)+gnutls_record_overhead_size()+3. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. + * + * Since: 3.1.2 + **/ +int +gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size, + unsigned int max_tries, unsigned int flags) +{ + int ret; + unsigned int retries = 1, diff; + struct timespec now; + + if (data_size > MAX_HEARTBEAT_LENGTH) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (gnutls_heartbeat_allowed + (session, GNUTLS_HB_LOCAL_ALLOWED_TO_SEND) == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + /* resume previous call if interrupted */ + if (session->internals.record_send_buffer.byte_length > 0 && + session->internals.record_send_buffer.head != NULL && + session->internals.record_send_buffer.head->type == + GNUTLS_HEARTBEAT) + return _gnutls_io_write_flush(session); + + switch (session->internals.hb_state) { + case SHB_SEND1: + if (data_size > DEFAULT_PADDING_SIZE) + data_size -= DEFAULT_PADDING_SIZE; + else + data_size = 0; + + _gnutls_buffer_reset(&session->internals.hb_local_data); + + ret = + _gnutls_buffer_resize(&session->internals. + hb_local_data, data_size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + gnutls_rnd(GNUTLS_RND_NONCE, + session->internals.hb_local_data.data, + data_size); + if (ret < 0) + return gnutls_assert_val(ret); + + gnutls_gettime(&session->internals.hb_ping_start); + session->internals.hb_local_data.length = data_size; + session->internals.hb_state = SHB_SEND2; + + FALLTHROUGH; + case SHB_SEND2: + session->internals.hb_actual_retrans_timeout_ms = + session->internals.hb_retrans_timeout_ms; + retry: + ret = + heartbeat_send_data(session, + session->internals.hb_local_data. + data, + session->internals.hb_local_data. + length, HEARTBEAT_REQUEST); + if (ret < 0) + return gnutls_assert_val(ret); + + gnutls_gettime(&session->internals.hb_ping_sent); + + if (!(flags & GNUTLS_HEARTBEAT_WAIT)) { + session->internals.hb_state = SHB_SEND1; + break; + } + + session->internals.hb_state = SHB_RECV; + FALLTHROUGH; + + case SHB_RECV: + ret = + _gnutls_recv_int(session, GNUTLS_HEARTBEAT, + NULL, 0, NULL, + session->internals. + hb_actual_retrans_timeout_ms); + if (ret == GNUTLS_E_HEARTBEAT_PONG_RECEIVED) { + session->internals.hb_state = SHB_SEND1; + break; + } else if (ret == GNUTLS_E_TIMEDOUT) { + retries++; + if (max_tries > 0 && retries > max_tries) { + session->internals.hb_state = SHB_SEND1; + return gnutls_assert_val(ret); + } + + gnutls_gettime(&now); + diff = + timespec_sub_ms(&now, + &session->internals. + hb_ping_start); + if (diff > session->internals.hb_total_timeout_ms) { + session->internals.hb_state = SHB_SEND1; + return + gnutls_assert_val(GNUTLS_E_TIMEDOUT); + } + + session->internals.hb_actual_retrans_timeout_ms *= + 2; + session->internals.hb_actual_retrans_timeout_ms %= + MAX_DTLS_TIMEOUT; + + session->internals.hb_state = SHB_SEND2; + goto retry; + } else if (ret < 0) { + session->internals.hb_state = SHB_SEND1; + return gnutls_assert_val(ret); + } + } + + return 0; +} + +/** + * gnutls_heartbeat_pong: + * @session: is a #gnutls_session_t type. + * @flags: should be zero + * + * This function replies to a ping by sending a pong to the peer. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. + * + * Since: 3.1.2 + **/ +int gnutls_heartbeat_pong(gnutls_session_t session, unsigned int flags) +{ + int ret; + + if (session->internals.record_send_buffer.byte_length > 0 && + session->internals.record_send_buffer.head != NULL && + session->internals.record_send_buffer.head->type == + GNUTLS_HEARTBEAT) + return _gnutls_io_write_flush(session); + + if (session->internals.hb_remote_data.length == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = + heartbeat_send_data(session, + session->internals.hb_remote_data.data, + session->internals.hb_remote_data.length, + HEARTBEAT_RESPONSE); + + _gnutls_buffer_reset(&session->internals.hb_remote_data); + + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + +/* + * Processes a heartbeat message. + */ +int _gnutls_heartbeat_handle(gnutls_session_t session, mbuffer_st * bufel) +{ + int ret; + unsigned type; + unsigned pos; + uint8_t *msg = _mbuffer_get_udata_ptr(bufel); + size_t hb_len, len = _mbuffer_get_udata_size(bufel); + + if (gnutls_heartbeat_allowed + (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND) == 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + + if (len < 3 + DEFAULT_PADDING_SIZE) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + pos = 0; + type = msg[pos++]; + + hb_len = _gnutls_read_uint16(&msg[pos]); + if (hb_len > len - 3 - DEFAULT_PADDING_SIZE) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + pos += 2; + + switch (type) { + case HEARTBEAT_REQUEST: + _gnutls_buffer_reset(&session->internals.hb_remote_data); + + ret = + _gnutls_buffer_resize(&session->internals. + hb_remote_data, hb_len); + if (ret < 0) + return gnutls_assert_val(ret); + + if (hb_len > 0) + memcpy(session->internals.hb_remote_data.data, + &msg[pos], hb_len); + session->internals.hb_remote_data.length = hb_len; + + return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PING_RECEIVED); + + case HEARTBEAT_RESPONSE: + + if (hb_len != session->internals.hb_local_data.length) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + + if (hb_len > 0 && + memcmp(&msg[pos], + session->internals.hb_local_data.data, + hb_len) != 0) { + if (IS_DTLS(session)) + return gnutls_assert_val(GNUTLS_E_AGAIN); /* ignore it */ + else + return + gnutls_assert_val + (GNUTLS_E_UNEXPECTED_PACKET); + } + + _gnutls_buffer_reset(&session->internals.hb_local_data); + + return gnutls_assert_val(GNUTLS_E_HEARTBEAT_PONG_RECEIVED); + default: + _gnutls_record_log + ("REC[%p]: HB: received unknown type %u\n", session, + type); + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + } +} + +/** + * gnutls_heartbeat_get_timeout: + * @session: is a #gnutls_session_t type. + * + * This function will return the milliseconds remaining + * for a retransmission of the previously sent ping + * message. This function is useful when ping is used in + * non-blocking mode, to estimate when to call gnutls_heartbeat_ping() + * if no packets have been received. + * + * Returns: the remaining time in milliseconds. + * + * Since: 3.1.2 + **/ +unsigned int gnutls_heartbeat_get_timeout(gnutls_session_t session) +{ + struct timespec now; + unsigned int diff; + + gnutls_gettime(&now); + diff = timespec_sub_ms(&now, &session->internals.hb_ping_sent); + if (diff >= session->internals.hb_actual_retrans_timeout_ms) + return 0; + else + return session->internals.hb_actual_retrans_timeout_ms - + diff; +} + +/** + * gnutls_heartbeat_set_timeouts: + * @session: is a #gnutls_session_t type. + * @retrans_timeout: The time at which a retransmission will occur in milliseconds + * @total_timeout: The time at which the connection will be aborted, in milliseconds. + * + * This function will override the timeouts for the DTLS heartbeat + * protocol. The retransmission timeout is the time after which a + * message from the peer is not received, the previous request will + * be retransmitted. The total timeout is the time after which the + * handshake will be aborted with %GNUTLS_E_TIMEDOUT. + * + * Since: 3.1.2 + **/ +void gnutls_heartbeat_set_timeouts(gnutls_session_t session, + unsigned int retrans_timeout, + unsigned int total_timeout) +{ + session->internals.hb_retrans_timeout_ms = retrans_timeout; + session->internals.hb_total_timeout_ms = total_timeout; +} + + +static int +_gnutls_heartbeat_recv_params(gnutls_session_t session, + const uint8_t * data, size_t _data_size) +{ + unsigned policy; + gnutls_ext_priv_data_t epriv; + + if (_gnutls_hello_ext_get_priv + (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) { + if (session->security_parameters.entity == GNUTLS_CLIENT) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + return 0; /* Not enabled */ + } + + if (_data_size == 0) + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + + policy = (intptr_t)epriv; + + if (data[0] == 1) + policy |= LOCAL_ALLOWED_TO_SEND; + else if (data[0] == 2) + policy |= LOCAL_NOT_ALLOWED_TO_SEND; + else + return + gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + epriv = (void*)(intptr_t)policy; + _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_HEARTBEAT, + epriv); + + return 0; +} + +static int +_gnutls_heartbeat_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + gnutls_ext_priv_data_t epriv; + uint8_t p; + + if (_gnutls_hello_ext_get_priv + (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0) + return 0; /* nothing to send - not enabled */ + + if (((intptr_t)epriv) & GNUTLS_HB_PEER_ALLOWED_TO_SEND) + p = 1; + else /*if (epriv.num & GNUTLS_HB_PEER_NOT_ALLOWED_TO_SEND) */ + p = 2; + + if (_gnutls_buffer_append_data(extdata, &p, 1) < 0) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + return 1; +} + +static int +_gnutls_heartbeat_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps) +{ + int ret; + + BUFFER_APPEND_NUM(ps, (intptr_t)epriv); + + return 0; + +} + +static int +_gnutls_heartbeat_unpack(gnutls_buffer_st * ps, + gnutls_ext_priv_data_t * _priv) +{ + gnutls_ext_priv_data_t epriv; + int ret; + + BUFFER_POP_CAST_NUM(ps, epriv); + + *_priv = epriv; + + ret = 0; + error: + return ret; +} + +const hello_ext_entry_st ext_mod_heartbeat = { + .name = "Heartbeat", + .tls_id = 15, + .gid = GNUTLS_EXTENSION_HEARTBEAT, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_heartbeat_recv_params, + .send_func = _gnutls_heartbeat_send_params, + .pack_func = _gnutls_heartbeat_pack, + .unpack_func = _gnutls_heartbeat_unpack, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + +#else +void gnutls_heartbeat_enable(gnutls_session_t session, unsigned int type) +{ +} + +unsigned gnutls_heartbeat_allowed(gnutls_session_t session, unsigned int type) +{ + return 0; +} + +int +gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size, + unsigned int max_tries, unsigned int flags) +{ + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +} + +int gnutls_heartbeat_pong(gnutls_session_t session, unsigned int flags) +{ + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); +} + +unsigned int gnutls_heartbeat_get_timeout(gnutls_session_t session) +{ + return 0; +} + +void gnutls_heartbeat_set_timeouts(gnutls_session_t session, + unsigned int retrans_timeout, + unsigned int total_timeout) +{ + return; +} +#endif diff --git a/lib/ext/heartbeat.h b/lib/ext/heartbeat.h new file mode 100644 index 0000000..1a21004 --- /dev/null +++ b/lib/ext/heartbeat.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 Free Software Foundation, Inc. + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_HEARTBEAT_H +#define GNUTLS_LIB_EXT_HEARTBEAT_H + +#include <hello_ext.h> + +#define HEARTBEAT_REQUEST 1 +#define HEARTBEAT_RESPONSE 2 + +#define MAX_HEARTBEAT_LENGTH DEFAULT_MAX_RECORD_SIZE + +#define LOCAL_ALLOWED_TO_SEND (1<<2) +#define LOCAL_NOT_ALLOWED_TO_SEND (1<<3) + +#define HEARTBEAT_DEFAULT_POLICY PEER_NOT_ALLOWED_TO_SEND + +extern const hello_ext_entry_st ext_mod_heartbeat; + +int _gnutls_heartbeat_handle(gnutls_session_t session, mbuffer_st * bufel); +int _gnutls_heartbeat_enabled(gnutls_session_t session, int local); + +#endif /* GNUTLS_LIB_EXT_HEARTBEAT_H */ diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c new file mode 100644 index 0000000..a4db3af --- /dev/null +++ b/lib/ext/key_share.c @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code the Key Share TLS 1.3 extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include "ext/supported_groups.h" +#include <state.h> +#include <num.h> +#include <algorithms.h> +#include "auth/psk.h" +#include "auth/cert.h" +#include "handshake.h" +#include "../ecc.h" +#include "../algorithms.h" +#include "pk.h" + +static int key_share_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int key_share_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_key_share = { + .name = "Key Share", + .tls_id = 51, + .gid = GNUTLS_EXTENSION_KEY_SHARE, + .client_parse_point = _GNUTLS_EXT_TLS_POST_CS, + .server_parse_point = _GNUTLS_EXT_TLS_POST_CS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | + GNUTLS_EXT_FLAG_HRR, + .recv_func = key_share_recv_params, + .send_func = key_share_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + +/* + * Generates key exchange parameters, and stores them in + * session->key.kshare_*_params. + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * + */ +static int client_gen_key_share(gnutls_session_t session, const gnutls_group_entry_st *group, gnutls_buffer_st *extdata) +{ + gnutls_datum_t tmp = {NULL, 0}; + int ret; + + if (group->pk != GNUTLS_PK_EC && group->pk != GNUTLS_PK_ECDH_X25519 && + group->pk != GNUTLS_PK_ECDH_X448 && + group->pk != GNUTLS_PK_DH) { + _gnutls_debug_log("Cannot send key share for group %s!\n", group->name); + return GNUTLS_E_INT_RET_0; + } + + _gnutls_handshake_log("EXT[%p]: sending key share for %s\n", session, group->name); + + ret = + _gnutls_buffer_append_prefix(extdata, 16, group->tls_id); + if (ret < 0) + return gnutls_assert_val(ret); + + if (group->pk == GNUTLS_PK_EC) { + gnutls_pk_params_release(&session->key.kshare.ecdh_params); + gnutls_pk_params_init(&session->key.kshare.ecdh_params); + + ret = _gnutls_pk_generate_keys(group->pk, group->curve, + &session->key.kshare.ecdh_params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_ecc_ansi_x962_export(group->curve, + session->key.kshare.ecdh_params.params[ECC_X], + session->key.kshare.ecdh_params.params[ECC_Y], + &tmp); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data_prefix(extdata, 16, tmp.data, tmp.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + session->key.kshare.ecdh_params.algo = group->pk; + session->key.kshare.ecdh_params.curve = group->curve; + + ret = 0; + + } else if (group->pk == GNUTLS_PK_ECDH_X25519 || + group->pk == GNUTLS_PK_ECDH_X448) { + gnutls_pk_params_release(&session->key.kshare.ecdhx_params); + gnutls_pk_params_init(&session->key.kshare.ecdhx_params); + + ret = _gnutls_pk_generate_keys(group->pk, group->curve, + &session->key.kshare.ecdhx_params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data_prefix(extdata, 16, + session->key.kshare.ecdhx_params.raw_pub.data, + session->key.kshare.ecdhx_params.raw_pub.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + session->key.kshare.ecdhx_params.algo = group->pk; + session->key.kshare.ecdhx_params.curve = group->curve; + + ret = 0; + + } else if (group->pk == GNUTLS_PK_DH) { + /* we need to initialize the group parameters first */ + gnutls_pk_params_release(&session->key.kshare.dh_params); + gnutls_pk_params_init(&session->key.kshare.dh_params); + + ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_G], + group->generator->data, group->generator->size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_P], + group->prime->data, group->prime->size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_Q], + group->q->data, group->q->size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + session->key.kshare.dh_params.algo = group->pk; + session->key.kshare.dh_params.dh_group = group->id; /* no curve in FFDH, we write the group */ + session->key.kshare.dh_params.qbits = *group->q_bits; + session->key.kshare.dh_params.params_nr = 3; + + ret = _gnutls_pk_generate_keys(group->pk, 0, &session->key.kshare.dh_params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_prefix(extdata, 16, group->prime->size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_fixed_mpi(extdata, session->key.kshare.dh_params.params[DH_Y], + group->prime->size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = 0; + } + + cleanup: + gnutls_free(tmp.data); + return ret; +} + +/* + * Sends server key exchange parameters + * + */ +static int server_gen_key_share(gnutls_session_t session, const gnutls_group_entry_st *group, gnutls_buffer_st *extdata) +{ + gnutls_datum_t tmp = {NULL, 0}; + int ret; + + if (group->pk != GNUTLS_PK_EC && group->pk != GNUTLS_PK_ECDH_X25519 && + group->pk != GNUTLS_PK_ECDH_X448 && + group->pk != GNUTLS_PK_DH) { + _gnutls_debug_log("Cannot send key share for group %s!\n", group->name); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + _gnutls_handshake_log("EXT[%p]: sending key share for %s\n", session, group->name); + + ret = + _gnutls_buffer_append_prefix(extdata, 16, group->tls_id); + if (ret < 0) + return gnutls_assert_val(ret); + + if (group->pk == GNUTLS_PK_EC) { + ret = _gnutls_ecc_ansi_x962_export(group->curve, + session->key.kshare.ecdh_params.params[ECC_X], + session->key.kshare.ecdh_params.params[ECC_Y], + &tmp); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data_prefix(extdata, 16, tmp.data, tmp.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + + } else if (group->pk == GNUTLS_PK_ECDH_X25519 || + group->pk == GNUTLS_PK_ECDH_X448) { + ret = + _gnutls_buffer_append_data_prefix(extdata, 16, + session->key.kshare.ecdhx_params.raw_pub.data, + session->key.kshare.ecdhx_params.raw_pub.size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = 0; + + } else if (group->pk == GNUTLS_PK_DH) { + ret = + _gnutls_buffer_append_prefix(extdata, 16, group->prime->size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_fixed_mpi(extdata, session->key.kshare.dh_params.params[DH_Y], + group->prime->size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = 0; + } + + cleanup: + gnutls_free(tmp.data); + return ret; +} + +/* Generates shared key and stores it in session->key.key + */ +static int +server_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *group, + const uint8_t * data, size_t data_size) +{ + const gnutls_ecc_curve_entry_st *curve; + int ret; + + if (group->pk == GNUTLS_PK_EC) { + gnutls_pk_params_st pub; + + gnutls_pk_params_release(&session->key.kshare.ecdh_params); + gnutls_pk_params_init(&session->key.kshare.ecdh_params); + + curve = _gnutls_ecc_curve_get_params(group->curve); + + gnutls_pk_params_init(&pub); + + if (curve->size*2+1 != data_size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* generate our key */ + ret = _gnutls_pk_generate_keys(curve->pk, curve->id, &session->key.kshare.ecdh_params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + /* read the public key */ + ret = _gnutls_ecc_ansi_x962_import(data, data_size, + &pub.params[ECC_X], + &pub.params[ECC_Y]); + if (ret < 0) + return gnutls_assert_val(ret); + + pub.algo = group->pk; + pub.curve = curve->id; + pub.params_nr = 2; + + /* generate shared */ + ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdh_params, &pub); + gnutls_pk_params_release(&pub); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = 0; + + } else if (group->pk == GNUTLS_PK_ECDH_X25519 || + group->pk == GNUTLS_PK_ECDH_X448) { + gnutls_pk_params_st pub; + + gnutls_pk_params_release(&session->key.kshare.ecdhx_params); + gnutls_pk_params_init(&session->key.kshare.ecdhx_params); + + curve = _gnutls_ecc_curve_get_params(group->curve); + + if (curve->size != data_size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* generate our key */ + ret = _gnutls_pk_generate_keys(curve->pk, curve->id, &session->key.kshare.ecdhx_params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + /* read the public key and generate shared */ + gnutls_pk_params_init(&pub); + + pub.algo = group->pk; + pub.curve = curve->id; + + pub.raw_pub.data = (void*)data; + pub.raw_pub.size = data_size; + + /* We don't mask the MSB in the final byte as required + * by RFC7748. This will be done internally by nettle 3.3 or later. + */ + ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdhx_params, &pub); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = 0; + + } else if (group->pk == GNUTLS_PK_DH) { + gnutls_pk_params_st pub; + + /* we need to initialize the group parameters first */ + gnutls_pk_params_release(&session->key.kshare.dh_params); + gnutls_pk_params_init(&session->key.kshare.dh_params); + + if (data_size != group->prime->size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* set group params */ + ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_G], + group->generator->data, group->generator->size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_P], + group->prime->data, group->prime->size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_mpi_init_scan_nz(&session->key.kshare.dh_params.params[DH_Q], + group->q->data, group->q->size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + session->key.kshare.dh_params.algo = GNUTLS_PK_DH; + session->key.kshare.dh_params.qbits = *group->q_bits; + session->key.kshare.dh_params.params_nr = 3; + + /* generate our keys */ + ret = _gnutls_pk_generate_keys(group->pk, 0, &session->key.kshare.dh_params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + /* read the public key and generate shared */ + gnutls_pk_params_init(&pub); + + ret = _gnutls_mpi_init_scan_nz(&pub.params[DH_Y], + data, data_size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + pub.algo = group->pk; + + /* generate shared key */ + ret = _gnutls_pk_derive_tls13(GNUTLS_PK_DH, &session->key.key, &session->key.kshare.dh_params, &pub); + _gnutls_mpi_release(&pub.params[DH_Y]); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = 0; + } else { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + _gnutls_debug_log("EXT[%p]: server generated %s shared key\n", session, group->name); + + return ret; +} + +/* Generates shared key and stores it in session->key.key + */ +static int +client_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *group, + const uint8_t * data, size_t data_size) +{ + const gnutls_ecc_curve_entry_st *curve; + int ret; + + if (group->pk == GNUTLS_PK_EC) { + gnutls_pk_params_st pub; + + curve = _gnutls_ecc_curve_get_params(group->curve); + + gnutls_pk_params_init(&pub); + + if (session->key.kshare.ecdh_params.algo != group->pk || session->key.kshare.ecdh_params.curve != curve->id) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + if (curve->size*2+1 != data_size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* read the server's public key */ + ret = _gnutls_ecc_ansi_x962_import(data, data_size, + &pub.params[ECC_X], + &pub.params[ECC_Y]); + if (ret < 0) + return gnutls_assert_val(ret); + + pub.algo = group->pk; + pub.curve = curve->id; + pub.params_nr = 2; + + /* generate shared key */ + ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdh_params, &pub); + gnutls_pk_params_release(&pub); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = 0; + + } else if (group->pk == GNUTLS_PK_ECDH_X25519 || + group->pk == GNUTLS_PK_ECDH_X448) { + gnutls_pk_params_st pub; + + curve = _gnutls_ecc_curve_get_params(group->curve); + + if (session->key.kshare.ecdhx_params.algo != group->pk || session->key.kshare.ecdhx_params.curve != curve->id) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + if (curve->size != data_size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* read the public key and generate shared */ + gnutls_pk_params_init(&pub); + + pub.algo = group->pk; + pub.curve = curve->id; + + pub.raw_pub.data = (void*)data; + pub.raw_pub.size = data_size; + + /* We don't mask the MSB in the final byte as required + * by RFC7748. This will be done internally by nettle 3.3 or later. + */ + ret = _gnutls_pk_derive_tls13(curve->pk, &session->key.key, &session->key.kshare.ecdhx_params, &pub); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = 0; + + } else if (group->pk == GNUTLS_PK_DH) { + gnutls_pk_params_st pub; + + if (session->key.kshare.dh_params.algo != group->pk || session->key.kshare.dh_params.dh_group != group->id) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + if (data_size != group->prime->size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* read the public key and generate shared */ + gnutls_pk_params_init(&pub); + + ret = _gnutls_mpi_init_scan_nz(&pub.params[DH_Y], + data, data_size); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + pub.algo = group->pk; + + /* generate shared key */ + ret = _gnutls_pk_derive_tls13(GNUTLS_PK_DH, &session->key.key, &session->key.kshare.dh_params, &pub); + _gnutls_mpi_release(&pub.params[DH_Y]); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = 0; + } else { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + _gnutls_debug_log("EXT[%p]: client generated %s shared key\n", session, group->name); + + return ret; +} + +static int +key_share_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + int ret; + size_t size; + unsigned gid; + const version_entry_st *ver; + const gnutls_group_entry_st *group; + unsigned used_share = 0; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + ver = get_version(session); + if (ver == NULL || ver->key_shares == 0) + return gnutls_assert_val(0); + + DECR_LEN(data_size, 2); + size = _gnutls_read_uint16(data); + data += 2; + + if (data_size != size) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* if we do PSK without DH ignore that share */ + if ((session->internals.hsk_flags & HSK_PSK_SELECTED) && + (session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK)) { + reset_cand_groups(session); + return 0; + } + + while(data_size > 0) { + DECR_LEN(data_size, 2); + gid = _gnutls_read_uint16(data); + data += 2; + + DECR_LEN(data_size, 2); + size = _gnutls_read_uint16(data); + data += 2; + + DECR_LEN(data_size, size); + + /* at this point we have already negotiated a group; + * find the group's share. */ + group = _gnutls_tls_id_to_group(gid); + + if (group != NULL) + _gnutls_handshake_log("EXT[%p]: Received key share for %s\n", session, group->name); + + if (group != NULL && group == session->internals.cand_group) { + _gnutls_session_group_set(session, group); + + ret = server_use_key_share(session, group, data, size); + if (ret < 0) + return gnutls_assert_val(ret); + + used_share = 1; + break; + + } + + data += size; + continue; + } + + /* we utilize GNUTLS_E_NO_COMMON_KEY_SHARE for: + * 1. signal for hello-retry-request in the handshake + * layer during first client hello parsing (server side - here). + * This does not result to error code being + * propagated to app layer. + * 2. Propagate to application error code that no + * common key share was found after an HRR was + * received (client side) + * 3. Propagate to application error code that no + * common key share was found after an HRR was + * sent (server side). + * In cases (2,3) the error is translated to illegal + * parameter alert. + */ + if (used_share == 0) { + return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE); + } + + session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED; + } else { /* Client */ + ver = get_version(session); + if (unlikely(ver == NULL || ver->key_shares == 0)) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) { + if (unlikely(!(session->internals.hsk_flags & HSK_HRR_RECEIVED))) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + DECR_LEN(data_size, 2); + gid = _gnutls_read_uint16(data); + + group = _gnutls_tls_id_to_group(gid); + if (group == NULL) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + _gnutls_handshake_log("EXT[%p]: HRR key share with %s\n", session, group->name); + + /* check if we support it */ + ret = _gnutls_session_supports_group(session, group->id); + if (ret < 0) { + _gnutls_handshake_log("EXT[%p]: received share for %s which is disabled\n", session, group->name); + return gnutls_assert_val(ret); + } + + _gnutls_session_group_set(session, group); + + return 0; + } + /* else */ + + DECR_LEN(data_size, 2); + gid = _gnutls_read_uint16(data); + data += 2; + + DECR_LEN(data_size, 2); + size = _gnutls_read_uint16(data); + data+=2; + + if (data_size != size) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + group = _gnutls_tls_id_to_group(gid); + if (group == NULL) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + /* check if we support it */ + ret = _gnutls_session_supports_group(session, group->id); + if (ret < 0) { + _gnutls_handshake_log("EXT[%p]: received share for %s which is disabled\n", session, group->name); + return gnutls_assert_val(ret); + } + + _gnutls_session_group_set(session, group); + session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED; + + ret = client_use_key_share(session, group, data, size); + if (ret < 0) + return gnutls_assert_val(ret); + } + + return 0; +} + +static inline bool +pk_type_is_ecdhx(gnutls_pk_algorithm_t pk) +{ + return pk == GNUTLS_PK_ECDH_X25519 || pk == GNUTLS_PK_ECDH_X448; +} + +static inline bool +pk_type_equal(gnutls_pk_algorithm_t a, gnutls_pk_algorithm_t b) +{ + return a == b || (pk_type_is_ecdhx(a) && pk_type_is_ecdhx(b)); +} + +/* returns data_size or a negative number on failure + */ +static int +key_share_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + unsigned i; + int ret; + unsigned int generated = 0; + const gnutls_group_entry_st *group; + const version_entry_st *ver; + + /* this extension is only being sent on client side */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + unsigned int length_pos; + + ver = _gnutls_version_max(session); + if (unlikely(ver == NULL || ver->key_shares == 0)) + return 0; + + if (!have_creds_for_tls13(session)) + return 0; + + length_pos = extdata->length; + + ret = + _gnutls_buffer_append_prefix(extdata, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + if (session->internals.hsk_flags & HSK_HRR_RECEIVED) { /* we know the group */ + group = get_group(session); + if (unlikely(group == NULL)) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = client_gen_key_share(session, group, extdata); + if (ret == GNUTLS_E_INT_RET_0) + return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE); + if (ret < 0) + return gnutls_assert_val(ret); + } else { + gnutls_pk_algorithm_t selected_groups[3]; + unsigned max_groups = 2; /* GNUTLS_KEY_SHARE_TOP2 */ + + if (session->internals.flags & GNUTLS_KEY_SHARE_TOP) + max_groups = 1; + else if (session->internals.flags & GNUTLS_KEY_SHARE_TOP3) + max_groups = 3; + + assert(max_groups <= sizeof(selected_groups)/sizeof(selected_groups[0])); + + /* generate key shares for out top-(max_groups) groups + * if they are of different PK type. */ + for (i = 0; i < session->internals.priorities->groups.size; i++) { + unsigned int j; + + group = session->internals.priorities->groups.entry[i]; + + for (j = 0; j < generated; j++) { + if (pk_type_equal(group->pk, selected_groups[j])) { + break; + } + } + if (j < generated) { + continue; + } + + selected_groups[generated] = group->pk; + + ret = client_gen_key_share(session, group, extdata); + if (ret == GNUTLS_E_INT_RET_0) + continue; /* no key share for this algorithm */ + if (ret < 0) + return gnutls_assert_val(ret); + + generated++; + + if (generated >= max_groups) + break; + } + } + + /* copy actual length */ + _gnutls_write_uint16(extdata->length - length_pos - 2, + &extdata->data[length_pos]); + + } else { /* server */ + ver = get_version(session); + if (unlikely(ver == NULL || ver->key_shares == 0)) + return gnutls_assert_val(0); + + if (_gnutls_ext_get_msg(session) == GNUTLS_EXT_FLAG_HRR) { + group = session->internals.cand_group; + + if (group == NULL) + return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE); + + _gnutls_session_group_set(session, group); + + _gnutls_handshake_log("EXT[%p]: requesting retry with group %s\n", session, group->name); + ret = + _gnutls_buffer_append_prefix(extdata, 16, group->tls_id); + if (ret < 0) + return gnutls_assert_val(ret); + } else { + /* if we are negotiating PSK without DH, do not send a key share */ + if ((session->internals.hsk_flags & HSK_PSK_SELECTED) && + (session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK)) + return gnutls_assert_val(0); + + group = get_group(session); + if (unlikely(group == NULL)) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = server_gen_key_share(session, group, extdata); + if (ret < 0) + return gnutls_assert_val(ret); + } + + session->internals.hsk_flags |= HSK_KEY_SHARE_SENT; + } + + return 0; +} diff --git a/lib/ext/key_share.h b/lib/ext/key_share.h new file mode 100644 index 0000000..ed9aa16 --- /dev/null +++ b/lib/ext/key_share.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_KEY_SHARE_H +#define GNUTLS_LIB_EXT_KEY_SHARE_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_key_share; + +#endif /* GNUTLS_LIB_EXT_KEY_SHARE_H */ diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c new file mode 100644 index 0000000..87302cb --- /dev/null +++ b/lib/ext/max_record.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2001-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Max Record Size TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <hello_ext.h> +#include <ext/max_record.h> + +static int _gnutls_max_record_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_max_record_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +/* Maps record size to numbers according to the + * extensions draft. + */ +static int _gnutls_mre_num2record(int num); +static int _gnutls_mre_record2num(uint16_t record_size); + + +const hello_ext_entry_st ext_mod_max_record_size = { + .name = "Maximum Record Size", + .tls_id = 1, + .gid = GNUTLS_EXTENSION_MAX_RECORD_SIZE, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_max_record_recv_params, + .send_func = _gnutls_max_record_send_params +}; + +/* + * In case of a server: if a MAX_RECORD_SIZE extension type is received then it stores + * into the session the new value. The server may use gnutls_get_max_record_size(), + * in order to access it. + * + * In case of a client: If a different max record size (than the default) has + * been specified then it sends the extension. + * + */ + +static int +_gnutls_max_record_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + ssize_t new_size; + + if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) + return 0; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (data_size > 0) { + DECR_LEN(data_size, 1); + + new_size = _gnutls_mre_num2record(data[0]); + + if (new_size < 0) { + gnutls_assert(); + return new_size; + } + + session->security_parameters.max_record_send_size = + new_size; + session->security_parameters.max_record_recv_size = + new_size; + } + } else { /* CLIENT SIDE - we must check if the sent record size is the right one + */ + if (data_size > 0) { + if (data_size != 1) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + new_size = _gnutls_mre_num2record(data[0]); + + if (new_size < 0) { + gnutls_assert(); + return new_size; + } + + if (new_size != session->security_parameters. + max_user_record_send_size) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } else { + session->security_parameters. + max_record_send_size = new_size; + session->security_parameters. + max_record_recv_size = new_size; + } + + } + + + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_max_record_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + uint8_t p; + int ret; + + /* this function sends the client extension data (dnsname) */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + /* if the user limits for sending and receiving are + * different, that means the programmer had chosen to + * use record_size_limit instead */ + if (session->security_parameters.max_user_record_send_size != + session->security_parameters.max_user_record_recv_size) + return 0; + + if (session->security_parameters.max_user_record_send_size != + DEFAULT_MAX_RECORD_SIZE) { + ret = _gnutls_mre_record2num + (session->security_parameters. + max_user_record_send_size); + + /* it's not an error, as long as we send the + * record_size_limit extension with that value */ + if (ret < 0) + return 0; + + p = (uint8_t) ret; + ret = _gnutls_buffer_append_data(extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + return 1; + } + + } else { /* server side */ + + if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_SENT) + return 0; + + if (session->security_parameters.max_record_recv_size != + DEFAULT_MAX_RECORD_SIZE) { + ret = _gnutls_mre_record2num + (session->security_parameters. + max_record_recv_size); + if (ret < 0) + return gnutls_assert_val(ret); + + p = (uint8_t) ret; + ret = _gnutls_buffer_append_data(extdata, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + return 1; + } + } + + return 0; +} + + +/* Maps numbers to record sizes according to the + * extensions draft. + */ +static int _gnutls_mre_num2record(int num) +{ + switch (num) { + case 1: + return 512; + case 2: + return 1024; + case 3: + return 2048; + case 4: + return 4096; + default: + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } +} + +/* Maps record size to numbers according to the + * extensions draft. + */ +static int _gnutls_mre_record2num(uint16_t record_size) +{ + switch (record_size) { + case 512: + return 1; + case 1024: + return 2; + case 2048: + return 3; + case 4096: + return 4; + default: + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + +} + +/** + * gnutls_record_get_max_size: + * @session: is a #gnutls_session_t type. + * + * Get the record size. The maximum record size is negotiated by the + * client after the first handshake message. + * + * Returns: The maximum record packet size in this connection. + **/ +size_t gnutls_record_get_max_size(gnutls_session_t session) +{ + /* Recv will hold the negotiated max record size + * always. + */ + return session->security_parameters.max_record_recv_size; +} + + +/** + * gnutls_record_set_max_size: + * @session: is a #gnutls_session_t type. + * @size: is the new size + * + * This function sets the maximum amount of plaintext sent and + * received in a record in this connection. + * + * Prior to 3.6.4, this function was implemented using a TLS extension + * called 'max fragment length', which limits the acceptable values to + * 512(=2^9), 1024(=2^10), 2048(=2^11) and 4096(=2^12). + * + * Since 3.6.4, the limit is also negotiated through a new TLS + * extension called 'record size limit', which doesn't have the + * limitation, as long as the value ranges between 512 and 16384. + * Note that while the 'record size limit' extension is preferred, not + * all TLS implementations use or even understand the extension. + * + * Deprecated: if the client can assume that the 'record size limit' + * extension is supported by the server, we recommend using + * gnutls_record_set_max_recv_size() instead. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + **/ +ssize_t gnutls_record_set_max_size(gnutls_session_t session, size_t size) +{ + if (size < MIN_RECORD_SIZE || size > DEFAULT_MAX_RECORD_SIZE) + return GNUTLS_E_INVALID_REQUEST; + + if (session->internals.handshake_in_progress) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + session->security_parameters.max_user_record_send_size = size; + session->security_parameters.max_user_record_recv_size = size; + + return 0; +} + +/** + * gnutls_record_set_max_recv_size: + * @session: is a #gnutls_session_t type. + * @size: is the new size + * + * This function sets the maximum amount of plaintext received in a + * record in this connection. + * + * The limit is also negotiated through a TLS extension called 'record + * size limit'. Note that while the 'record size limit' extension is + * preferred, not all TLS implementations use or even understand the + * extension. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since: 3.6.8 + **/ +ssize_t gnutls_record_set_max_recv_size(gnutls_session_t session, size_t size) +{ + if (size < + (session->internals.allow_small_records ? + MIN_RECORD_SIZE_SMALL : MIN_RECORD_SIZE) || + size > DEFAULT_MAX_RECORD_SIZE) + return GNUTLS_E_INVALID_REQUEST; + + if (session->internals.handshake_in_progress) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + session->security_parameters.max_user_record_recv_size = size; + + return 0; +} diff --git a/lib/ext/max_record.h b/lib/ext/max_record.h new file mode 100644 index 0000000..758c8e1 --- /dev/null +++ b/lib/ext/max_record.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2001-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_MAX_RECORD_H +#define GNUTLS_LIB_EXT_MAX_RECORD_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_max_record_size; + +#endif /* GNUTLS_LIB_EXT_MAX_RECORD_H */ diff --git a/lib/ext/post_handshake.c b/lib/ext/post_handshake.c new file mode 100644 index 0000000..27fe1e7 --- /dev/null +++ b/lib/ext/post_handshake.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Post-Handshake TLS 1.3 extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <hello_ext.h> +#include <ext/post_handshake.h> +#include "auth/cert.h" + +static int _gnutls_post_handshake_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_post_handshake_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_post_handshake = { + .name = "Post Handshake Auth", + .tls_id = 49, + .gid = GNUTLS_EXTENSION_POST_HANDSHAKE, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO, + .recv_func = _gnutls_post_handshake_recv_params, + .send_func = _gnutls_post_handshake_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + +static int +_gnutls_post_handshake_recv_params(gnutls_session_t session, + const uint8_t * data, size_t _data_size) +{ + const version_entry_st *vers; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + vers = get_version(session); + if (unlikely(vers == NULL)) + return 0; + + if ((session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH) && + vers->post_handshake_auth) + session->security_parameters.post_handshake_auth = 1; + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_post_handshake_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + gnutls_certificate_credentials_t cred; + const version_entry_st *max; + + if (session->security_parameters.entity != GNUTLS_CLIENT || + !(session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH)) { + /* not sent on server side */ + return 0; + } + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) /* no certificate authentication */ + return gnutls_assert_val(0); + + max = _gnutls_version_max(session); + if (unlikely(max == NULL)) + return gnutls_assert_val(0); + + if (max->post_handshake_auth) + return GNUTLS_E_INT_RET_0; + else + return 0; +} diff --git a/lib/ext/post_handshake.h b/lib/ext/post_handshake.h new file mode 100644 index 0000000..7a1cc7a --- /dev/null +++ b/lib/ext/post_handshake.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_POST_HANDSHAKE_H +#define GNUTLS_LIB_EXT_POST_HANDSHAKE_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_post_handshake; + +#endif /* GNUTLS_LIB_EXT_POST_HANDSHAKE_H */ diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c new file mode 100644 index 0000000..8dff2b4 --- /dev/null +++ b/lib/ext/pre_shared_key.c @@ -0,0 +1,911 @@ +/* + * Copyright (C) 2017-2018 Free Software Foundation, Inc. + * Copyright (C) 2018 Red Hat, Inc. + * + * Author: Ander Juaristi, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "auth/psk.h" +#include "handshake.h" +#include "kx.h" +#include "secrets.h" +#include "tls13/anti_replay.h" +#include "tls13/psk_ext_parser.h" +#include "tls13/finished.h" +#include "tls13/session_ticket.h" +#include "auth/psk_passwd.h" +#include <ext/session_ticket.h> +#include <ext/pre_shared_key.h> +#include <assert.h> + +static int +compute_psk_from_ticket(const tls13_ticket_st *ticket, gnutls_datum_t *key) +{ + int ret; + + if (unlikely(ticket->prf == NULL || ticket->prf->output_size == 0)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + key->data = gnutls_malloc(ticket->prf->output_size); + if (!key->data) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + key->size = ticket->prf->output_size; + + ret = _tls13_expand_secret2(ticket->prf, + RESUMPTION_LABEL, sizeof(RESUMPTION_LABEL)-1, + ticket->nonce, ticket->nonce_size, + ticket->resumption_master_secret, + key->size, + key->data); + if (ret < 0) + gnutls_assert(); + + return ret; +} + +static int +compute_binder_key(const mac_entry_st *prf, + const uint8_t *key, size_t keylen, + bool resuming, + void *out) +{ + int ret; + const char ext_label[] = EXT_BINDER_LABEL; + const size_t ext_label_len = sizeof(ext_label) - 1; + const char res_label[] = RES_BINDER_LABEL; + const size_t res_label_len = sizeof(res_label) - 1; + const char *label = resuming ? res_label : ext_label; + size_t label_len = resuming ? res_label_len : ext_label_len; + uint8_t tmp_key[MAX_HASH_SIZE]; + + /* Compute HKDF-Extract(0, psk) */ + ret = _tls13_init_secret2(prf, key, keylen, tmp_key); + if (ret < 0) + return ret; + + /* Compute Derive-Secret(secret, label, transcript_hash) */ + ret = _tls13_derive_secret2(prf, label, label_len, + NULL, 0, tmp_key, out); + if (ret < 0) + return ret; + + return 0; +} + +static int +compute_psk_binder(gnutls_session_t session, + const mac_entry_st *prf, unsigned binders_length, + int exts_length, int ext_offset, + const gnutls_datum_t *psk, const gnutls_datum_t *client_hello, + bool resuming, void *out) +{ + int ret; + unsigned client_hello_pos, extensions_len_pos; + gnutls_buffer_st handshake_buf; + uint8_t binder_key[MAX_HASH_SIZE]; + + _gnutls_buffer_init(&handshake_buf); + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (session->internals.hsk_flags & HSK_HRR_RECEIVED) { + ret = gnutls_buffer_append_data(&handshake_buf, + (const void *) session->internals.handshake_hash_buffer.data, + session->internals.handshake_hash_buffer.length); + if (ret < 0) { + gnutls_assert(); + goto error; + } + } + + client_hello_pos = handshake_buf.length; + ret = gnutls_buffer_append_data(&handshake_buf, client_hello->data, + client_hello->size); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + /* This is a ClientHello message */ + handshake_buf.data[client_hello_pos] = GNUTLS_HANDSHAKE_CLIENT_HELLO; + + /* At this point we have not yet added the binders to the ClientHello, + * but we have to overwrite the size field, pretending as if binders + * of the correct length were present. + */ + _gnutls_write_uint24(handshake_buf.length - client_hello_pos + binders_length - 2, &handshake_buf.data[client_hello_pos + 1]); + _gnutls_write_uint16(handshake_buf.length - client_hello_pos + binders_length - ext_offset, + &handshake_buf.data[client_hello_pos + ext_offset]); + extensions_len_pos = handshake_buf.length - client_hello_pos - exts_length - 2; + _gnutls_write_uint16(exts_length + binders_length + 2, + &handshake_buf.data[client_hello_pos + extensions_len_pos]); + } else { + if (session->internals.hsk_flags & HSK_HRR_SENT) { + if (unlikely(session->internals.handshake_hash_buffer.length <= client_hello->size)) { + ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + goto error; + } + + ret = gnutls_buffer_append_data(&handshake_buf, + session->internals.handshake_hash_buffer.data, + session->internals.handshake_hash_buffer.length - client_hello->size); + if (ret < 0) { + gnutls_assert(); + goto error; + } + } + + if (unlikely(client_hello->size <= binders_length)) { + ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + goto error; + } + + ret = gnutls_buffer_append_data(&handshake_buf, + (const void *) client_hello->data, + client_hello->size - binders_length); + if (ret < 0) { + gnutls_assert(); + goto error; + } + } + + ret = compute_binder_key(prf, + psk->data, psk->size, resuming, + binder_key); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = _gnutls13_compute_finished(prf, binder_key, + &handshake_buf, + out); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = 0; +error: + _gnutls_buffer_clear(&handshake_buf); + return ret; +} + +static int +generate_early_secrets(gnutls_session_t session, + const mac_entry_st *prf) +{ + int ret; + + ret = _tls13_derive_secret2(prf, EARLY_TRAFFIC_LABEL, sizeof(EARLY_TRAFFIC_LABEL)-1, + session->internals.handshake_hash_buffer.data, + session->internals.handshake_hash_buffer_client_hello_len, + session->key.proto.tls13.temp_secret, + session->key.proto.tls13.e_ckey); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_call_keylog_func(session, "CLIENT_EARLY_TRAFFIC_SECRET", + session->key.proto.tls13.e_ckey, + prf->output_size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _tls13_derive_secret2(prf, EARLY_EXPORTER_MASTER_LABEL, sizeof(EARLY_EXPORTER_MASTER_LABEL)-1, + session->internals.handshake_hash_buffer.data, + session->internals.handshake_hash_buffer_client_hello_len, + session->key.proto.tls13.temp_secret, + session->key.proto.tls13.ap_expkey); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_call_keylog_func(session, "EARLY_EXPORTER_SECRET", + session->key.proto.tls13.ap_expkey, + prf->output_size); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + +/* Calculate TLS 1.3 Early Secret and the derived secrets from the + * selected PSK. */ +int +_gnutls_generate_early_secrets_for_psk(gnutls_session_t session) +{ + const uint8_t *psk; + size_t psk_size; + const mac_entry_st *prf; + int ret; + + psk = session->key.binders[0].psk.data; + psk_size = session->key.binders[0].psk.size; + prf = session->key.binders[0].prf; + + if (unlikely(psk_size == 0)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = _tls13_init_secret2(prf, psk, psk_size, + session->key.proto.tls13.temp_secret); + if (ret < 0) + return gnutls_assert_val(ret); + + session->key.proto.tls13.temp_secret_size = prf->output_size; + + ret = generate_early_secrets(session, session->key.binders[0].prf); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + +static int +client_send_params(gnutls_session_t session, + gnutls_buffer_t extdata, + const gnutls_psk_client_credentials_t cred) +{ + int ret, ext_offset = 0; + uint8_t binder_value[MAX_HASH_SIZE]; + size_t spos; + gnutls_datum_t username = {NULL, 0}; + gnutls_datum_t user_key = {NULL, 0}, rkey = {NULL, 0}; + unsigned client_hello_len; + unsigned next_idx; + const mac_entry_st *prf_res = NULL; + const mac_entry_st *prf_psk = NULL; + struct timespec cur_time; + uint32_t ticket_age, ob_ticket_age; + int free_username = 0; + psk_auth_info_t info = NULL; + unsigned psk_id_len = 0; + unsigned binders_len, binders_pos; + tls13_ticket_st *ticket = &session->internals.tls13_ticket; + + if (((session->internals.flags & GNUTLS_NO_TICKETS) || + session->internals.tls13_ticket.ticket.data == NULL) && + (!cred || !_gnutls_have_psk_credentials(cred, session))) { + + return 0; + } + + binders_len = 0; + + /* placeholder to be filled later */ + spos = extdata->length; + ret = _gnutls_buffer_append_prefix(extdata, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + /* First, let's see if we have a session ticket to send */ + if (!(session->internals.flags & GNUTLS_NO_TICKETS) && + ticket->ticket.data != NULL) { + + /* We found a session ticket */ + if (unlikely(ticket->prf == NULL)) { + tls13_ticket_deinit(ticket); + ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + goto cleanup; + } + + prf_res = ticket->prf; + + gnutls_gettime(&cur_time); + if (unlikely(_gnutls_timespec_cmp(&cur_time, + &ticket->arrival_time) < 0)) { + gnutls_assert(); + tls13_ticket_deinit(ticket); + goto ignore_ticket; + } + + /* Check whether the ticket is stale */ + ticket_age = timespec_sub_ms(&cur_time, &ticket->arrival_time); + if (ticket_age / 1000 > ticket->lifetime) { + tls13_ticket_deinit(ticket); + goto ignore_ticket; + } + + ret = compute_psk_from_ticket(ticket, &rkey); + if (ret < 0) { + tls13_ticket_deinit(ticket); + goto ignore_ticket; + } + + /* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */ + ob_ticket_age = ticket_age + ticket->age_add; + + if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16, + ticket->ticket.data, + ticket->ticket.size)) < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Now append the obfuscated ticket age */ + if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) { + gnutls_assert(); + goto cleanup; + } + + psk_id_len += 6 + ticket->ticket.size; + binders_len += 1 + _gnutls_mac_get_algo_len(prf_res); + } + + ignore_ticket: + if (cred && _gnutls_have_psk_credentials(cred, session)) { + gnutls_datum_t tkey; + + if (cred->binder_algo == NULL) { + gnutls_assert(); + ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + goto cleanup; + } + + prf_psk = cred->binder_algo; + + ret = _gnutls_find_psk_key(session, cred, &username, &tkey, &free_username); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + if (username.size == 0 || username.size > UINT16_MAX) { + ret = gnutls_assert_val(GNUTLS_E_INVALID_PASSWORD); + goto cleanup; + } + + if (!free_username) { + /* we need to copy the key */ + ret = _gnutls_set_datum(&user_key, tkey.data, tkey.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } else { + user_key.data = tkey.data; + user_key.size = tkey.size; + } + + ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + assert(info != NULL); + + ret = _gnutls_copy_psk_username(info, username); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + + if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16, + username.data, + username.size)) < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Now append the obfuscated ticket age */ + if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) { + gnutls_assert(); + goto cleanup; + } + + psk_id_len += 6 + username.size; + binders_len += 1 + _gnutls_mac_get_algo_len(prf_psk); + } + + /* if no tickets or identities to be sent */ + if (psk_id_len == 0) { + /* reset extensions buffer */ + extdata->length = spos; + return 0; + } + + _gnutls_write_uint16(psk_id_len, &extdata->data[spos]); + + binders_pos = extdata->length-spos; + ext_offset = _gnutls_ext_get_extensions_offset(session); + + /* Compute the binders. extdata->data points to the start + * of this client hello. */ + assert(extdata->length >= sizeof(mbuffer_st)); + assert(ext_offset >= (ssize_t)sizeof(mbuffer_st)); + ext_offset -= sizeof(mbuffer_st); + client_hello_len = extdata->length-sizeof(mbuffer_st); + + next_idx = 0; + + ret = _gnutls_buffer_append_prefix(extdata, 16, binders_len); + if (ret < 0) { + gnutls_assert_val(ret); + goto cleanup; + } + + if (prf_res && rkey.size > 0) { + gnutls_datum_t client_hello; + + client_hello.data = extdata->data+sizeof(mbuffer_st); + client_hello.size = client_hello_len; + + ret = compute_psk_binder(session, prf_res, + binders_len, binders_pos, + ext_offset, &rkey, &client_hello, 1, + binder_value); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Associate the selected pre-shared key with the session */ + gnutls_free(session->key.binders[next_idx].psk.data); + session->key.binders[next_idx].psk.data = rkey.data; + session->key.binders[next_idx].psk.size = rkey.size; + rkey.data = NULL; + + session->key.binders[next_idx].prf = prf_res; + session->key.binders[next_idx].resumption = 1; + session->key.binders[next_idx].idx = next_idx; + + _gnutls_handshake_log("EXT[%p]: sent PSK resumption identity (%d)\n", session, next_idx); + + next_idx++; + + /* Add the binder */ + ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_res->output_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT; + } + + if (prf_psk && user_key.size > 0 && info) { + gnutls_datum_t client_hello; + + client_hello.data = extdata->data+sizeof(mbuffer_st); + client_hello.size = client_hello_len; + + ret = compute_psk_binder(session, prf_psk, + binders_len, binders_pos, + ext_offset, &user_key, &client_hello, 0, + binder_value); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Associate the selected pre-shared key with the session */ + gnutls_free(session->key.binders[next_idx].psk.data); + session->key.binders[next_idx].psk.data = user_key.data; + session->key.binders[next_idx].psk.size = user_key.size; + user_key.data = NULL; + + session->key.binders[next_idx].prf = prf_psk; + session->key.binders[next_idx].resumption = 0; + session->key.binders[next_idx].idx = next_idx; + + _gnutls_handshake_log("EXT[%p]: sent PSK identity '%s' (%d)\n", session, info->username, next_idx); + + next_idx++; + + /* Add the binder */ + ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_psk->output_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + ret = 0; + +cleanup: + if (free_username) + _gnutls_free_datum(&username); + + _gnutls_free_temp_key_datum(&user_key); + _gnutls_free_temp_key_datum(&rkey); + + return ret; +} + +static int +server_send_params(gnutls_session_t session, gnutls_buffer_t extdata) +{ + int ret; + + if (!(session->internals.hsk_flags & HSK_PSK_SELECTED)) + return 0; + + ret = _gnutls_buffer_append_prefix(extdata, 16, + session->key.binders[0].idx); + if (ret < 0) + return gnutls_assert_val(ret); + + return 2; +} + +static int server_recv_params(gnutls_session_t session, + const unsigned char *data, size_t len, + const gnutls_psk_server_credentials_t pskcred) +{ + int ret; + const mac_entry_st *prf; + gnutls_datum_t full_client_hello; + uint8_t binder_value[MAX_HASH_SIZE]; + uint16_t psk_index, i; + gnutls_datum_t binder_recvd = { NULL, 0 }; + gnutls_datum_t key = {NULL, 0}; + psk_ext_parser_st psk_parser; + psk_ext_iter_st psk_iter; + struct psk_st psk; + psk_auth_info_t info; + tls13_ticket_st ticket_data; + /* These values should be set properly when session ticket is accepted. */ + uint32_t ticket_age = UINT32_MAX; + struct timespec ticket_creation_time = { 0, 0 }; + bool resuming; + bool refuse_early_data = false; + + ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len); + if (ret < 0) { + /* No PSKs advertised by client */ + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + return 0; + return gnutls_assert_val(ret); + } + + _gnutls13_psk_ext_iter_init(&psk_iter, &psk_parser); + for (psk_index = 0; ; psk_index++) { + ret = _gnutls13_psk_ext_iter_next_identity(&psk_iter, &psk); + if (ret < 0) { + /* We couldn't find any usable PSK */ + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + return 0; + return gnutls_assert_val(ret); + } + + /* This will unpack the session ticket if it is well + * formed and has the expected name */ + if (!(session->internals.flags & GNUTLS_NO_TICKETS) && + _gnutls13_unpack_session_ticket(session, &psk.identity, &ticket_data) == 0) { + prf = ticket_data.prf; + + session->internals.resumption_requested = 1; + + /* Check whether ticket is stale or not */ + ticket_age = psk.ob_ticket_age - ticket_data.age_add; + if (ticket_age / 1000 > ticket_data.lifetime) { + gnutls_assert(); + tls13_ticket_deinit(&ticket_data); + continue; + } + + ret = compute_psk_from_ticket(&ticket_data, &key); + if (ret < 0) { + gnutls_assert(); + tls13_ticket_deinit(&ticket_data); + continue; + } + + memcpy(&ticket_creation_time, + &ticket_data.creation_time, + sizeof(struct timespec)); + + tls13_ticket_deinit(&ticket_data); + + resuming = 1; + break; + } else if (pskcred && + psk.ob_ticket_age == 0 && + psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) { + prf = pskcred->binder_algo; + + /* this fails only on configuration errors; as such we always + * return its error code in that case */ + ret = _gnutls_psk_pwd_find_entry(session, (char *) psk.identity.data, psk.identity.size, &key); + if (ret < 0) + return gnutls_assert_val(ret); + + resuming = 0; + break; + } + } + + _gnutls13_psk_ext_iter_init(&psk_iter, &psk_parser); + for (i = 0; i <= psk_index; i++) { + ret = _gnutls13_psk_ext_iter_next_binder(&psk_iter, &binder_recvd); + if (ret < 0) { + gnutls_assert(); + /* We couldn't extract binder */ + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + goto fail; + } + } + + /* Get full ClientHello */ + if (!_gnutls_ext_get_full_client_hello(session, &full_client_hello)) { + ret = GNUTLS_E_INTERNAL_ERROR; + gnutls_assert(); + goto fail; + } + + /* Compute the binder value for this PSK */ + ret = compute_psk_binder(session, prf, psk_parser.binders_len+2, 0, 0, + &key, &full_client_hello, resuming, + binder_value); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + if (_gnutls_mac_get_algo_len(prf) != binder_recvd.size || + gnutls_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) { + gnutls_assert(); + ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + goto fail; + } + + if (session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK) + _gnutls_handshake_log("EXT[%p]: selected DHE-PSK mode\n", session); + else { + reset_cand_groups(session); + _gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session); + } + + /* save the username in psk_auth_info to make it available + * using gnutls_psk_server_get_username() */ + if (!resuming) { + assert(psk.identity.size <= MAX_USERNAME_SIZE); + + ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + assert(info != NULL); + + ret = _gnutls_copy_psk_username(info, psk.identity); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + _gnutls_handshake_log("EXT[%p]: selected PSK identity: %s (%d)\n", session, info->username, psk_index); + + /* We currently only support early data in resuming connection, + * due to lack of API function to associate encryption + * parameters with external PSK. + */ + refuse_early_data = true; + } else { + if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) { + if (session->internals.anti_replay) { + ret = _gnutls_anti_replay_check(session->internals.anti_replay, + ticket_age, + &ticket_creation_time, + &binder_recvd); + if (ret < 0) { + refuse_early_data = true; + _gnutls_handshake_log("EXT[%p]: replay detected; rejecting early data\n", + session); + } + } else { + refuse_early_data = true; + _gnutls_handshake_log("EXT[%p]: anti-replay is not enabled; rejecting early data\n", + session); + } + } + + session->internals.resumed = true; + _gnutls_handshake_log("EXT[%p]: selected resumption PSK identity (%d)\n", session, psk_index); + } + + session->internals.hsk_flags |= HSK_PSK_SELECTED; + + if ((session->internals.flags & GNUTLS_ENABLE_EARLY_DATA) && + (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) && + !refuse_early_data && + !(session->internals.hsk_flags & HSK_HRR_SENT)) { + session->internals.hsk_flags |= HSK_EARLY_DATA_ACCEPTED; + _gnutls_handshake_log("EXT[%p]: early data accepted\n", + session); + } + + /* Reference the selected pre-shared key */ + session->key.binders[0].psk.data = key.data; + session->key.binders[0].psk.size = key.size; + + session->key.binders[0].idx = psk_index; + session->key.binders[0].prf = prf; + session->key.binders[0].resumption = resuming; + + ret = _gnutls_generate_early_secrets_for_psk(session); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + return 0; + + fail: + gnutls_free(key.data); + return ret; +} + +/* + * Return values for this function: + * - 0 : Not applicable. + * - >0 : Ok. Return size of extension data. + * - GNUTLS_E_INT_RET_0 : Size of extension data is zero. + * - <0 : There's been an error. + * + * In the client, generates the PskIdentity and PskBinderEntry messages. + * + * PskIdentity identities<7..2^16-1>; + * PskBinderEntry binders<33..2^16-1>; + * + * struct { + * opaque identity<1..2^16-1>; + * uint32 obfuscated_ticket_age; + * } PskIdentity; + * + * opaque PskBinderEntry<32..255>; + * + * The server sends the selected identity, which is a zero-based index + * of the PSKs offered by the client: + * + * struct { + * uint16 selected_identity; + * } PreSharedKeyExtension; + */ +static int _gnutls_psk_send_params(gnutls_session_t session, + gnutls_buffer_t extdata) +{ + gnutls_psk_client_credentials_t cred = NULL; + const version_entry_st *vers; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + vers = _gnutls_version_max(session); + + if (!vers || !vers->tls13_sem) + return 0; + + if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) { + cred = (gnutls_psk_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + } + + if ((session->internals.flags & GNUTLS_NO_TICKETS) && !session->internals.priorities->have_psk) + return 0; + + return client_send_params(session, extdata, cred); + } else { + vers = get_version(session); + + if (!vers || !vers->tls13_sem) + return 0; + + if ((session->internals.flags & GNUTLS_NO_TICKETS) && !session->internals.priorities->have_psk) + return 0; + + if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED) + return server_send_params(session, extdata); + else + return 0; + } +} + +static void swap_binders(gnutls_session_t session) +{ + struct binder_data_st tmp; + + memcpy(&tmp, &session->key.binders[0], sizeof(struct binder_data_st)); + memcpy(&session->key.binders[0], &session->key.binders[1], sizeof(struct binder_data_st)); + memcpy(&session->key.binders[1], &tmp, sizeof(struct binder_data_st)); +} + +/* + * Return values for this function: + * - 0 : Not applicable. + * - >0 : Ok. Return size of extension data. + * - <0 : There's been an error. + */ +static int _gnutls_psk_recv_params(gnutls_session_t session, + const unsigned char *data, size_t len) +{ + unsigned i; + gnutls_psk_server_credentials_t pskcred; + const version_entry_st *vers = get_version(session); + int ret; + + if (!vers || !vers->tls13_sem) + return 0; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) { + uint16_t selected_identity = _gnutls_read_uint16(data); + + for (i=0;i<sizeof(session->key.binders)/sizeof(session->key.binders[0]);i++) { + if (session->key.binders[i].prf != NULL && session->key.binders[i].idx == selected_identity) { + if (session->key.binders[i].resumption) { + session->internals.resumed = true; + _gnutls_handshake_log("EXT[%p]: selected PSK-resumption mode\n", session); + } else { + _gnutls_handshake_log("EXT[%p]: selected PSK mode\n", session); + } + + /* different PSK is selected, than the one we calculated early secrets */ + if (i != 0) { + /* ensure that selected binder is set on (our) index zero */ + swap_binders(session); + + ret = _gnutls_generate_early_secrets_for_psk(session); + if (ret < 0) + return gnutls_assert_val(ret); + } + session->internals.hsk_flags |= HSK_PSK_SELECTED; + } + } + + return 0; + } else { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } + } else { + if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED) { + if (session->internals.hsk_flags & HSK_PSK_KE_MODE_INVALID) { + /* We received a "psk_ke_modes" extension, but with a value we don't support */ + return 0; + } + + pskcred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + /* If there are no PSK credentials, this extension is not applicable, + * so we return zero. */ + if (pskcred == NULL && (session->internals.flags & GNUTLS_NO_TICKETS)) + return 0; + + return server_recv_params(session, data, len, pskcred); + } else { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + } + } +} + +const hello_ext_entry_st ext_mod_pre_shared_key = { + .name = "Pre Shared Key", + .tls_id = PRE_SHARED_KEY_TLS_ID, + .gid = GNUTLS_EXTENSION_PRE_SHARED_KEY, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO, + .send_func = _gnutls_psk_send_params, + .recv_func = _gnutls_psk_recv_params +}; diff --git a/lib/ext/pre_shared_key.h b/lib/ext/pre_shared_key.h new file mode 100644 index 0000000..f1ea62c --- /dev/null +++ b/lib/ext/pre_shared_key.h @@ -0,0 +1,23 @@ +#ifndef GNUTLS_LIB_EXT_PRE_SHARED_KEY_H +#define GNUTLS_LIB_EXT_PRE_SHARED_KEY_H + +#include "auth/psk.h" +#include <hello_ext.h> +#include "tls13/session_ticket.h" + +#define PRE_SHARED_KEY_TLS_ID 41 + +extern const hello_ext_entry_st ext_mod_pre_shared_key; + +inline static +unsigned _gnutls_have_psk_credentials(const gnutls_psk_client_credentials_t cred, gnutls_session_t session) +{ + if ((cred->get_function || cred->username.data) && session->internals.priorities->have_psk) + return 1; + else + return 0; +} + +int _gnutls_generate_early_secrets_for_psk(gnutls_session_t session); + +#endif /* GNUTLS_LIB_EXT_PRE_SHARED_KEY_H */ diff --git a/lib/ext/psk_ke_modes.c b/lib/ext/psk_ke_modes.c new file mode 100644 index 0000000..cc28536 --- /dev/null +++ b/lib/ext/psk_ke_modes.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2017 Free Software Foundation, Inc. + * + * Author: Ander Juaristi + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "ext/psk_ke_modes.h" +#include "ext/pre_shared_key.h" +#include <assert.h> + +#define PSK_KE 0 +#define PSK_DHE_KE 1 + +static int +psk_ke_modes_send_params(gnutls_session_t session, + gnutls_buffer_t extdata) +{ + int ret; + const version_entry_st *vers; + uint8_t data[2]; + unsigned pos, i; + unsigned have_dhpsk = 0; + unsigned have_psk = 0; + + /* Server doesn't send psk_key_exchange_modes */ + if (session->security_parameters.entity == GNUTLS_SERVER) + return 0; + + /* If session ticket is disabled and no PSK key exchange is + * enabled, don't send the extension */ + if ((session->internals.flags & GNUTLS_NO_TICKETS) && + !session->internals.priorities->have_psk) + return 0; + + vers = _gnutls_version_max(session); + if (!vers || !vers->tls13_sem) + return 0; + + /* We send the list prioritized according to our preferences as a convention + * (used throughout the protocol), even if the protocol doesn't mandate that + * for this particular message. That way we can keep the TLS 1.2 semantics/ + * prioritization when negotiating PSK or DHE-PSK. Receiving servers would + * very likely respect our prioritization if they parse the message serially. */ + pos = 0; + for (i=0;i<session->internals.priorities->_kx.num_priorities;i++) { + if (session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_PSK && !have_psk) { + assert(pos <= 1); + data[pos++] = PSK_KE; + session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; + have_psk = 1; + } else if ((session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_DHE_PSK || + session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_ECDHE_PSK) && !have_dhpsk) { + assert(pos <= 1); + data[pos++] = PSK_DHE_KE; + session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; + have_dhpsk = 1; + } + + if (have_psk && have_dhpsk) + break; + } + + /* For session resumption we need to send at least one */ + if (pos == 0) { + if (session->internals.flags & GNUTLS_NO_TICKETS) + return 0; + + data[pos++] = PSK_DHE_KE; + data[pos++] = PSK_KE; + session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; + session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; + } + + ret = _gnutls_buffer_append_data_prefix(extdata, 8, data, pos); + if (ret < 0) + return gnutls_assert_val(ret); + + session->internals.hsk_flags |= HSK_PSK_KE_MODES_SENT; + + return 0; +} + +#define MAX_POS INT_MAX + +/* + * Since we only support ECDHE-authenticated PSKs, the server + * just verifies that a "psk_key_exchange_modes" extension was received, + * and that it contains the value one. + */ +static int +psk_ke_modes_recv_params(gnutls_session_t session, + const unsigned char *data, size_t len) +{ + uint8_t ke_modes_len; + const version_entry_st *vers = get_version(session); + gnutls_psk_server_credentials_t cred; + int dhpsk_pos = MAX_POS; + int psk_pos = MAX_POS; + int cli_psk_pos = MAX_POS; + int cli_dhpsk_pos = MAX_POS; + unsigned i; + + /* Client doesn't receive psk_key_exchange_modes */ + if (session->security_parameters.entity == GNUTLS_CLIENT) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + + /* we set hsk_flags to HSK_PSK_KE_MODE_INVALID on failure to ensure that + * when we parse the pre-shared key extension we detect PSK_KE_MODES as + * received. */ + if (!vers || !vers->tls13_sem) { + session->internals.hsk_flags |= HSK_PSK_KE_MODE_INVALID; + return gnutls_assert_val(0); + } + + cred = (gnutls_psk_server_credentials_t)_gnutls_get_cred(session, GNUTLS_CRD_PSK); + if (cred == NULL && (session->internals.flags & GNUTLS_NO_TICKETS)) { + session->internals.hsk_flags |= HSK_PSK_KE_MODE_INVALID; + return gnutls_assert_val(0); + } + + DECR_LEN(len, 1); + ke_modes_len = *(data++); + + for (i=0;i<session->internals.priorities->_kx.num_priorities;i++) { + if (session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_PSK && psk_pos == MAX_POS) { + psk_pos = i; + } else if ((session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_DHE_PSK || + session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_ECDHE_PSK) && + dhpsk_pos == MAX_POS) { + dhpsk_pos = i; + } + + if (dhpsk_pos != MAX_POS && psk_pos != MAX_POS) + break; + } + + if (psk_pos == MAX_POS && dhpsk_pos == MAX_POS) { + if (!(session->internals.flags & GNUTLS_NO_TICKETS)) + dhpsk_pos = 0; + else if (session->internals.priorities->groups.size == 0) + return gnutls_assert_val(0); + } + + for (i=0;i<ke_modes_len;i++) { + DECR_LEN(len, 1); + if (data[i] == PSK_DHE_KE) + cli_dhpsk_pos = i; + else if (data[i] == PSK_KE) + cli_psk_pos = i; + + _gnutls_handshake_log("EXT[%p]: PSK KE mode %.2x received\n", + session, (unsigned)data[i]); + if (cli_psk_pos != MAX_POS && cli_dhpsk_pos != MAX_POS) + break; + } + + if (session->internals.priorities->server_precedence) { + if (dhpsk_pos != MAX_POS && cli_dhpsk_pos != MAX_POS && (dhpsk_pos < psk_pos || cli_psk_pos == MAX_POS)) + session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; + else if (psk_pos != MAX_POS && cli_psk_pos != MAX_POS && (psk_pos < dhpsk_pos || cli_dhpsk_pos == MAX_POS)) + session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; + } else { + if (dhpsk_pos != MAX_POS && cli_dhpsk_pos != MAX_POS && (cli_dhpsk_pos < cli_psk_pos || psk_pos == MAX_POS)) + session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; + else if (psk_pos != MAX_POS && cli_psk_pos != MAX_POS && (cli_psk_pos < cli_dhpsk_pos || dhpsk_pos == MAX_POS)) + session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; + } + + if ((session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK) || + (session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK)) { + + return 0; + } else { + session->internals.hsk_flags |= HSK_PSK_KE_MODE_INVALID; + return gnutls_assert_val(0); + } +} + +const hello_ext_entry_st ext_mod_psk_ke_modes = { + .name = "PSK Key Exchange Modes", + .tls_id = 45, + .gid = GNUTLS_EXTENSION_PSK_KE_MODES, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO, + .send_func = psk_ke_modes_send_params, + .recv_func = psk_ke_modes_recv_params +}; diff --git a/lib/ext/psk_ke_modes.h b/lib/ext/psk_ke_modes.h new file mode 100644 index 0000000..56876a9 --- /dev/null +++ b/lib/ext/psk_ke_modes.h @@ -0,0 +1,8 @@ +#ifndef GNUTLS_LIB_EXT_PSK_KE_MODES_H +#define GNUTLS_LIB_EXT_PSK_KE_MODES_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_psk_ke_modes; + +#endif /* GNUTLS_LIB_EXT_PSK_KE_MODES_H */ diff --git a/lib/ext/record_size_limit.c b/lib/ext/record_size_limit.c new file mode 100644 index 0000000..9398b18 --- /dev/null +++ b/lib/ext/record_size_limit.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2018 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Record Size Limit TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <hello_ext.h> +#include <ext/record_size_limit.h> + +static int _gnutls_record_size_limit_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_record_size_limit_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_record_size_limit = { + .name = "Record Size Limit", + .tls_id = 28, + .gid = GNUTLS_EXTENSION_RECORD_SIZE_LIMIT, + .client_parse_point = GNUTLS_EXT_MANDATORY, + .server_parse_point = GNUTLS_EXT_MANDATORY, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_record_size_limit_recv_params, + .send_func = _gnutls_record_size_limit_send_params +}; + +static int +_gnutls_record_size_limit_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + ssize_t new_size; + const version_entry_st *vers; + + DECR_LEN(data_size, 2); + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + new_size = _gnutls_read_uint16(data); + + /* protocol error */ + if (new_size < 64) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + session->internals.hsk_flags |= HSK_RECORD_SIZE_LIMIT_RECEIVED; + + /* we do not want to accept sizes outside of our supported range */ + if (new_size < + (session->internals.allow_small_records ? + MIN_RECORD_SIZE_SMALL : MIN_RECORD_SIZE)) { + /* for server, reject it by omitting the extension in the reply */ + if (session->security_parameters.entity == GNUTLS_SERVER) { + _gnutls_handshake_log("EXT[%p]: client requested too small record_size_limit %u; ignoring\n", + session, (unsigned)new_size); + return gnutls_assert_val(0); + } else { + _gnutls_handshake_log("EXT[%p]: server requested too small record_size_limit %u; closing the connection\n", + session, (unsigned)new_size); + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + } + + session->internals.hsk_flags |= HSK_RECORD_SIZE_LIMIT_NEGOTIATED; + + /* client uses the reception of this extension as an + * indication of the request was accepted by the server */ + if (session->security_parameters.entity == GNUTLS_CLIENT) + session->security_parameters.max_record_recv_size = + session->security_parameters.max_user_record_recv_size; + + _gnutls_handshake_log("EXT[%p]: record_size_limit %u negotiated\n", + session, (unsigned)new_size); + + /* subtract 1 octet for content type */ + vers = get_version(session); + if (unlikely(vers == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + session->security_parameters.max_record_send_size = + MIN(new_size - vers->tls13_sem, + session->security_parameters.max_user_record_send_size); + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_record_size_limit_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + int ret; + uint16_t send_size; + + assert(session->security_parameters.max_user_record_recv_size >= 64 && + session->security_parameters.max_user_record_recv_size <= + DEFAULT_MAX_RECORD_SIZE); + + send_size = session->security_parameters.max_user_record_recv_size; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + const version_entry_st *vers; + + /* if we had received the extension and rejected, don't send it */ + if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_RECEIVED && + !(session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED)) + return gnutls_assert_val(0); + + /* add 1 octet for content type */ + vers = get_version(session); + if (unlikely(vers == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + session->security_parameters.max_record_recv_size = + send_size; + + send_size += vers->tls13_sem; + } else { + const version_entry_st *vers; + + /* add 1 octet for content type */ + vers = _gnutls_version_max(session); + if (unlikely(vers == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + send_size += vers->tls13_sem; + } + + ret = _gnutls_buffer_append_prefix(extdata, 16, send_size); + if (ret < 0) + return gnutls_assert_val(ret); + + session->internals.hsk_flags |= HSK_RECORD_SIZE_LIMIT_SENT; + + return 2; +} diff --git a/lib/ext/record_size_limit.h b/lib/ext/record_size_limit.h new file mode 100644 index 0000000..da7cade --- /dev/null +++ b/lib/ext/record_size_limit.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_RECORD_SIZE_LIMIT_H +#define GNUTLS_LIB_EXT_RECORD_SIZE_LIMIT_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_record_size_limit; + +#endif /* GNUTLS_LIB_EXT_RECORD_SIZE_LIMIT_H */ diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c new file mode 100644 index 0000000..f76895d --- /dev/null +++ b/lib/ext/safe_renegotiation.c @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2009-2012 Free Software Foundation, Inc. + * + * Author: Steve Dispensa (<dispensa@phonefactor.com>) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include <ext/safe_renegotiation.h> +#include "errors.h" + + +static int _gnutls_sr_recv_params(gnutls_session_t state, + const uint8_t * data, size_t data_size); +static int _gnutls_sr_send_params(gnutls_session_t state, + gnutls_buffer_st *); +static void _gnutls_sr_deinit_data(gnutls_ext_priv_data_t priv); + +const hello_ext_entry_st ext_mod_sr = { + .name = "Safe Renegotiation", + .tls_id = 65281, + .gid = GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .client_parse_point = GNUTLS_EXT_MANDATORY, + .server_parse_point = GNUTLS_EXT_MANDATORY, + .recv_func = _gnutls_sr_recv_params, + .send_func = _gnutls_sr_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = _gnutls_sr_deinit_data, + .cannot_be_overriden = 1 +}; + +int +_gnutls_ext_sr_finished(gnutls_session_t session, void *vdata, + size_t vdata_size, int dir) +{ + int ret; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + if (session->internals.priorities->sr == SR_DISABLED || + session->internals.priorities->no_extensions) { + return 0; + } + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret < 0) { + gnutls_assert(); + /* if a client didn't advertise safe renegotiation, we treat + * it as disabled. */ + if (session->security_parameters.entity == GNUTLS_SERVER) + return 0; + return ret; + } + priv = epriv; + + /* Save data for safe renegotiation. + */ + if (vdata_size > MAX_VERIFY_DATA_SIZE) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if ((session->security_parameters.entity == GNUTLS_CLIENT + && dir == 0) + || (session->security_parameters.entity == GNUTLS_SERVER + && dir == 1)) { + priv->client_verify_data_len = vdata_size; + memcpy(priv->client_verify_data, vdata, vdata_size); + } else { + priv->server_verify_data_len = vdata_size; + memcpy(priv->server_verify_data, vdata, vdata_size); + } + + return 0; +} + +int _gnutls_ext_sr_verify(gnutls_session_t session) +{ + int ret; + sr_ext_st *priv = NULL; + gnutls_ext_priv_data_t epriv; + + if (session->internals.priorities->sr == SR_DISABLED) { + gnutls_assert(); + return 0; + } + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret >= 0) + priv = epriv; + + /* Safe renegotiation */ + + if (priv && priv->safe_renegotiation_received) { + if ((priv->ri_extension_data_len < + priv->client_verify_data_len) + || + (memcmp + (priv->ri_extension_data, priv->client_verify_data, + priv->client_verify_data_len))) { + gnutls_assert(); + _gnutls_handshake_log + ("HSK[%p]: Safe renegotiation failed [1]\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if ((priv->ri_extension_data_len != + priv->client_verify_data_len + + priv->server_verify_data_len) + || memcmp(priv->ri_extension_data + + priv->client_verify_data_len, + priv->server_verify_data, + priv->server_verify_data_len) != 0) { + gnutls_assert(); + _gnutls_handshake_log + ("HSK[%p]: Safe renegotiation failed [2]\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + } else { /* Make sure there are 0 extra bytes */ + + if (priv->ri_extension_data_len != + priv->client_verify_data_len) { + gnutls_assert(); + _gnutls_handshake_log + ("HSK[%p]: Safe renegotiation failed [3]\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + } + + _gnutls_handshake_log + ("HSK[%p]: Safe renegotiation succeeded\n", session); + } else { /* safe renegotiation not received... */ + + if (priv && priv->connection_using_safe_renegotiation) { + gnutls_assert(); + _gnutls_handshake_log + ("HSK[%p]: Peer previously asked for safe renegotiation\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + + /* Clients can't tell if it's an initial negotiation */ + if (session->internals.initial_negotiation_completed) { + if (session->internals.priorities->sr < SR_PARTIAL) { + _gnutls_handshake_log + ("HSK[%p]: Allowing unsafe (re)negotiation\n", + session); + } else { + gnutls_assert(); + _gnutls_handshake_log + ("HSK[%p]: Denying unsafe (re)negotiation\n", + session); + return + GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED; + } + } else { + if (session->internals.priorities->sr < SR_SAFE) { + _gnutls_handshake_log + ("HSK[%p]: Allowing unsafe initial negotiation\n", + session); + } else { + gnutls_assert(); + _gnutls_handshake_log + ("HSK[%p]: Denying unsafe initial negotiation\n", + session); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + } + } + + return 0; +} + +/* if a server received the special ciphersuite. + */ +int _gnutls_ext_sr_recv_cs(gnutls_session_t session) +{ + int ret, set = 0; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret < 0) { + set = 1; + } + + if (set != 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + } else + priv = epriv; + + priv->safe_renegotiation_received = 1; + priv->connection_using_safe_renegotiation = 1; + _gnutls_hello_ext_save_sr(session); + + if (set != 0) + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + epriv); + + return 0; +} + +int _gnutls_ext_sr_send_cs(gnutls_session_t session) +{ + int ret, set = 0; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret < 0) { + set = 1; + } + + if (set != 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + epriv); + } + + return 0; +} + +static int +_gnutls_sr_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + unsigned int len; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int set = 0, ret; + + if (data_size == 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + len = data[0]; + DECR_LEN(data_size, + len + 1 /* count the first byte and payload */ ); + + if (session->internals.priorities->sr == SR_DISABLED) { + gnutls_assert(); + return 0; + } + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret < 0 + && session->security_parameters.entity == GNUTLS_SERVER) { + set = 1; + } else if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (set != 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + epriv); + } else { + priv = epriv; + } + + /* It is not legal to receive this extension on a renegotiation and + * not receive it on the initial negotiation. + */ + if (session->internals.initial_negotiation_completed != 0 && + priv->connection_using_safe_renegotiation == 0) { + gnutls_assert(); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + + if (len > sizeof(priv->ri_extension_data)) { + gnutls_assert(); + return GNUTLS_E_SAFE_RENEGOTIATION_FAILED; + } + + if (len > 0) + memcpy(priv->ri_extension_data, &data[1], len); + priv->ri_extension_data_len = len; + + /* "safe renegotiation received" means on *this* handshake; "connection using + * safe renegotiation" means that the initial hello received on the connection + * indicated safe renegotiation. + */ + priv->safe_renegotiation_received = 1; + priv->connection_using_safe_renegotiation = 1; + + return 0; +} + +static int +_gnutls_sr_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + /* The format of this extension is a one-byte length of verify data followed + * by the verify data itself. Note that the length byte does not include + * itself; IOW, empty verify data is represented as a length of 0. That means + * the minimum extension is one byte: 0x00. + */ + sr_ext_st *priv; + int ret, set = 0, len; + gnutls_ext_priv_data_t epriv; + size_t init_length = extdata->length; + + if (session->internals.priorities->sr == SR_DISABLED) { + gnutls_assert(); + return 0; + } + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret < 0) { + set = 1; + } + + if (set != 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + epriv); + } else + priv = epriv; + + /* Always offer the extension if we're a client */ + if (priv->connection_using_safe_renegotiation || + session->security_parameters.entity == GNUTLS_CLIENT) { + len = priv->client_verify_data_len; + if (session->security_parameters.entity == GNUTLS_SERVER) + len += priv->server_verify_data_len; + + ret = _gnutls_buffer_append_prefix(extdata, 8, len); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data(extdata, + priv->client_verify_data, + priv-> + client_verify_data_len); + if (ret < 0) + return gnutls_assert_val(ret); + + if (session->security_parameters.entity == GNUTLS_SERVER) { + ret = + _gnutls_buffer_append_data(extdata, + priv-> + server_verify_data, + priv-> + server_verify_data_len); + if (ret < 0) + return gnutls_assert_val(ret); + } + } else + return 0; + + return extdata->length - init_length; +} + +static void _gnutls_sr_deinit_data(gnutls_ext_priv_data_t priv) +{ + gnutls_free(priv); +} + +/** + * gnutls_safe_renegotiation_status: + * @session: is a #gnutls_session_t type. + * + * Can be used to check whether safe renegotiation is being used + * in the current session. + * + * Returns: 0 when safe renegotiation is not used and non (0) when + * safe renegotiation is used. + * + * Since: 2.10.0 + **/ +unsigned gnutls_safe_renegotiation_status(gnutls_session_t session) +{ + int ret; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SAFE_RENEGOTIATION, + &epriv); + if (ret < 0) { + gnutls_assert(); + return 0; + } + priv = epriv; + + return priv->connection_using_safe_renegotiation; +} diff --git a/lib/ext/safe_renegotiation.h b/lib/ext/safe_renegotiation.h new file mode 100644 index 0000000..bc2024a --- /dev/null +++ b/lib/ext/safe_renegotiation.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009-2012 Free Software Foundation, Inc. + * + * Author: Steve Dispensa (<dispensa@phonefactor.com>) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SAFE_RENEGOTIATION_H +#define GNUTLS_LIB_EXT_SAFE_RENEGOTIATION_H + +#include <hello_ext.h> + +typedef struct { + uint8_t client_verify_data[MAX_VERIFY_DATA_SIZE]; + size_t client_verify_data_len; + uint8_t server_verify_data[MAX_VERIFY_DATA_SIZE]; + size_t server_verify_data_len; + uint8_t ri_extension_data[MAX_VERIFY_DATA_SIZE * 2]; /* max signal is 72 bytes in s->c sslv3 */ + size_t ri_extension_data_len; + + unsigned int safe_renegotiation_received:1; + unsigned int initial_negotiation_completed:1; + unsigned int connection_using_safe_renegotiation:1; +} sr_ext_st; + +extern const hello_ext_entry_st ext_mod_sr; + +int _gnutls_ext_sr_finished(gnutls_session_t session, void *vdata, + size_t vdata_size, int dir); +int _gnutls_ext_sr_recv_cs(gnutls_session_t session); +int _gnutls_ext_sr_verify(gnutls_session_t session); +int _gnutls_ext_sr_send_cs(gnutls_session_t); + +#endif /* GNUTLS_LIB_EXT_SAFE_RENEGOTIATION_H */ diff --git a/lib/ext/server_cert_type.c b/lib/ext/server_cert_type.c new file mode 100644 index 0000000..6db2a1f --- /dev/null +++ b/lib/ext/server_cert_type.c @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2016 - 2018 ARPA2 project + * + * Author: Tom Vrancken (dev@tomvrancken.nl) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + * This file is part of the server_certificate_type extension as + * defined in RFC7250 (https://tools.ietf.org/html/rfc7250). + * + * The server_certificate_type extension in the client hello indicates + * the types of certificates the client is able to process when provided + * by the server in a subsequent certificate payload. + */ + +#include <gnutls_int.h> +#include <gnutls/gnutls.h> +#include "ext/cert_types.h" +#include "ext/server_cert_type.h" +#include "hello_ext.h" +#include "hello_ext_lib.h" +#include "errors.h" +#include "state.h" +#include "datum.h" + + +static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + const uint8_t* data, + size_t data_size); +static int _gnutls_server_cert_type_send_params(gnutls_session_t session, + gnutls_buffer_st* data); + + +const hello_ext_entry_st ext_mod_server_cert_type = { + .name = "Server Certificate Type", + .tls_id = 20, + .gid = GNUTLS_EXTENSION_SERVER_CERT_TYPE, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | + GNUTLS_EXT_FLAG_DTLS | + GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | + GNUTLS_EXT_FLAG_EE, + .recv_func = _gnutls_server_cert_type_recv_params, + .send_func = _gnutls_server_cert_type_send_params, + .pack_func = _gnutls_hello_ext_default_pack, + .unpack_func = _gnutls_hello_ext_default_unpack, + .deinit_func = _gnutls_hello_ext_default_deinit, + .cannot_be_overriden = 1 +}; + + +static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + const uint8_t* data, + size_t data_size) +{ + int ret; + gnutls_certificate_type_t cert_type; + size_t i; + bool found = false; + const uint8_t* pdata = data; + + /* Only activate this extension if we have cert credentials set + * and alternative cert types are allowed */ + if (!are_alternative_cert_types_allowed(session) || + (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)) + return 0; + + if (!IS_SERVER(session)) { // client mode + gnutls_datum_t sent_cert_types; // Holds the previously sent cert types + + /* Compare packet length with expected packet length. For the + * client this is a single byte. */ + if (data_size != 1) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + + /* The server picked one of the offered cert types if he supports + * at least one of them. If both parties play by the rules then we + * may only receive a cert type that we offered, i.e. one that we + * support. Because the world isn't as beautiful as it may seem, + * we're going to check it nevertheless. */ + cert_type = IANA2cert_type(pdata[0]); + + _gnutls_handshake_log("EXT[%p]: Received a %s server certificate type confirmation from the server.\n", + session, gnutls_certificate_type_get_name(cert_type)); + + // Check validity of cert type + if (cert_type == GNUTLS_CRT_UNKNOWN) { + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE); + } + + /* Get the cert types that we sent to the server (they were stored + * in IANA representation. + */ + ret = _gnutls_hello_ext_get_datum(session, + GNUTLS_EXTENSION_SERVER_CERT_TYPE, + &sent_cert_types); + if (ret < 0) { + /* This should not happen and indicate a memory corruption! + * Assertion are always on in production code so execution + * will halt here. */ + assert(false); + } + + // Check whether what we got back is actually offered by us + for (i = 0; i < sent_cert_types.size; i++) { + if (IANA2cert_type(sent_cert_types.data[i]) == cert_type) + found = true; + } + + if (found) { + // Everything OK, now set the server certificate type + _gnutls_session_server_cert_type_set(session, cert_type); + ret = GNUTLS_E_SUCCESS; + } else { + // No valid cert type found + ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + return ret; + + } else { // server mode + gnutls_datum_t cert_types; // Holds the received cert types + + // Compare packet length with expected packet length. + DECR_LEN(data_size, 1); + if (data[0] != data_size) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + pdata += 1; + + // Assign the contents of our data buffer to a gnutls_datum_t + cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning + cert_types.size = data_size; + + // Store the server certificate types in our session + _gnutls_hello_ext_set_datum(session, + GNUTLS_EXTENSION_SERVER_CERT_TYPE, + &cert_types); + + /* We receive a list of supported certificate types that the client + * is able to process when offered by the server via a subsequent + * Certificate message. This list is sorted by order of preference. + * We now check in this order of preference whether we support any + * of these certificate types. + */ + for (i = 0; i < cert_types.size; i++) { + // Convert to internal representation + cert_type = IANA2cert_type(cert_types.data[i]); + + // If we have an invalid cert id then continue to the next + if (cert_type == GNUTLS_CRT_UNKNOWN) + continue; + + _gnutls_handshake_log("EXT[%p]: Checking compatibility of a %s server certificate type that was received from the client.\n", + session, gnutls_certificate_type_get_name(cert_type)); + + // Check for support of this cert type + if (_gnutls_session_is_cert_type_supported(session, cert_type, true, GNUTLS_CTYPE_SERVER) == 0) { + found = true; + break; + } + } + + // We found a matching ctype, we pick this one + if (found) { + _gnutls_session_server_cert_type_set(session, cert_type); + ret = GNUTLS_E_SUCCESS; + } else { + /* If no supported certificate type can be found we terminate + * with a fatal alert of type "unsupported_certificate" + * (according to specification rfc7250). + */ + ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + } + + return ret; + } +} + +static int _gnutls_server_cert_type_send_params(gnutls_session_t session, + gnutls_buffer_st* data) +{ + int ret; + uint8_t cert_type_IANA; // Holds an IANA cert type ID + gnutls_certificate_type_t cert_type; + + /* Only activate this extension if we have cert credentials set + * and alternative cert types are allowed */ + if (!are_alternative_cert_types_allowed(session) || + (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)) + return 0; + + if (!IS_SERVER(session)) { // Client mode + uint8_t cert_types[GNUTLS_CRT_MAX]; // The list with supported (IANA) cert types. Inv: 0 <= cert type Id < 256 + size_t i, num_cert_types = 0; + priority_st* cert_priorities; + gnutls_datum_t tmp_cert_types; // For type conversion + + // For brevity + cert_priorities = &session->internals.priorities->server_ctype; + + /* Retrieve server certificate type priorities if any. If no + * priorities are set then the default server certificate type + * initialization values apply. This default is currently set to + * X.509 in which case we don't enable this extension. + */ + if (cert_priorities->num_priorities > 0) { // Priorities are explicitly set + /* If the certificate priority is explicitly set to only + * X.509 (default) then, according to spec we don't send + * this extension. We check this here to avoid further work in + * this routine. We also check it below after pruning supported + * types. + */ + if (cert_priorities->num_priorities == 1 && + cert_priorities->priorities[0] == DEFAULT_CERT_TYPE) { + _gnutls_handshake_log + ("EXT[%p]: Server certificate type was set to default cert type (%s). " + "We therefore do not send this extension.\n", + session, + gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE)); + + // Explicitly set but default ctype, so don't send anything + return 0; + } + + /* We are only allowed to send certificate types that we support. + * Therefore we check this here and prune our original list. + * This check might seem redundant now because we don't check for + * credentials (they are not needed for a client) and only check the + * priorities over which we already iterate. In the future, + * additional checks might be necessary and they can be easily + * added in the ..type_supported() routine without modifying the + * structure of the code here. + */ + for (i = 0; i < cert_priorities->num_priorities; i++) { + + cert_type = cert_priorities->priorities[i]; + + if (_gnutls_session_is_cert_type_supported(session, cert_type, + false, GNUTLS_CTYPE_SERVER) == 0) { + /* Check whether we are allowed to store another cert type + * in our buffer. In other words, prevent a possible buffer + * overflow. This situation can occur when a user sets + * duplicate cert types in the priority strings. */ + if (num_cert_types >= GNUTLS_CRT_MAX) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + + // Convert to IANA representation + ret = cert_type2IANA(cert_type); + + if (ret < 0) + return gnutls_assert_val(ret); + + cert_type_IANA = ret; // For readability + + // Add this cert type to our list with supported types + cert_types[num_cert_types] = cert_type_IANA; + num_cert_types++; + + _gnutls_handshake_log + ("EXT[%p]: Server certificate type %s (%d) was queued.\n", + session, + gnutls_certificate_type_get_name(cert_type), + cert_type_IANA); + } + } + + /* Check whether there are any supported certificate types left + * after the previous pruning step. If not, we do not send this + * extension. Also, if the only supported type is the default type + * we do not send this extension (according to RFC7250). + */ + if (num_cert_types == 0) { // For now, this should not occur since we only check priorities while pruning. + _gnutls_handshake_log + ("EXT[%p]: Server certificate types were set but none of them is supported. " + "We do not send this extension.\n", + session); + + return 0; + } else if (num_cert_types == 1 && + IANA2cert_type(cert_types[0]) == DEFAULT_CERT_TYPE) { + _gnutls_handshake_log + ("EXT[%p]: The only supported server certificate type is (%s) which is the default. " + "We therefore do not send this extension.\n", + session, + gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE)); + + return 0; + } + + /* We have data to send and store a copy internally. We convert + * our list with supported cert types to a datum_t in order to + * be able to make the ..._set_datum call. + */ + tmp_cert_types.data = cert_types; + tmp_cert_types.size = num_cert_types; + + _gnutls_hello_ext_set_datum(session, + GNUTLS_EXTENSION_SERVER_CERT_TYPE, + &tmp_cert_types); + + /* Serialize the certificate types into a sequence of octets + * uint8: length of sequence of cert types (1 octet) + * uint8: cert types (0 <= #octets <= 255) + */ + ret = _gnutls_buffer_append_data_prefix(data, 8, + cert_types, + num_cert_types); + + // Check for errors and cleanup in case of error + if (ret < 0) { + return gnutls_assert_val(ret); + } else { + // Number of bytes we are sending + return num_cert_types + 1; + } + } + } else { // Server mode + // Retrieve negotiated server certificate type and send it + cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER); + ret = cert_type2IANA(cert_type); + + if (ret < 0) + return gnutls_assert_val(ret); + + cert_type_IANA = ret; // For readability + + _gnutls_handshake_log("EXT[%p]: Confirming to use a %s server certificate type.\n", + session, gnutls_certificate_type_get_name(cert_type)); + + ret = gnutls_buffer_append_data(data, &cert_type_IANA, 1); + + if (ret < 0) + return gnutls_assert_val(ret); + + return 1; // sent one byte + } + + // In all other cases don't enable this extension + return 0; +} + + +/** Extension interface **/ + +/* The interface is defined in state.c: + * Public: + * - gnutls_certificate_type_get2 + * + * Private: + * - _gnutls_session_server_cert_type_set + */ diff --git a/lib/ext/server_cert_type.h b/lib/ext/server_cert_type.h new file mode 100644 index 0000000..3c15b0b --- /dev/null +++ b/lib/ext/server_cert_type.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 - 2018 ARPA2 project + * + * Author: Tom Vrancken (dev@tomvrancken.nl) + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + * This file is part of the server_certificate_type extension as + * defined in RFC7250 (https://tools.ietf.org/html/rfc7250). + * + * The server_certificate_type extension in the client hello indicates + * the certificate types the client is able to process from the server + * in order to authenticate the server. + */ + +#ifndef GNUTLS_LIB_EXT_SERVER_CERT_TYPE_H +#define GNUTLS_LIB_EXT_SERVER_CERT_TYPE_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_server_cert_type; + +#endif /* GNUTLS_LIB_EXT_SERVER_CERT_TYPE_H */ diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c new file mode 100644 index 0000000..d52c8d0 --- /dev/null +++ b/lib/ext/server_name.c @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "num.h" +#include "str.h" +#include <ext/server_name.h> +#include "hello_ext_lib.h" + +static int _gnutls_server_name_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_server_name_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +int +_gnutls_server_name_set_raw(gnutls_session_t session, + gnutls_server_name_type_t type, + const void *name, size_t name_length); + +const hello_ext_entry_st ext_mod_server_name = { + .name = "Server Name Indication", + .tls_id = 0, + .gid = GNUTLS_EXTENSION_SERVER_NAME, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .client_parse_point = GNUTLS_EXT_MANDATORY, + .server_parse_point = GNUTLS_EXT_MANDATORY, + .recv_func = _gnutls_server_name_recv_params, + .send_func = _gnutls_server_name_send_params, + .pack_func = _gnutls_hello_ext_default_pack, + .unpack_func = _gnutls_hello_ext_default_unpack, + .deinit_func = _gnutls_hello_ext_default_deinit, + .cannot_be_overriden = 1 +}; + +/* + * In case of a server: if a NAME_DNS extension type is received then + * it stores into the session the value of NAME_DNS. The server may + * use gnutls_ext_get_server_name(), in order to access it. + * + * In case of a client: If a proper NAME_DNS extension type is found + * in the session then it sends the extension to the peer. + * + */ +static int +_gnutls_server_name_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + const unsigned char *p; + uint16_t len, type; + gnutls_datum_t name; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + len = _gnutls_read_uint16(data); + if (len == 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (len != data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + p = data + 2; + + while (data_size > 0) { + DECR_LEN(data_size, 1); + type = *p; + p++; + + DECR_LEN(data_size, 2); + len = _gnutls_read_uint16(p); + p += 2; + + if (len == 0) { + _gnutls_handshake_log + ("HSK[%p]: Received server name size of zero\n", + session); + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + + DECR_LEN(data_size, len); + + if (type == 0) { /* NAME_DNS */ + if (!_gnutls_dnsname_is_valid((char*)p, len)) { + _gnutls_handshake_log + ("HSK[%p]: Server name is not acceptable: '%.*s'\n", + session, (int) len, p); + return gnutls_assert_val(GNUTLS_E_RECEIVED_DISALLOWED_NAME); + } + + name.data = (void*)p; + name.size = len; + + _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME); + return _gnutls_hello_ext_set_datum(session, + GNUTLS_EXTENSION_SERVER_NAME, + &name); + } + p += len; + + } + + + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_server_name_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + int total_size = 0, ret; + gnutls_datum_t name; + + ret = + _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_SERVER_NAME, + &name); + if (ret < 0) + return 0; + + /* this function sends the client extension data (dnsname) + */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (name.size == 0) + return 0; + + /* uint8_t + uint16_t + size + */ + total_size = 2 + 1 + 2 + name.size; + + /* UINT16: write total size of all names + */ + ret = + _gnutls_buffer_append_prefix(extdata, 16, + total_size - 2); + if (ret < 0) + return gnutls_assert_val(ret); + + /* UINT8: type of this extension + * UINT16: size of the first name + * LEN: the actual server name. + */ + ret = + _gnutls_buffer_append_prefix(extdata, 8, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + _gnutls_debug_log("HSK[%p]: sent server name: '%.*s'\n", session, name.size, name.data); + + ret = + _gnutls_buffer_append_data_prefix + (extdata, 16, + name.data, name.size); + if (ret < 0) + return gnutls_assert_val(ret); + } else { + return 0; + } + + return total_size; +} + +/** + * gnutls_server_name_get: + * @session: is a #gnutls_session_t type. + * @data: will hold the data + * @data_length: will hold the data length. Must hold the maximum size of data. + * @type: will hold the server name indicator type + * @indx: is the index of the server_name + * + * This function will allow you to get the name indication (if any), a + * client has sent. The name indication may be any of the enumeration + * gnutls_server_name_type_t. + * + * If @type is GNUTLS_NAME_DNS, then this function is to be used by + * servers that support virtual hosting, and the data will be a null + * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string). + * + * If @data has not enough size to hold the server name + * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will + * hold the required size. + * + * @indx is used to retrieve more than one server names (if sent by + * the client). The first server name has an index of 0, the second 1 + * and so on. If no name with the given index exists + * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, on UTF-8 + * decoding error %GNUTLS_E_IDNA_ERROR is returned, otherwise a negative + * error code is returned. + **/ +int +gnutls_server_name_get(gnutls_session_t session, void *data, + size_t * data_length, + unsigned int *type, unsigned int indx) +{ + char *_data = data; + gnutls_datum_t name; + int ret; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (indx != 0) + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + + ret = + _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_SERVER_NAME, &name); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if (name.size == 0) { + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + *type = GNUTLS_NAME_DNS; + + if (*data_length > name.size) { /* greater since we need one extra byte for the null */ + *data_length = name.size; + memcpy(data, name.data, *data_length); + + /* null terminate */ + _data[(*data_length)] = 0; + + } else { + *data_length = name.size + 1; + ret = GNUTLS_E_SHORT_MEMORY_BUFFER; + goto cleanup; + } + + ret = 0; + cleanup: + return ret; +} + +/* This does not do any conversion not perform any check */ +int +_gnutls_server_name_set_raw(gnutls_session_t session, + gnutls_server_name_type_t type, + const void *name, size_t name_length) +{ + int ret; + gnutls_datum_t dname; + + if (name_length >= MAX_SERVER_NAME_SIZE) { + return GNUTLS_E_INVALID_REQUEST; + } + + _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME); + + dname.data = (void*)name; + dname.size = name_length; + + ret = _gnutls_hello_ext_set_datum(session, GNUTLS_EXTENSION_SERVER_NAME, &dname); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + +/** + * gnutls_server_name_set: + * @session: is a #gnutls_session_t type. + * @type: specifies the indicator type + * @name: is a string that contains the server name. + * @name_length: holds the length of name excluding the terminating null byte + * + * This function is to be used by clients that want to inform (via a + * TLS extension mechanism) the server of the name they connected to. + * This should be used by clients that connect to servers that do + * virtual hosting. + * + * The value of @name depends on the @type type. In case of + * %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string, + * without the trailing dot, is expected. + * + * IPv4 or IPv6 addresses are not permitted to be set by this function. + * If the function is called with a name of @name_length zero it will clear + * all server names set. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + **/ +int +gnutls_server_name_set(gnutls_session_t session, + gnutls_server_name_type_t type, + const void *name, size_t name_length) +{ + int ret; + gnutls_datum_t idn_name = {NULL,0}; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (name_length == 0) { /* unset extension */ + _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME); + return 0; + } + + ret = gnutls_idna_map(name, name_length, &idn_name, 0); + if (ret < 0) { + _gnutls_debug_log("unable to convert name %s to IDNA2008 format\n", (char*)name); + return ret; + } + + name = idn_name.data; + name_length = idn_name.size; + + ret = _gnutls_server_name_set_raw(session, type, name, name_length); + gnutls_free(idn_name.data); + + return ret; +} + +unsigned _gnutls_server_name_matches_resumed(gnutls_session_t session) +{ + gnutls_datum_t name1, name2; + int ret; + + ret = + _gnutls_hello_ext_get_datum(session, + GNUTLS_EXTENSION_SERVER_NAME, + &name1); + if (ret < 0) { /* no server name in this session */ + name1.data = NULL; + name1.size = 0; + } + + ret = + _gnutls_hello_ext_get_resumed_datum(session, + GNUTLS_EXTENSION_SERVER_NAME, + &name2); + if (ret < 0) { /* no server name in this session */ + name2.data = NULL; + name2.size = 0; + } + + if (name1.data == NULL || name2.data == NULL) { + if (name1.data == name2.data) + return 1; + else + return 0; + } + + if (name1.size != name2.size) + return 0; + + if (memcmp(name1.data, name2.data, name1.size) != 0) + return 0; + + return 1; +} diff --git a/lib/ext/server_name.h b/lib/ext/server_name.h new file mode 100644 index 0000000..b5cdd0e --- /dev/null +++ b/lib/ext/server_name.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2012 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SERVER_NAME_H +#define GNUTLS_LIB_EXT_SERVER_NAME_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_server_name; + +unsigned _gnutls_server_name_matches_resumed(gnutls_session_t); + +#endif /* GNUTLS_LIB_EXT_SERVER_NAME_H */ diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c new file mode 100644 index 0000000..87d9069 --- /dev/null +++ b/lib/ext/session_ticket.c @@ -0,0 +1,843 @@ +/* + * Copyright (C) 2009-2018 Free Software Foundation, Inc. + * + * Author: Daiki Ueno, Ander Juaristi + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file implements the TLS session ticket extension. + * + * Note that the extension is only used in TLS 1.2. For TLS 1.3, session + * tickets are sent as part of pre_shared_key extension (see pre_shared_key.c). + */ + +#include "gnutls_int.h" +#include "errors.h" +#include <fips.h> +#include <datum.h> +#include <algorithms.h> +#include <handshake.h> +#include <num.h> +#include <constate.h> +#include <session_pack.h> +#include <random.h> +#include <ext/session_ticket.h> +#include <mbuffers.h> +#include <hello_ext.h> +#include <constate.h> +#include <dtls.h> +#include "stek.h" +#include "db.h" + +static int session_ticket_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int session_ticket_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); +static int session_ticket_unpack(gnutls_buffer_st * ps, + gnutls_ext_priv_data_t * _priv); +static int session_ticket_pack(gnutls_ext_priv_data_t _priv, + gnutls_buffer_st * ps); +static void session_ticket_deinit_data(gnutls_ext_priv_data_t priv); + +const hello_ext_entry_st ext_mod_session_ticket = { + .name = "Session Ticket", + .tls_id = 35, + .gid = GNUTLS_EXTENSION_SESSION_TICKET, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + /* This extension must be parsed on session resumption as well; see + * https://gitlab.com/gnutls/gnutls/issues/841 */ + .client_parse_point = GNUTLS_EXT_MANDATORY, + /* on server side we want this parsed after normal handshake resumption + * actions are complete */ + .server_parse_point = GNUTLS_EXT_TLS, + .recv_func = session_ticket_recv_params, + .send_func = session_ticket_send_params, + .pack_func = session_ticket_pack, + .unpack_func = session_ticket_unpack, + .deinit_func = session_ticket_deinit_data, + .cannot_be_overriden = 1 +}; + +typedef struct { + uint8_t *session_ticket; + int session_ticket_len; +} session_ticket_ext_st; + +static void +deinit_ticket(struct ticket_st *ticket) +{ + free(ticket->encrypted_state); +} + +static int +unpack_ticket(const gnutls_datum_t *ticket_data, struct ticket_st *ticket) +{ + const uint8_t * data = ticket_data->data; + size_t data_size = ticket_data->size; + const uint8_t *encrypted_state; + + /* Format: + * Key name + * IV + * data length + * encrypted data + * MAC + */ + DECR_LEN(data_size, TICKET_KEY_NAME_SIZE); + memcpy(ticket->key_name, data, TICKET_KEY_NAME_SIZE); + data += TICKET_KEY_NAME_SIZE; + + DECR_LEN(data_size, TICKET_IV_SIZE); + memcpy(ticket->IV, data, TICKET_IV_SIZE); + data += TICKET_IV_SIZE; + + DECR_LEN(data_size, 2); + ticket->encrypted_state_len = _gnutls_read_uint16(data); + data += 2; + + encrypted_state = data; + + DECR_LEN(data_size, ticket->encrypted_state_len); + data += ticket->encrypted_state_len; + + DECR_LEN(data_size, TICKET_MAC_SIZE); + memcpy(ticket->mac, data, TICKET_MAC_SIZE); + + ticket->encrypted_state = + gnutls_malloc(ticket->encrypted_state_len); + if (!ticket->encrypted_state) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + memcpy(ticket->encrypted_state, encrypted_state, + ticket->encrypted_state_len); + + return 0; +} + +static void +pack_ticket(const struct ticket_st *ticket, gnutls_datum_t *ticket_data) +{ + uint8_t *p; + + p = ticket_data->data; + + memcpy(p, ticket->key_name, TICKET_KEY_NAME_SIZE); + p += TICKET_KEY_NAME_SIZE; + + memcpy(p, ticket->IV, TICKET_IV_SIZE); + p += TICKET_IV_SIZE; + + _gnutls_write_uint16(ticket->encrypted_state_len, p); + p += 2; + + /* We use memmove instead of memcpy here because + * ticket->encrypted_state is allocated from + * ticket_data->data, and thus both memory areas may overlap. + */ + memmove(p, ticket->encrypted_state, ticket->encrypted_state_len); + p += ticket->encrypted_state_len; + + memcpy(p, ticket->mac, TICKET_MAC_SIZE); +} + +static +int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket, + uint8_t * digest) +{ + mac_hd_st digest_hd; + uint16_t length16; + int ret; + + ret = _gnutls_mac_init(&digest_hd, mac_to_entry(TICKET_MAC_ALGO), + key->data, key->size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + _gnutls_mac(&digest_hd, ticket->key_name, TICKET_KEY_NAME_SIZE); + _gnutls_mac(&digest_hd, ticket->IV, TICKET_IV_SIZE); + length16 = _gnutls_conv_uint16(ticket->encrypted_state_len); + _gnutls_mac(&digest_hd, &length16, 2); + _gnutls_mac(&digest_hd, ticket->encrypted_state, + ticket->encrypted_state_len); + _gnutls_mac_deinit(&digest_hd, digest); + + return 0; +} + +int +_gnutls_decrypt_session_ticket(gnutls_session_t session, + const gnutls_datum_t *ticket_data, + gnutls_datum_t *state) +{ + cipher_hd_st cipher_hd; + gnutls_datum_t IV; + gnutls_datum_t stek_key_name, stek_cipher_key, stek_mac_key; + uint8_t cmac[TICKET_MAC_SIZE]; + struct ticket_st ticket; + int ret; + + /* Retrieve ticket decryption keys */ + if (_gnutls_get_session_ticket_decryption_key(session, + ticket_data, + &stek_key_name, + &stek_mac_key, + &stek_cipher_key) < 0) + return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); + + ret = unpack_ticket(ticket_data, &ticket); + if (ret < 0) + return ret; + + /* If the key name of the ticket does not match the one that is currently active, + issue a new ticket. */ + if (memcmp + (ticket.key_name, stek_key_name.data, + stek_key_name.size)) { + ret = GNUTLS_E_DECRYPTION_FAILED; + goto cleanup; + } + + /* Check the integrity of ticket */ + ret = digest_ticket(&stek_mac_key, &ticket, cmac); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + if (memcmp(ticket.mac, cmac, TICKET_MAC_SIZE)) { + ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); + goto cleanup; + } + + if (ticket.encrypted_state_len % TICKET_BLOCK_SIZE != 0) { + ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); + goto cleanup; + } + + /* Decrypt encrypted_state */ + IV.data = ticket.IV; + IV.size = TICKET_IV_SIZE; + ret = + _gnutls_cipher_init(&cipher_hd, + cipher_to_entry(TICKET_CIPHER), + &stek_cipher_key, &IV, 0); + if (ret < 0) { + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); + gnutls_assert(); + goto cleanup; + } + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED); + + ret = _gnutls_cipher_decrypt(&cipher_hd, ticket.encrypted_state, + ticket.encrypted_state_len); + if (ret < 0) { + gnutls_assert(); + goto cleanup2; + } + + state->data = ticket.encrypted_state; + state->size = ticket.encrypted_state_len; + + ticket.encrypted_state = NULL; + + ret = 0; + +cleanup2: + _gnutls_cipher_deinit(&cipher_hd); + +cleanup: + deinit_ticket(&ticket); + + return ret; + +} + +int +_gnutls_encrypt_session_ticket(gnutls_session_t session, + const gnutls_datum_t *state, + gnutls_datum_t *ticket_data) +{ + cipher_hd_st cipher_hd; + gnutls_datum_t IV; + gnutls_datum_t encrypted_state; + gnutls_datum_t result = { NULL, 0 }; + uint8_t iv[TICKET_IV_SIZE]; + gnutls_datum_t stek_cipher_key, stek_mac_key, stek_key_name; + struct ticket_st ticket; + int ret; + + encrypted_state.size = ((state->size + TICKET_BLOCK_SIZE - 1) / TICKET_BLOCK_SIZE) * TICKET_BLOCK_SIZE; + result.size = TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2 + + encrypted_state.size + TICKET_MAC_SIZE; + result.data = gnutls_calloc(1, result.size); + if (!result.data) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + encrypted_state.data = result.data + TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2; + memcpy(encrypted_state.data, state->data, state->size); + + /* Retrieve ticket encryption keys */ + if (_gnutls_get_session_ticket_encryption_key(session, + &stek_key_name, + &stek_mac_key, + &stek_cipher_key) < 0) { + ret = GNUTLS_E_ENCRYPTION_FAILED; + goto cleanup; + } + + /* Encrypt state */ + IV.data = iv; + IV.size = TICKET_IV_SIZE; + + ret = gnutls_rnd(GNUTLS_RND_NONCE, iv, TICKET_IV_SIZE); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = + _gnutls_cipher_init(&cipher_hd, + cipher_to_entry(TICKET_CIPHER), + &stek_cipher_key, &IV, 1); + if (ret < 0) { + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); + gnutls_assert(); + goto cleanup; + } + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED); + + ret = _gnutls_cipher_encrypt(&cipher_hd, encrypted_state.data, + encrypted_state.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup2; + } + + + /* Fill the ticket structure to compute MAC. */ + memcpy(ticket.key_name, stek_key_name.data, stek_key_name.size); + memcpy(ticket.IV, IV.data, IV.size); + ticket.encrypted_state_len = encrypted_state.size; + ticket.encrypted_state = encrypted_state.data; + + ret = digest_ticket(&stek_mac_key, &ticket, ticket.mac); + if (ret < 0) { + gnutls_assert(); + goto cleanup2; + } + + pack_ticket(&ticket, &result); + ticket_data->data = result.data; + ticket_data->size = result.size; + result.data = NULL; + +cleanup2: + _gnutls_cipher_deinit(&cipher_hd); + +cleanup: + _gnutls_free_datum(&result); + + return ret; +} + +static int +unpack_session(gnutls_session_t session, const gnutls_datum_t *state) +{ + int ret; + + if (unlikely(!state)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = _gnutls_session_unpack(session, state); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_check_resumed_params(session); + if (ret < 0) + return gnutls_assert_val(ret); + + session->internals.resumed = true; + return 0; +} + +static int +session_ticket_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + gnutls_datum_t ticket_data; + gnutls_datum_t state; + int ret; + + if (session->internals.flags & (GNUTLS_NO_TICKETS | GNUTLS_NO_TICKETS_TLS12)) + return 0; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + /* The client requested a new session ticket. */ + if (data_size == 0) { + session->internals.session_ticket_renew = 1; + return 0; + } + + ticket_data.data = (void *)data; + ticket_data.size = data_size; + if ((ret = _gnutls_decrypt_session_ticket(session, &ticket_data, &state)) == 0) { + ret = unpack_session(session, &state); + + _gnutls_free_datum(&state); + } + + if (ret < 0) { + session->internals.session_ticket_renew = 1; + return 0; + } + } else { /* Client */ + + if (data_size == 0) { + session->internals.session_ticket_renew = 1; + return 0; + } + } + + return 0; +} + +/* returns a positive number if we send the extension data, (0) if we + do not want to send it, and a negative number on failure. + */ +static int +session_ticket_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + session_ticket_ext_st *priv = NULL; + gnutls_ext_priv_data_t epriv; + int ret; + + if (session->internals.flags & (GNUTLS_NO_TICKETS | GNUTLS_NO_TICKETS_TLS12)) + return 0; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (session->internals.session_ticket_renew) { + return GNUTLS_E_INT_RET_0; + } + } else { + ret = + _gnutls_hello_ext_get_resumed_priv(session, + GNUTLS_EXTENSION_SESSION_TICKET, + &epriv); + if (ret >= 0) + priv = epriv; + + /* no previous data. Just advertise it */ + if (ret < 0) + return GNUTLS_E_INT_RET_0; + + /* previous data had session tickets disabled. Don't advertise. Ignore. */ + if (session->internals.flags & GNUTLS_NO_TICKETS) + return 0; + + if (priv->session_ticket_len > 0) { + ret = + _gnutls_buffer_append_data(extdata, + priv-> + session_ticket, + priv-> + session_ticket_len); + if (ret < 0) + return gnutls_assert_val(ret); + + return priv->session_ticket_len; + } + } + return 0; +} + + +static void session_ticket_deinit_data(gnutls_ext_priv_data_t epriv) +{ + session_ticket_ext_st *priv = epriv; + + gnutls_free(priv->session_ticket); + gnutls_free(priv); +} + +static int +session_ticket_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps) +{ + session_ticket_ext_st *priv = epriv; + int ret; + + BUFFER_APPEND_PFX4(ps, priv->session_ticket, + priv->session_ticket_len); + + return 0; +} + +static int +session_ticket_unpack(gnutls_buffer_st * ps, gnutls_ext_priv_data_t * _priv) +{ + session_ticket_ext_st *priv = NULL; + int ret; + gnutls_ext_priv_data_t epriv; + gnutls_datum_t ticket; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_DATUM(ps, &ticket); + priv->session_ticket = ticket.data; + priv->session_ticket_len = ticket.size; + + epriv = priv; + *_priv = epriv; + + return 0; + + error: + gnutls_free(priv); + return ret; +} + + + +/** + * gnutls_session_ticket_key_generate: + * @key: is a pointer to a #gnutls_datum_t which will contain a newly + * created key. + * + * Generate a random key to encrypt security parameters within + * SessionTicket. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an + * error code. + * + * Since: 2.10.0 + **/ +int gnutls_session_ticket_key_generate(gnutls_datum_t * key) +{ + if (_gnutls_fips_mode_enabled()) { + int ret; + /* in FIPS140-2 mode gnutls_key_generate imposes + * some limits on allowed key size, thus it is not + * used. These limits do not affect this function as + * it does not generate a "key" but rather key material + * that includes nonces and other stuff. */ + key->data = gnutls_malloc(TICKET_MASTER_KEY_SIZE); + if (key->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + key->size = TICKET_MASTER_KEY_SIZE; + ret = gnutls_rnd(GNUTLS_RND_RANDOM, key->data, key->size); + if (ret < 0) { + gnutls_free(key->data); + return ret; + } + return 0; + } else { + return gnutls_key_generate(key, TICKET_MASTER_KEY_SIZE); + } +} + +/** + * gnutls_session_ticket_enable_client: + * @session: is a #gnutls_session_t type. + * + * Request that the client should attempt session resumption using + * SessionTicket. This call is typically unnecessary as session + * tickets are enabled by default. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an + * error code. + * + * Since: 2.10.0 + **/ +int gnutls_session_ticket_enable_client(gnutls_session_t session) +{ + if (!session) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + session->internals.flags &= ~GNUTLS_NO_TICKETS; + + return 0; +} + +/** + * gnutls_session_ticket_enable_server: + * @session: is a #gnutls_session_t type. + * @key: key to encrypt session parameters. + * + * Request that the server should attempt session resumption using + * session tickets, i.e., by delegating storage to the client. + * @key must be initialized using gnutls_session_ticket_key_generate(). + * To avoid leaking that key, use gnutls_memset() prior to + * releasing it. + * + * The default ticket expiration time can be overridden using + * gnutls_db_set_cache_expiration(). + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an + * error code. + * + * Since: 2.10.0 + **/ +int +gnutls_session_ticket_enable_server(gnutls_session_t session, + const gnutls_datum_t * key) +{ + int ret; + + if (!session || !key || key->size != TICKET_MASTER_KEY_SIZE || !key->data) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = _gnutls_initialize_session_ticket_key_rotation(session, key); + if (ret < 0) + return gnutls_assert_val(ret); + + session->internals.flags &= ~GNUTLS_NO_TICKETS; + + return 0; +} + +/* + * Return zero if session tickets haven't been enabled. + */ +int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) +{ + mbuffer_st *bufel = NULL; + uint8_t *data = NULL, *p; + int data_size = 0; + int ret; + gnutls_datum_t state = { NULL, 0 }; + uint16_t epoch_saved = session->security_parameters.epoch_write; + gnutls_datum_t ticket_data; + + if (again == 0) { + if (session->internals.flags & (GNUTLS_NO_TICKETS | + GNUTLS_NO_TICKETS_TLS12)) { + return 0; + } + if (!session->key.stek_initialized) { + return 0; + } + if (!session->internals.session_ticket_renew) { + return 0; + } + + _gnutls_handshake_log + ("HSK[%p]: sending session ticket\n", session); + + /* XXX: Temporarily set write algorithms to be used. + _gnutls_write_connection_state_init() does this job, but it also + triggers encryption, while NewSessionTicket should not be + encrypted in the record layer. */ + ret = + _gnutls_epoch_set_keys(session, + session->security_parameters. + epoch_next, 0); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Under TLS1.2 with session tickets, the session ID is used for different + * purposes than the TLS1.0 session ID. Ensure that there is an internally + * set value which the server will see on the original and resumed sessions */ + if (!session->internals.resumed) { + ret = _gnutls_generate_session_id(session->security_parameters. + session_id, + &session->security_parameters. + session_id_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + session->security_parameters.epoch_write = + session->security_parameters.epoch_next; + + /* Pack security parameters. */ + ret = _gnutls_session_pack(session, &state); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Generate an encrypted ticket */ + ret = _gnutls_encrypt_session_ticket(session, &state, &ticket_data); + session->security_parameters.epoch_write = epoch_saved; + _gnutls_free_datum(&state); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + bufel = + _gnutls_handshake_alloc(session, + 4 + 2 + ticket_data.size); + if (!bufel) { + gnutls_assert(); + _gnutls_free_datum(&ticket_data); + return GNUTLS_E_MEMORY_ERROR; + } + + data = _mbuffer_get_udata_ptr(bufel); + p = data; + + _gnutls_write_uint32(session->internals.expire_time, p); + p += 4; + + _gnutls_write_uint16(ticket_data.size, p); + p += 2; + + memcpy(p, ticket_data.data, ticket_data.size); + p += ticket_data.size; + + _gnutls_free_datum(&ticket_data); + + data_size = p - data; + + session->internals.hsk_flags |= HSK_TLS12_TICKET_SENT; + } + return _gnutls_send_handshake(session, data_size ? bufel : NULL, + GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); +} + +/* + * Return zero if session tickets haven't been enabled. + */ +int _gnutls_recv_new_session_ticket(gnutls_session_t session) +{ + uint8_t *p; + int data_size; + gnutls_buffer_st buf; + uint16_t ticket_len; + int ret; + session_ticket_ext_st *priv = NULL; + gnutls_ext_priv_data_t epriv; + + if (session->internals.flags & (GNUTLS_NO_TICKETS | + GNUTLS_NO_TICKETS_TLS12)) + return 0; + if (!session->internals.session_ticket_renew) + return 0; + + /* This is the last flight and peer cannot be sure + * we have received it unless we notify him. So we + * wait for a message and retransmit if needed. */ + if (IS_DTLS(session) && !_dtls_is_async(session)) { + unsigned have; + mbuffer_st *bufel = NULL; + + have = gnutls_record_check_pending(session) + + record_check_unprocessed(session); + + if (have != 0) { + bufel = _mbuffer_head_get_first(&session->internals.record_buffer, NULL); + } + + if (have == 0 || (bufel && bufel->type != GNUTLS_HANDSHAKE)) { + ret = _dtls_wait_and_retransmit(session); + if (ret < 0) + return gnutls_assert_val(ret); + } + } + + ret = _gnutls_recv_handshake(session, + GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, + 0, &buf); + if (ret < 0) + return gnutls_assert_val_fatal(ret); + + p = buf.data; + data_size = buf.length; + + DECR_LENGTH_COM(data_size, 4, ret = + GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + goto error); + /* skip over lifetime hint */ + p += 4; + + DECR_LENGTH_COM(data_size, 2, ret = + GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + goto error); + ticket_len = _gnutls_read_uint16(p); + p += 2; + + DECR_LENGTH_COM(data_size, ticket_len, ret = + GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + goto error); + + priv = gnutls_calloc(1, sizeof(*priv)); + if (!priv) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } + if (ticket_len > 0) { + priv->session_ticket = + gnutls_realloc_fast(priv->session_ticket, ticket_len); + if (!priv->session_ticket) { + gnutls_free(priv); + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } + memcpy(priv->session_ticket, p, ticket_len); + } + priv->session_ticket_len = ticket_len; + epriv = priv; + + /* Discard the current session ID. (RFC5077 3.4) */ + ret = + _gnutls_generate_session_id(session->security_parameters. + session_id, + &session->security_parameters. + session_id_size); + if (ret < 0) { + gnutls_assert(); + session_ticket_deinit_data(epriv); + ret = GNUTLS_E_INTERNAL_ERROR; + goto error; + } + ret = 0; + + _gnutls_handshake_log + ("HSK[%p]: received session ticket\n", session); + session->internals.hsk_flags |= HSK_TICKET_RECEIVED; + + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SESSION_TICKET, + epriv); + + error: + _gnutls_buffer_clear(&buf); + + return ret; +} diff --git a/lib/ext/session_ticket.h b/lib/ext/session_ticket.h new file mode 100644 index 0000000..da804ec --- /dev/null +++ b/lib/ext/session_ticket.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009-2012 Free Software Foundation, Inc. + * + * Author: Daiki Ueno + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SESSION_TICKET_H +#define GNUTLS_LIB_EXT_SESSION_TICKET_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_session_ticket; + +int _gnutls_send_new_session_ticket(gnutls_session_t session, int again); +int _gnutls_recv_new_session_ticket(gnutls_session_t session); + +int _gnutls_encrypt_session_ticket(gnutls_session_t session, + const gnutls_datum_t *state, + gnutls_datum_t *ticket_data); +int _gnutls_decrypt_session_ticket(gnutls_session_t session, + const gnutls_datum_t *ticket_data, + gnutls_datum_t *state); + +#endif /* GNUTLS_LIB_EXT_SESSION_TICKET_H */ diff --git a/lib/ext/signature.c b/lib/ext/signature.c new file mode 100644 index 0000000..bb350f5 --- /dev/null +++ b/lib/ext/signature.c @@ -0,0 +1,587 @@ +/* + * Copyright (C) 2002-2016 Free Software Foundation, Inc. + * Copyright (C) 2015-2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Signature Algorithms TLS extension. + * This extension is currently gnutls specific. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <gnutls/gnutls.h> +#include <ext/signature.h> +#include <state.h> +#include <num.h> +#include <algorithms.h> +#include <abstract_int.h> + +/* + * Some (all SChannel) clients fail to send proper SigAlgs due to Micro$oft crazyness. + * Patch the extension for them. + */ +#ifdef ENABLE_GOST +#define GOST_SIG_FIXUP_SCHANNEL +#endif + +static int _gnutls_signature_algorithm_recv_params(gnutls_session_t + session, + const uint8_t * data, + size_t data_size); +static int _gnutls_signature_algorithm_send_params(gnutls_session_t + session, + gnutls_buffer_st * extdata); +static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv); +static int signature_algorithms_pack(gnutls_ext_priv_data_t epriv, + gnutls_buffer_st * ps); +static int signature_algorithms_unpack(gnutls_buffer_st * ps, + gnutls_ext_priv_data_t * _priv); + +const hello_ext_entry_st ext_mod_sig = { + .name = "Signature Algorithms", + .tls_id = 13, + .gid = GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .recv_func = _gnutls_signature_algorithm_recv_params, + .send_func = _gnutls_signature_algorithm_send_params, + .pack_func = signature_algorithms_pack, + .unpack_func = signature_algorithms_unpack, + .deinit_func = signature_algorithms_deinit_data, + .cannot_be_overriden = 1 +}; + +typedef struct { + /* TLS 1.2 signature algorithms */ + gnutls_sign_algorithm_t sign_algorithms[MAX_ALGOS]; + uint16_t sign_algorithms_size; +} sig_ext_st; + +/* generates a SignatureAndHashAlgorithm structure with length as prefix + * by using the setup priorities. + */ +int +_gnutls_sign_algorithm_write_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + uint8_t *p; + unsigned int len, i; + const sign_algorithm_st *aid, *prev = NULL; + uint8_t buffer[MAX_ALGOS*2]; + + p = buffer; + len = 0; + + /* This generates a list of TLS signature algorithms. It has + * limited duplicate detection, and does not add twice the same + * AID */ + + for (i=0;i<session->internals.priorities->sigalg.size;i++) { + aid = &session->internals.priorities->sigalg.entry[i]->aid; + + if (HAVE_UNKNOWN_SIGAID(aid)) + continue; + + if (prev && prev->id[0] == aid->id[0] && prev->id[1] == aid->id[1]) + continue; + + /* Ignore non-GOST sign types for CertReq */ + if (session->security_parameters.cs && + _gnutls_kx_is_vko_gost(session->security_parameters.cs->kx_algorithm) && + !_sign_is_gost(session->internals.priorities->sigalg.entry[i])) + continue; + + _gnutls_handshake_log + ("EXT[%p]: sent signature algo (%d.%d) %s\n", session, + (int)aid->id[0], (int)aid->id[1], + session->internals.priorities->sigalg.entry[i]->name); + + len += 2; + if (unlikely(len >= sizeof(buffer))) { + len -= 2; + break; + } + + *p = aid->id[0]; + p++; + *p = aid->id[1]; + p++; + prev = aid; + } + + return _gnutls_buffer_append_data_prefix(extdata, 16, buffer, len); +} + + +/* Parses the Signature Algorithm structure and stores data into + * session->security_parameters.extensions. + */ +int +_gnutls_sign_algorithm_parse_data(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + unsigned int sig, i; + sig_ext_st *priv; + gnutls_ext_priv_data_t epriv; + const version_entry_st *ver = get_version(session); + + if (data_size == 0 || data_size % 2 != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (ver == NULL) { /* assume TLS 1.2 semantics */ + ver = version_to_entry(GNUTLS_TLS1_2); + if (unlikely(ver == NULL)) { + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } + } + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + for (i = 0; i < data_size; i += 2) { + uint8_t id[2]; + + id[0] = data[i]; + id[1] = data[i + 1]; + + sig = _gnutls_tls_aid_to_sign(id[0], id[1], ver); + + _gnutls_handshake_log + ("EXT[%p]: rcvd signature algo (%d.%d) %s\n", session, + (int)id[0], (int)id[1], + gnutls_sign_get_name(sig)); + + if (sig != GNUTLS_SIGN_UNKNOWN) { + if (priv->sign_algorithms_size == MAX_ALGOS) + break; + priv->sign_algorithms[priv-> + sign_algorithms_size++] = sig; + } + } + + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + epriv); + + return 0; +} + +/* + * In case of a server: if a SIGNATURE_ALGORITHMS extension type is + * received then it stores into the session security parameters the + * new value. + * + * In case of a client: If a signature_algorithms have been specified + * then it is an error; + */ + +static int +_gnutls_signature_algorithm_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size) +{ + int ret; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + /* nothing for now */ + gnutls_assert(); + /* Although TLS 1.2 mandates that we must not accept reply + * to this message, there are good reasons to just ignore it. Check + * https://www.ietf.org/mail-archive/web/tls/current/msg03880.html + */ + /* return GNUTLS_E_UNEXPECTED_PACKET; */ + } else { + /* SERVER SIDE + */ + if (data_size >= 2) { + uint16_t len; + + DECR_LEN(data_size, 2); + len = _gnutls_read_uint16(data); + DECR_LEN(data_size, len); + + if (data_size > 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + ret = + _gnutls_sign_algorithm_parse_data(session, + data + 2, + len); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } else { + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_signature_algorithm_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + int ret; + size_t init_length = extdata->length; + const version_entry_st *ver = get_version(session); + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + /* this function sends the client extension data */ + if (session->security_parameters.entity == GNUTLS_CLIENT + && _gnutls_version_has_selectable_sighash(ver)) { + if (session->internals.priorities->sigalg.size > 0) { + ret = + _gnutls_sign_algorithm_write_params(session, extdata); + if (ret < 0) + return gnutls_assert_val(ret); + + return extdata->length - init_length; + } + } + + /* if we are here it means we don't send the extension */ + return 0; +} + +#ifdef GOST_SIG_FIXUP_SCHANNEL +static bool +is_gost_sig_present(sig_ext_st *priv) +{ + unsigned i; + const gnutls_sign_entry_st *se; + + for (i = 0; i < priv->sign_algorithms_size; i++) { + se = _gnutls_sign_to_entry(priv->sign_algorithms[i]); + if (se != NULL && _sign_is_gost(se)) + return true; + } + + return false; +} +#endif + +/* Returns a requested by the peer signature algorithm that + * matches the given certificate's public key algorithm. + * + * When the @client_cert flag is not set, then this function will + * also check whether the signature algorithm is allowed to be + * used in that session. Otherwise GNUTLS_SIGN_UNKNOWN is + * returned. + */ +gnutls_sign_algorithm_t +_gnutls_session_get_sign_algo(gnutls_session_t session, + gnutls_pcert_st * cert, + gnutls_privkey_t privkey, + unsigned client_cert, + gnutls_kx_algorithm_t kx_algorithm) +{ + unsigned i; + int ret; + const version_entry_st *ver = get_version(session); + sig_ext_st *priv; + gnutls_ext_priv_data_t epriv; + unsigned int cert_algo; + const gnutls_sign_entry_st *se; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_SIGN_UNKNOWN); + + cert_algo = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL); + + ret = + _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + &epriv); + if (ret < 0) + priv = NULL; + else + priv = epriv; + +#ifdef GOST_SIG_FIXUP_SCHANNEL + /* + * Some (all SChannel) clients fail to send proper SigAlgs due to Micro$oft crazyness. + * If we are negotiating GOST KX (because we have received GOST + * ciphersuites) and if we have received no GOST SignatureAlgorithms, + * assume that the client could not send them and continue negotiation + * as if correct algorithm was sent. + */ + if (_gnutls_kx_is_vko_gost(kx_algorithm) && + (!priv || + !is_gost_sig_present(priv) || + !_gnutls_version_has_selectable_sighash(ver))) { + gnutls_digest_algorithm_t dig; + + _gnutls_handshake_log("EXT[%p]: GOST KX, but no GOST SigAlgs received, patching up.", session); + + if (cert_algo == GNUTLS_PK_GOST_01) + dig = GNUTLS_DIG_GOSTR_94; + else if (cert_algo == GNUTLS_PK_GOST_12_256) + dig = GNUTLS_DIG_STREEBOG_256; + else if (cert_algo == GNUTLS_PK_GOST_12_512) + dig = GNUTLS_DIG_STREEBOG_512; + else + dig = GNUTLS_DIG_SHA1; + + ret = gnutls_pk_to_sign(cert_algo, dig); + + if (!client_cert && _gnutls_session_sign_algo_enabled(session, ret) < 0) + goto fail; + return ret; + } +#endif + + if (!priv || !_gnutls_version_has_selectable_sighash(ver)) { + /* none set, allow SHA-1 only */ + ret = gnutls_pk_to_sign(cert_algo, GNUTLS_DIG_SHA1); + + if (!client_cert && _gnutls_session_sign_algo_enabled(session, ret) < 0) + goto fail; + return ret; + } + + + + for (i = 0; i < priv->sign_algorithms_size; i++) { + se = _gnutls_sign_to_entry(priv->sign_algorithms[i]); + if (se == NULL) + continue; + + _gnutls_handshake_log("checking cert compat with %s\n", se->name); + + if (_gnutls_privkey_compatible_with_sig(privkey, priv->sign_algorithms[i]) == 0) + continue; + + if (sign_supports_cert_pk_algorithm(se, cert_algo) != 0) { + if (_gnutls_pubkey_compatible_with_sig + (session, cert->pubkey, ver, se->id) < 0) + continue; + + if (_gnutls_session_sign_algo_enabled + (session, se->id) < 0) + continue; + + return se->id; + } + } + + /* When having a legacy client certificate which can only be signed + * using algorithms we don't always enable by default (e.g., DSA-SHA1), + * continue and sign with it. */ + if (client_cert) { + _gnutls_audit_log(session, "No shared signature schemes with peer for client certificate (%s). Is the certificate a legacy one?\n", + gnutls_pk_get_name(cert_algo)); + } + + fail: + return GNUTLS_SIGN_UNKNOWN; +} + +/* Check if the given signature algorithm is supported. + * This means that it is enabled by the priority functions, + * and in case of a server a matching certificate exists. + */ +int +_gnutls_session_sign_algo_enabled(gnutls_session_t session, + gnutls_sign_algorithm_t sig) +{ + unsigned i; + const version_entry_st *ver = get_version(session); + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + if (!_gnutls_version_has_selectable_sighash(ver)) { + return 0; + } + + if (ver->tls13_sem) { + /* disallow RSA, DSA, and SHA1 */ + const gnutls_sign_entry_st *se; + + se = _gnutls_sign_to_entry(sig); + if (se == NULL || (se->flags & GNUTLS_SIGN_FLAG_TLS13_OK) == 0) { + gnutls_assert(); + goto disallowed; + } + } + + for (i = 0; i < session->internals.priorities->sigalg.size; i++) { + if (session->internals.priorities->sigalg.entry[i]->id == sig) { + return 0; /* ok */ + } + } + + disallowed: + _gnutls_handshake_log("Signature algorithm %s is not enabled\n", gnutls_sign_algorithm_get_name(sig)); + return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; +} + +static void signature_algorithms_deinit_data(gnutls_ext_priv_data_t priv) +{ + gnutls_free(priv); +} + +static int +signature_algorithms_pack(gnutls_ext_priv_data_t epriv, + gnutls_buffer_st * ps) +{ + sig_ext_st *priv = epriv; + int ret, i; + + BUFFER_APPEND_NUM(ps, priv->sign_algorithms_size); + for (i = 0; i < priv->sign_algorithms_size; i++) { + BUFFER_APPEND_NUM(ps, priv->sign_algorithms[i]); + } + return 0; +} + +static int +signature_algorithms_unpack(gnutls_buffer_st * ps, + gnutls_ext_priv_data_t * _priv) +{ + sig_ext_st *priv; + int i, ret; + gnutls_ext_priv_data_t epriv; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_NUM(ps, priv->sign_algorithms_size); + for (i = 0; i < priv->sign_algorithms_size; i++) { + BUFFER_POP_NUM(ps, priv->sign_algorithms[i]); + } + + epriv = priv; + *_priv = epriv; + + return 0; + + error: + gnutls_free(priv); + return ret; +} + + + +/** + * gnutls_sign_algorithm_get_requested: + * @session: is a #gnutls_session_t type. + * @indx: is an index of the signature algorithm to return + * @algo: the returned certificate type will be stored there + * + * Returns the signature algorithm specified by index that was + * requested by the peer. If the specified index has no data available + * this function returns %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE. If + * the negotiated TLS version does not support signature algorithms + * then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned even + * for the first index. The first index is 0. + * + * This function is useful in the certificate callback functions + * to assist in selecting the correct certificate. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise + * an error code is returned. + * + * Since: 2.10.0 + **/ +int +gnutls_sign_algorithm_get_requested(gnutls_session_t session, + size_t indx, + gnutls_sign_algorithm_t * algo) +{ + const version_entry_st *ver = get_version(session); + sig_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int ret; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = + _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS, + &epriv); + if (ret < 0) { + gnutls_assert(); + return ret; + } + priv = epriv; + + if (!_gnutls_version_has_selectable_sighash(ver) + || priv->sign_algorithms_size == 0) { + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if (indx < priv->sign_algorithms_size) { + *algo = priv->sign_algorithms[indx]; + return 0; + } else + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; +} + +/** + * gnutls_sign_algorithm_get: + * @session: is a #gnutls_session_t type. + * + * Returns the signature algorithm that is (or will be) used in this + * session by the server to sign data. This function should be + * used only with TLS 1.2 or later. + * + * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN. + * + * Since: 3.1.1 + **/ +int gnutls_sign_algorithm_get(gnutls_session_t session) +{ + return session->security_parameters.server_sign_algo; +} + +/** + * gnutls_sign_algorithm_get_client: + * @session: is a #gnutls_session_t type. + * + * Returns the signature algorithm that is (or will be) used in this + * session by the client to sign data. This function should be + * used only with TLS 1.2 or later. + * + * Returns: The sign algorithm or %GNUTLS_SIGN_UNKNOWN. + * + * Since: 3.1.11 + **/ +int gnutls_sign_algorithm_get_client(gnutls_session_t session) +{ + return session->security_parameters.client_sign_algo; +} diff --git a/lib/ext/signature.h b/lib/ext/signature.h new file mode 100644 index 0000000..ef42763 --- /dev/null +++ b/lib/ext/signature.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2002-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SIGNATURE_H +#define GNUTLS_LIB_EXT_SIGNATURE_H + +/* signature algorithms extension + */ + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_sig; + +gnutls_sign_algorithm_t +_gnutls_session_get_sign_algo(gnutls_session_t session, + gnutls_pcert_st * cert, + gnutls_privkey_t privkey, + unsigned client_cert, + gnutls_kx_algorithm_t kx_algorithm); +int _gnutls_sign_algorithm_parse_data(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +int _gnutls_sign_algorithm_write_params(gnutls_session_t session, + gnutls_buffer_st * extdata); +int _gnutls_session_sign_algo_enabled(gnutls_session_t session, + gnutls_sign_algorithm_t sig); + +static inline void +gnutls_sign_algorithm_set_server(gnutls_session_t session, + gnutls_sign_algorithm_t sign) +{ + session->security_parameters.server_sign_algo = sign; +} + +static inline void +gnutls_sign_algorithm_set_client(gnutls_session_t session, + gnutls_sign_algorithm_t sign) +{ + session->security_parameters.client_sign_algo = sign; +} + +#endif /* GNUTLS_LIB_EXT_SIGNATURE_H */ diff --git a/lib/ext/srp.c b/lib/ext/srp.c new file mode 100644 index 0000000..f236c64 --- /dev/null +++ b/lib/ext/srp.c @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2001-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include <ext/srp.h> + +#ifdef ENABLE_SRP + +#include "auth.h" +#include <auth/srp_kx.h> +#include "errors.h" +#include "algorithms.h" +#include <num.h> +#include <hello_ext.h> + +static int _gnutls_srp_unpack(gnutls_buffer_st * ps, + gnutls_ext_priv_data_t * _priv); +static int _gnutls_srp_pack(gnutls_ext_priv_data_t epriv, + gnutls_buffer_st * ps); +static void _gnutls_srp_deinit_data(gnutls_ext_priv_data_t epriv); +static int _gnutls_srp_recv_params(gnutls_session_t state, + const uint8_t * data, size_t data_size); +static int _gnutls_srp_send_params(gnutls_session_t state, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_srp = { + .name = "SRP", + .tls_id = 12, + .gid = GNUTLS_EXTENSION_SRP, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO, + .recv_func = _gnutls_srp_recv_params, + .send_func = _gnutls_srp_send_params, + .pack_func = _gnutls_srp_pack, + .unpack_func = _gnutls_srp_unpack, + .deinit_func = _gnutls_srp_deinit_data, + .cannot_be_overriden = 1 +}; + + +static int +_gnutls_srp_recv_params(gnutls_session_t session, const uint8_t * data, + size_t data_size) +{ + uint8_t len; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (data_size > 0) { + DECR_LEN(data_size, 1); + + len = data[0]; + DECR_LEN(data_size, len); + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + priv->username = gnutls_malloc(len + 1); + if (priv->username) { + memcpy(priv->username, &data[1], len); + /* null terminated */ + priv->username[len] = 0; + } + + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SRP, + epriv); + } + } + return 0; +} + +static unsigned have_srp_ciphersuites(gnutls_session_t session) +{ + unsigned j; + unsigned kx; + + for (j = 0; j < session->internals.priorities->cs.size; j++) { + kx = session->internals.priorities->cs.entry[j]->kx_algorithm; + if (kx == GNUTLS_KX_SRP || kx == GNUTLS_KX_SRP_RSA || kx == GNUTLS_KX_SRP_DSS) + return 1; + } + + return 0; +} + +/* returns data_size or a negative number on failure + * data is allocated locally + */ +static int +_gnutls_srp_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + unsigned len; + int ret; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv = NULL; + char *username = NULL, *password = NULL; + gnutls_srp_client_credentials_t cred = + (gnutls_srp_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_SRP); + + if (session->security_parameters.entity != GNUTLS_CLIENT) + return 0; + + if (cred == NULL) + return 0; + + if (!have_srp_ciphersuites(session)) { + return 0; + } + + /* this function sends the client extension data (username) */ + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + if (cred->username != NULL) { /* send username */ + len = MIN(strlen(cred->username), 255); + + ret = + _gnutls_buffer_append_data_prefix(extdata, 8, + cred-> + username, + len); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + priv->username = gnutls_strdup(cred->username); + if (priv->username == NULL) { + gnutls_assert(); + goto cleanup; + } + + priv->password = gnutls_strdup(cred->password); + if (priv->password == NULL) { + gnutls_assert(); + goto cleanup; + } + + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SRP, + epriv); + + return len + 1; + } else if (cred->get_function != NULL) { + /* Try the callback + */ + + if (cred-> + get_function(session, &username, &password) < 0 + || username == NULL || password == NULL) { + gnutls_assert(); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; + } + + len = MIN(strlen(username), 255); + + priv->username = username; + priv->password = password; + + ret = + _gnutls_buffer_append_data_prefix(extdata, 8, + username, + len); + if (ret < 0) { + ret = gnutls_assert_val(ret); + goto cleanup; + } + + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SRP, + epriv); + + return len + 1; + } + return 0; + + cleanup: + gnutls_free(username); + gnutls_free(password); + gnutls_free(priv); + + return ret; +} + +static void _gnutls_srp_deinit_data(gnutls_ext_priv_data_t epriv) +{ + srp_ext_st *priv = epriv; + + gnutls_free(priv->username); + gnutls_free(priv->password); + gnutls_free(priv); +} + +static int +_gnutls_srp_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps) +{ + srp_ext_st *priv = epriv; + int ret; + int password_len = 0, username_len = 0; + + if (priv->username) + username_len = strlen(priv->username); + + if (priv->password) + password_len = strlen(priv->password); + + BUFFER_APPEND_PFX4(ps, priv->username, username_len); + BUFFER_APPEND_PFX4(ps, priv->password, password_len); + + return 0; +} + +static int +_gnutls_srp_unpack(gnutls_buffer_st * ps, gnutls_ext_priv_data_t * _priv) +{ + srp_ext_st *priv; + int ret; + gnutls_ext_priv_data_t epriv; + gnutls_datum_t username = { NULL, 0 }; + gnutls_datum_t password = { NULL, 0 }; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_DATUM(ps, &username); + BUFFER_POP_DATUM(ps, &password); + + priv->username = (char *) username.data; + priv->password = (char *) password.data; + + epriv = priv; + *_priv = epriv; + + return 0; + + error: + _gnutls_free_datum(&username); + _gnutls_free_datum(&password); + return ret; +} + + +#endif /* ENABLE_SRP */ diff --git a/lib/ext/srp.h b/lib/ext/srp.h new file mode 100644 index 0000000..fd7576f --- /dev/null +++ b/lib/ext/srp.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2000-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SRP_H +#define GNUTLS_LIB_EXT_SRP_H + +#include <hello_ext.h> + +#define IS_SRP_KX(kx) ((kx == GNUTLS_KX_SRP || (kx == GNUTLS_KX_SRP_RSA) || \ + kx == GNUTLS_KX_SRP_DSS)?1:0) + +#ifdef ENABLE_SRP + +extern const hello_ext_entry_st ext_mod_srp; + +typedef struct { + char *username; + char *password; +} srp_ext_st; + +#endif + +#endif /* GNUTLS_LIB_EXT_SRP_H */ diff --git a/lib/ext/srtp.c b/lib/ext/srtp.c new file mode 100644 index 0000000..b2e36b3 --- /dev/null +++ b/lib/ext/srtp.c @@ -0,0 +1,672 @@ +/* + * Copyright (C) 2012 Free Software Foundation + * + * Author: Martin Storsjo + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "num.h" +#include <ext/srtp.h> + +static int _gnutls_srtp_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_srtp_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +static int _gnutls_srtp_unpack(gnutls_buffer_st * ps, + gnutls_ext_priv_data_t * _priv); +static int _gnutls_srtp_pack(gnutls_ext_priv_data_t _priv, + gnutls_buffer_st * ps); +static void _gnutls_srtp_deinit_data(gnutls_ext_priv_data_t priv); + + +const hello_ext_entry_st ext_mod_srtp = { + .name = "SRTP", + .tls_id = 14, + .gid = GNUTLS_EXTENSION_SRTP, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .client_parse_point = GNUTLS_EXT_APPLICATION, + .server_parse_point = GNUTLS_EXT_APPLICATION, + .recv_func = _gnutls_srtp_recv_params, + .send_func = _gnutls_srtp_send_params, + .pack_func = _gnutls_srtp_pack, + .unpack_func = _gnutls_srtp_unpack, + .deinit_func = _gnutls_srtp_deinit_data, + .cannot_be_overriden = 1 +}; + +typedef struct { + const char *name; + gnutls_srtp_profile_t id; + unsigned int key_length; + unsigned int salt_length; +} srtp_profile_st; + +static const srtp_profile_st profile_names[] = { + { + "SRTP_AES128_CM_HMAC_SHA1_80", + GNUTLS_SRTP_AES128_CM_HMAC_SHA1_80, + 16, 14}, + { + "SRTP_AES128_CM_HMAC_SHA1_32", + GNUTLS_SRTP_AES128_CM_HMAC_SHA1_32, + 16, 14}, + { + "SRTP_NULL_HMAC_SHA1_80", + GNUTLS_SRTP_NULL_HMAC_SHA1_80, + 16, 14}, + { + "SRTP_NULL_SHA1_32", + GNUTLS_SRTP_NULL_HMAC_SHA1_32, + 16, 14}, + { + NULL, + 0, 0, 0} +}; + +static const srtp_profile_st *get_profile(gnutls_srtp_profile_t profile) +{ + const srtp_profile_st *p = profile_names; + while (p->name != NULL) { + if (p->id == profile) + return p; + p++; + } + return NULL; +} + +static gnutls_srtp_profile_t find_profile(const char *str, const char *end) +{ + const srtp_profile_st *prof = profile_names; + unsigned int len; + if (end != NULL) { + len = end - str; + } else { + len = strlen(str); + } + + while (prof->name != NULL) { + if (strlen(prof->name) == len + && !strncmp(str, prof->name, len)) { + return prof->id; + } + prof++; + } + return 0; +} + +/** + * gnutls_srtp_get_profile_id + * @name: The name of the profile to look up + * @profile: Will hold the profile id + * + * This function allows you to look up a profile based on a string. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.1.4 + **/ +int gnutls_srtp_get_profile_id(const char *name, + gnutls_srtp_profile_t * profile) +{ + *profile = find_profile(name, NULL); + if (*profile == 0) { + return GNUTLS_E_ILLEGAL_PARAMETER; + } + return 0; +} + +#define MAX_PROFILES_IN_SRTP_EXTENSION 256 + +/** + * gnutls_srtp_get_profile_name + * @profile: The profile to look up a string for + * + * This function allows you to get the corresponding name for a + * SRTP protection profile. + * + * Returns: On success, the name of a SRTP profile as a string, + * otherwise NULL. + * + * Since 3.1.4 + **/ +const char *gnutls_srtp_get_profile_name(gnutls_srtp_profile_t profile) +{ + const srtp_profile_st *p = get_profile(profile); + + if (p != NULL) + return p->name; + + return NULL; +} + +static int +_gnutls_srtp_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + unsigned int i; + int ret; + const uint8_t *p = data; + size_t len; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + uint16_t profile; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) + return 0; + + priv = epriv; + + DECR_LENGTH_RET(data_size, 2, 0); + len = _gnutls_read_uint16(p); + p += 2; + + if (len + 1 > data_size) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (session->security_parameters.entity == GNUTLS_SERVER) { + if (len > MAX_PROFILES_IN_SRTP_EXTENSION * 2) + return 0; + } else { + if (len != 2) + return + gnutls_assert_val + (GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } + + priv->selected_profile = 0; + + while (len > 0) { + DECR_LEN(data_size, 2); + profile = _gnutls_read_uint16(p); + + for (i = 0; + i < priv->profiles_size + && priv->selected_profile == 0; i++) { + if (priv->profiles[i] == profile) { + priv->selected_profile = profile; + break; + } + } + p += 2; + len -= 2; + } + + DECR_LEN(data_size, 1); + priv->mki_size = *p; + p++; + + if (priv->mki_size > 0) { + DECR_LEN(data_size, priv->mki_size); + memcpy(priv->mki, p, priv->mki_size); + priv->mki_received = 1; + } + + return 0; +} + +static int +_gnutls_srtp_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + unsigned i; + int total_size = 0, ret; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) + return 0; + + priv = epriv; + + if (priv->profiles_size == 0) + return 0; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + /* Don't send anything if no matching profile was found */ + if (priv->selected_profile == 0) + return 0; + + ret = _gnutls_buffer_append_prefix(extdata, 16, 2); + if (ret < 0) + return gnutls_assert_val(ret); + ret = + _gnutls_buffer_append_prefix(extdata, 16, + priv->selected_profile); + if (ret < 0) + return gnutls_assert_val(ret); + total_size = 4; + } else { + ret = + _gnutls_buffer_append_prefix(extdata, 16, + 2 * priv->profiles_size); + if (ret < 0) + return gnutls_assert_val(ret); + + for (i = 0; i < priv->profiles_size; i++) { + ret = + _gnutls_buffer_append_prefix(extdata, 16, + priv-> + profiles[i]); + if (ret < 0) + return gnutls_assert_val(ret); + } + total_size = 2 + 2 * priv->profiles_size; + } + + /* use_mki */ + ret = + _gnutls_buffer_append_data_prefix(extdata, 8, priv->mki, + priv->mki_size); + if (ret < 0) + return gnutls_assert_val(ret); + total_size += 1 + priv->mki_size; + + return total_size; +} + +/** + * gnutls_srtp_get_selected_profile: + * @session: is a #gnutls_session_t type. + * @profile: will hold the profile + * + * This function allows you to get the negotiated SRTP profile. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.1.4 + **/ +int +gnutls_srtp_get_selected_profile(gnutls_session_t session, + gnutls_srtp_profile_t * profile) +{ + srtp_ext_st *priv; + int ret; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + priv = epriv; + + if (priv->selected_profile == 0) { + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + *profile = priv->selected_profile; + + return 0; +} + +/** + * gnutls_srtp_get_mki: + * @session: is a #gnutls_session_t type. + * @mki: will hold the MKI + * + * This function exports the negotiated Master Key Identifier, + * received by the peer if any. The returned value in @mki should be + * treated as constant and valid only during the session's lifetime. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.1.4 + **/ +int gnutls_srtp_get_mki(gnutls_session_t session, gnutls_datum_t * mki) +{ + srtp_ext_st *priv; + int ret; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + priv = epriv; + + if (priv->mki_received == 0) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + mki->data = priv->mki; + mki->size = priv->mki_size; + + return 0; +} + +/** + * gnutls_srtp_set_mki: + * @session: is a #gnutls_session_t type. + * @mki: holds the MKI + * + * This function sets the Master Key Identifier, to be + * used by this session (if any). + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.1.4 + **/ +int +gnutls_srtp_set_mki(gnutls_session_t session, const gnutls_datum_t * mki) +{ + int ret; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SRTP, epriv); + } else + priv = epriv; + + if (mki->size > 0 && mki->size <= sizeof(priv->mki)) { + priv->mki_size = mki->size; + memcpy(priv->mki, mki->data, mki->size); + } else + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + return 0; +} + +/** + * gnutls_srtp_set_profile: + * @session: is a #gnutls_session_t type. + * @profile: is the profile id to add. + * + * This function is to be used by both clients and servers, to declare + * what SRTP profiles they support, to negotiate with the peer. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since 3.1.4 + **/ +int +gnutls_srtp_set_profile(gnutls_session_t session, + gnutls_srtp_profile_t profile) +{ + int ret; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) { + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SRTP, epriv); + } else + priv = epriv; + + if (priv->profiles_size < MAX_SRTP_PROFILES) + priv->profiles_size++; + priv->profiles[priv->profiles_size - 1] = profile; + + return 0; +} + +/** + * gnutls_srtp_set_profile_direct: + * @session: is a #gnutls_session_t type. + * @profiles: is a string that contains the supported SRTP profiles, + * separated by colons. + * @err_pos: In case of an error this will have the position in the string the error occurred, may be NULL. + * + * This function is to be used by both clients and servers, to declare + * what SRTP profiles they support, to negotiate with the peer. + * + * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned, + * %GNUTLS_E_SUCCESS on success, or an error code. + * + * Since 3.1.4 + **/ +int +gnutls_srtp_set_profile_direct(gnutls_session_t session, + const char *profiles, const char **err_pos) +{ + int ret; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int set = 0; + const char *col; + gnutls_srtp_profile_t id; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRTP, + &epriv); + if (ret < 0) { + set = 1; + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + if (err_pos != NULL) + *err_pos = profiles; + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + epriv = priv; + } else + priv = epriv; + + do { + col = strchr(profiles, ':'); + id = find_profile(profiles, col); + if (id == 0) { + if (set != 0) + gnutls_free(priv); + if (err_pos != NULL) + *err_pos = profiles; + return GNUTLS_E_INVALID_REQUEST; + } + + if (priv->profiles_size < MAX_SRTP_PROFILES) { + priv->profiles_size++; + } + priv->profiles[priv->profiles_size - 1] = id; + profiles = col + 1; + } while (col != NULL); + + if (set != 0) + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_SRTP, epriv); + + return 0; +} + +/** + * gnutls_srtp_get_keys: + * @session: is a #gnutls_session_t type. + * @key_material: Space to hold the generated key material + * @key_material_size: The maximum size of the key material + * @client_key: The master client write key, pointing inside the key material + * @server_key: The master server write key, pointing inside the key material + * @client_salt: The master client write salt, pointing inside the key material + * @server_salt: The master server write salt, pointing inside the key material + * + * This is a helper function to generate the keying material for SRTP. + * It requires the space of the key material to be pre-allocated (should be at least + * 2x the maximum key size and salt size). The @client_key, @client_salt, @server_key + * and @server_salt are convenience datums that point inside the key material. They may + * be %NULL. + * + * Returns: On success the size of the key material is returned, + * otherwise, %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not + * sufficient, or a negative error code. + * + * Since 3.1.4 + **/ +int +gnutls_srtp_get_keys(gnutls_session_t session, + void *key_material, + unsigned int key_material_size, + gnutls_datum_t * client_key, + gnutls_datum_t * client_salt, + gnutls_datum_t * server_key, + gnutls_datum_t * server_salt) +{ + int ret; + const srtp_profile_st *p; + gnutls_srtp_profile_t profile; + unsigned int msize; + uint8_t *km = key_material; + + ret = gnutls_srtp_get_selected_profile(session, &profile); + if (ret < 0) + return gnutls_assert_val(ret); + + p = get_profile(profile); + if (p == NULL) + return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM); + + msize = 2 * (p->key_length + p->salt_length); + if (msize > key_material_size) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + + if (msize == 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = + gnutls_prf(session, sizeof("EXTRACTOR-dtls_srtp") - 1, + "EXTRACTOR-dtls_srtp", 0, 0, NULL, msize, + key_material); + if (ret < 0) + return gnutls_assert_val(ret); + + if (client_key) { + client_key->data = km; + client_key->size = p->key_length; + } + + if (server_key) { + server_key->data = km + p->key_length; + server_key->size = p->key_length; + } + + if (client_salt) { + client_salt->data = km + 2 * p->key_length; + client_salt->size = p->salt_length; + } + + if (server_salt) { + server_salt->data = + km + 2 * p->key_length + p->salt_length; + server_salt->size = p->salt_length; + } + + return msize; +} + +static void _gnutls_srtp_deinit_data(gnutls_ext_priv_data_t priv) +{ + gnutls_free(priv); +} + +static int +_gnutls_srtp_pack(gnutls_ext_priv_data_t epriv, gnutls_buffer_st * ps) +{ + srtp_ext_st *priv = epriv; + unsigned int i; + int ret; + + BUFFER_APPEND_NUM(ps, priv->profiles_size); + for (i = 0; i < priv->profiles_size; i++) { + BUFFER_APPEND_NUM(ps, priv->profiles[i]); + } + + BUFFER_APPEND_NUM(ps, priv->mki_received); + if (priv->mki_received) { + BUFFER_APPEND_NUM(ps, priv->selected_profile); + BUFFER_APPEND_PFX4(ps, priv->mki, priv->mki_size); + } + return 0; +} + +static int +_gnutls_srtp_unpack(gnutls_buffer_st * ps, gnutls_ext_priv_data_t * _priv) +{ + srtp_ext_st *priv; + unsigned int i; + int ret; + gnutls_ext_priv_data_t epriv; + + priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + BUFFER_POP_NUM(ps, priv->profiles_size); + for (i = 0; i < priv->profiles_size; i++) { + BUFFER_POP_NUM(ps, priv->profiles[i]); + } + BUFFER_POP_NUM(ps, priv->selected_profile); + + BUFFER_POP_NUM(ps, priv->mki_received); + if (priv->mki_received) { + BUFFER_POP_NUM(ps, priv->mki_size); + BUFFER_POP(ps, priv->mki, priv->mki_size); + } + + epriv = priv; + *_priv = epriv; + + return 0; + + error: + gnutls_free(priv); + return ret; +} diff --git a/lib/ext/srtp.h b/lib/ext/srtp.h new file mode 100644 index 0000000..d05454a --- /dev/null +++ b/lib/ext/srtp.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 Free Software Foundation + * + * Author: Martin Storsjo + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SRTP_H +#define GNUTLS_LIB_EXT_SRTP_H +#ifndef EXT_SRTP_H +#define EXT_SRTP_H + +#include <hello_ext.h> + +#define MAX_SRTP_PROFILES 4 + +typedef struct { + gnutls_srtp_profile_t profiles[MAX_SRTP_PROFILES]; + unsigned profiles_size; + gnutls_srtp_profile_t selected_profile; + uint8_t mki[256]; + unsigned mki_size; + unsigned int mki_received; +} srtp_ext_st; + +extern const hello_ext_entry_st ext_mod_srtp; + +#endif + +#endif /* GNUTLS_LIB_EXT_SRTP_H */ diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c new file mode 100644 index 0000000..1e89286 --- /dev/null +++ b/lib/ext/status_request.c @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2012-2017 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Simon Josefsson, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* + Status Request (OCSP) TLS extension. See RFC 6066 section 8: + https://tools.ietf.org/html/rfc6066#section-8 +*/ + +#include "gnutls_int.h" +#include "errors.h" +#include <hello_ext.h> +#include <ext/status_request.h> +#include <mbuffers.h> +#include <auth.h> +#include <auth/cert.h> +#include <handshake.h> + +#ifdef ENABLE_OCSP + +typedef struct { + /* server response */ + gnutls_datum_t sresp; + + unsigned int expect_cstatus; +} status_request_ext_st; + +/* + From RFC 6066. Client sends: + + struct { + CertificateStatusType status_type; + select (status_type) { + case ocsp: OCSPStatusRequest; + } request; + } CertificateStatusRequest; + + enum { ocsp(1), (255) } CertificateStatusType; + + struct { + ResponderID responder_id_list<0..2^16-1>; + Extensions request_extensions; + } OCSPStatusRequest; + + opaque ResponderID<1..2^16-1>; + opaque Extensions<0..2^16-1>; +*/ + + +static int +client_send(gnutls_session_t session, + gnutls_buffer_st * extdata, status_request_ext_st * priv) +{ + const uint8_t data[5] = "\x01\x00\x00\x00\x00"; + const int len = 5; + int ret; + + /* We do not support setting either ResponderID or Extensions */ + + ret = _gnutls_buffer_append_data(extdata, data, len); + if (ret < 0) + return gnutls_assert_val(ret); + + session->internals.hsk_flags |= HSK_OCSP_REQUESTED; + + return len; +} + +static int +server_recv(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + unsigned rid_bytes = 0; + + /* minimum message is type (1) + responder_id_list (2) + + request_extension (2) = 5 */ + if (data_size < 5) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* We ignore non-ocsp CertificateStatusType. The spec is unclear + what should be done. */ + if (data[0] != 0x01) { + gnutls_assert(); + _gnutls_handshake_log("EXT[%p]: unknown status_type %d\n", + session, data[0]); + return 0; + } + DECR_LEN(data_size, 1); + data++; + + rid_bytes = _gnutls_read_uint16(data); + + DECR_LEN(data_size, 2); + /*data += 2;*/ + + /* sanity check only, we don't use any of the data below */ + + if (data_size < rid_bytes) + return + gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + _gnutls_handshake_log("EXT[%p]: OCSP status was requested\n", session); + session->internals.hsk_flags |= HSK_OCSP_REQUESTED; + + return 0; +} + + +static int +client_recv(gnutls_session_t session, + status_request_ext_st * priv, + const uint8_t * data, size_t size) +{ + if (size != 0) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + else { + priv->expect_cstatus = 1; + return 0; + } +} + + +/* + * Servers return a certificate response along with their certificate + * by sending a "CertificateStatus" message immediately after the + * "Certificate" message (and before any "ServerKeyExchange" or + * "CertificateRequest" messages). If a server returns a + * "CertificateStatus" message, then the server MUST have included an + * extension of type "status_request" with empty "extension_data" in + * the extended server hello. + * + * According to the description above, as a server we could simply + * return GNUTLS_E_INT_RET_0 on this function. In that case we would + * only need to use the callbacks at the time we need to send the data, + * and skip the status response packet if no such data are there. + * However, that behavior would break gnutls 3.3.x which expects the status + * response to be always send if the extension is present. + * + * Instead we ensure that this extension is parsed after the CS/certificate + * are selected (with the _GNUTLS_EXT_TLS_POST_CS type), and we discover + * (or not) the response to send early. + */ +static int +server_send(gnutls_session_t session, + gnutls_buffer_st * extdata, status_request_ext_st * priv) +{ + int ret; + gnutls_certificate_credentials_t cred; + gnutls_status_request_ocsp_func func; + void *func_ptr; + const version_entry_st *ver = get_version(session); + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) /* no certificate authentication */ + return 0; + + /* no need to set sresp; responses are send during certificate sending and + * no response is required from server side. */ + if (ver && ver->multi_ocsp) + return 0; + + /* Under TLS1.2 we obtain the response at this point in order to respond + * appropriately (empty extension vs no response) */ + if (session->internals.selected_ocsp_length > 0) { + if (session->internals.selected_ocsp[0].response.data) { + if (session->internals.selected_ocsp[0].exptime != 0 && + (gnutls_time(0) >= session->internals.selected_ocsp[0].exptime)) { + gnutls_assert(); + return 0; + } + + ret = _gnutls_set_datum(&priv->sresp, + session->internals.selected_ocsp[0].response.data, + session->internals.selected_ocsp[0].response.size); + if (ret < 0) + return gnutls_assert_val(ret); + return GNUTLS_E_INT_RET_0; + } else { + return 0; + } + } else if (session->internals.selected_ocsp_func) { + func = session->internals.selected_ocsp_func; + func_ptr = session->internals.selected_ocsp_func_ptr; + + if (func == NULL) + return 0; + + ret = func(session, func_ptr, &priv->sresp); + if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS) + return 0; + else if (ret < 0) + return gnutls_assert_val(ret); + } else { + return 0; + } + + return GNUTLS_E_INT_RET_0; +} + +static int +_gnutls_status_request_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + gnutls_ext_priv_data_t epriv; + status_request_ext_st *priv; + int ret; + + /* Do not bother sending the OCSP status request extension + * if we are not using certificate authentication */ + if (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL) + return 0; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + &epriv); + if (ret < 0 || epriv == NULL) /* it is ok not to have it */ + return 0; + priv = epriv; + + return client_send(session, extdata, priv); + } else { + epriv = priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + epriv); + + return server_send(session, extdata, priv); + } +} + +static int +_gnutls_status_request_recv_params(gnutls_session_t session, + const uint8_t * data, size_t size) +{ + gnutls_ext_priv_data_t epriv; + status_request_ext_st *priv; + int ret; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + ret = _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + &epriv); + if (ret < 0 || epriv == NULL) /* it is ok not to have it */ + return 0; + priv = epriv; + + return client_recv(session, priv, data, size); + } else { + return server_recv(session, data, size); + } +} + +/** + * gnutls_ocsp_status_request_enable_client: + * @session: is a #gnutls_session_t type. + * @responder_id: ignored, must be %NULL + * @responder_id_size: ignored, must be zero + * @extensions: ignored, must be %NULL + * + * This function is to be used by clients to request OCSP response + * from the server, using the "status_request" TLS extension. Only + * OCSP status type is supported. + * + * Previous versions of GnuTLS supported setting @responder_id and + * @extensions fields, but due to the difficult semantics of the + * parameter usage, and other issues, this support was removed + * since 3.6.0 and these parameters must be set to %NULL. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since: 3.1.3 + **/ +int +gnutls_ocsp_status_request_enable_client(gnutls_session_t session, + gnutls_datum_t * responder_id, + size_t responder_id_size, + gnutls_datum_t * extensions) +{ + status_request_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + if (session->security_parameters.entity == GNUTLS_SERVER) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + epriv = priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + _gnutls_hello_ext_set_priv(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + epriv); + + return 0; +} + + +static void _gnutls_status_request_deinit_data(gnutls_ext_priv_data_t epriv) +{ + status_request_ext_st *priv = epriv; + + if (priv == NULL) + return; + + gnutls_free(priv->sresp.data); + gnutls_free(priv); +} + +const hello_ext_entry_st ext_mod_status_request = { + .name = "OCSP Status Request", + .tls_id = STATUS_REQUEST_TLS_ID, + .gid = GNUTLS_EXTENSION_STATUS_REQUEST, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .client_parse_point = _GNUTLS_EXT_TLS_POST_CS, + .server_parse_point = _GNUTLS_EXT_TLS_POST_CS, + .recv_func = _gnutls_status_request_recv_params, + .send_func = _gnutls_status_request_send_params, + .deinit_func = _gnutls_status_request_deinit_data, + .cannot_be_overriden = 1 +}; + +/* Functions to be called from handshake */ + +int +_gnutls_send_server_certificate_status(gnutls_session_t session, int again) +{ + mbuffer_st *bufel = NULL; + uint8_t *data; + int data_size = 0; + int ret; + gnutls_ext_priv_data_t epriv; + status_request_ext_st *priv; + + if (!(session->internals.hsk_flags & HSK_OCSP_REQUESTED)) + return 0; + + if (again == 0) { + ret = + _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + &epriv); + if (ret < 0) + return 0; + + priv = epriv; + + if (!priv->sresp.size) + return 0; + + data_size = priv->sresp.size + 4; + bufel = + _gnutls_handshake_alloc(session, data_size); + if (!bufel) { + _gnutls_free_datum(&priv->sresp); + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + data = _mbuffer_get_udata_ptr(bufel); + + data[0] = 0x01; + _gnutls_write_uint24(priv->sresp.size, &data[1]); + memcpy(&data[4], priv->sresp.data, priv->sresp.size); + + _gnutls_free_datum(&priv->sresp); + } + return _gnutls_send_handshake(session, data_size ? bufel : NULL, + GNUTLS_HANDSHAKE_CERTIFICATE_STATUS); +} + +int _gnutls_parse_ocsp_response(gnutls_session_t session, const uint8_t *data, ssize_t data_size, gnutls_datum_t *resp) +{ + int ret; + ssize_t r_size; + + resp->data = 0; + resp->size = 0; + + /* minimum message is type (1) + response (3) + data */ + if (data_size < 4) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (data[0] != 0x01) { + gnutls_assert(); + _gnutls_handshake_log("EXT[%p]: unknown status_type %d\n", + session, data[0]); + return 0; + } + + DECR_LENGTH_RET(data_size, 1, + GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + data++; + + DECR_LENGTH_RET(data_size, 3, + GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + r_size = _gnutls_read_uint24(data); + data += 3; + + DECR_LENGTH_RET(data_size, r_size, + GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (r_size < 1) + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + ret = _gnutls_set_datum(resp, data, r_size); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + +int _gnutls_recv_server_certificate_status(gnutls_session_t session) +{ + uint8_t *data; + ssize_t data_size; + gnutls_buffer_st buf; + int ret; + gnutls_datum_t resp; + status_request_ext_st *priv = NULL; + gnutls_ext_priv_data_t epriv; + cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + + if (info == NULL) + return 0; + + ret = + _gnutls_hello_ext_get_priv(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + &epriv); + if (ret < 0) + return 0; + + priv = epriv; + + if (!priv->expect_cstatus) + return 0; + + ret = _gnutls_recv_handshake(session, + GNUTLS_HANDSHAKE_CERTIFICATE_STATUS, + 1, &buf); + if (ret < 0) + return gnutls_assert_val_fatal(ret); + + priv->expect_cstatus = 0; + + data = buf.data; + data_size = buf.length; + + if (data_size == 0) { + ret = 0; + goto error; + } + + ret = _gnutls_parse_ocsp_response(session, data, data_size, &resp); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + if (resp.data && resp.size > 0) { + for (unsigned int i = 0; i < info->nocsp; i++) + gnutls_free(info->raw_ocsp_list[i].data); + gnutls_free(info->raw_ocsp_list); + + info->raw_ocsp_list = gnutls_malloc(sizeof(gnutls_datum_t)); + if (info->raw_ocsp_list == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } + info->raw_ocsp_list[0].data = resp.data; + info->raw_ocsp_list[0].size = resp.size; + info->nocsp = 1; + } + + ret = 0; + + error: + _gnutls_buffer_clear(&buf); + + return ret; +} + +#endif diff --git a/lib/ext/status_request.h b/lib/ext/status_request.h new file mode 100644 index 0000000..dc1d233 --- /dev/null +++ b/lib/ext/status_request.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * Author: Simon Josefsson + * + * 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_STATUS_REQUEST_H +#define GNUTLS_LIB_EXT_STATUS_REQUEST_H + +#include <hello_ext.h> + +#define STATUS_REQUEST_TLS_ID 5 + +extern const hello_ext_entry_st ext_mod_status_request; + +int +_gnutls_send_server_certificate_status(gnutls_session_t session, + int again); +int _gnutls_recv_server_certificate_status(gnutls_session_t session); + +int _gnutls_parse_ocsp_response(gnutls_session_t session, const uint8_t *data, + ssize_t data_size, + gnutls_datum_t *resp); + +#endif /* GNUTLS_LIB_EXT_STATUS_REQUEST_H */ diff --git a/lib/ext/supported_groups.c b/lib/ext/supported_groups.c new file mode 100644 index 0000000..56e514a --- /dev/null +++ b/lib/ext/supported_groups.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2011-2012 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Supported Groups extension (rfc7919). + * This extension was previously named Supported Elliptic Curves under TLS 1.2. + */ + +#include "ext/supported_groups.h" +#include "str.h" +#include "num.h" +#include "auth/psk.h" +#include "auth/cert.h" +#include "auth/anon.h" +#include "algorithms.h" +#include <gnutls/gnutls.h> + + +static int _gnutls_supported_groups_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int _gnutls_supported_groups_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + + +const hello_ext_entry_st ext_mod_supported_groups = { + .name = "Supported Groups", + .tls_id = 10, + .gid = GNUTLS_EXTENSION_SUPPORTED_GROUPS, + .client_parse_point = GNUTLS_EXT_TLS, + .server_parse_point = GNUTLS_EXT_TLS, + .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | + GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO, + .recv_func = _gnutls_supported_groups_recv_params, + .send_func = _gnutls_supported_groups_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + + +static unsigned get_min_dh(gnutls_session_t session) +{ + gnutls_certificate_credentials_t cert_cred; + gnutls_psk_server_credentials_t psk_cred; + gnutls_anon_server_credentials_t anon_cred; + unsigned level = 0; + + cert_cred = (gnutls_certificate_credentials_t)_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + psk_cred = (gnutls_psk_server_credentials_t)_gnutls_get_cred(session, GNUTLS_CRD_PSK); + anon_cred = (gnutls_anon_server_credentials_t)_gnutls_get_cred(session, GNUTLS_CRD_ANON); + + if (cert_cred) { + level = cert_cred->dh_sec_param; + } else if (psk_cred) { + level = psk_cred->dh_sec_param; + } else if (anon_cred) { + level = anon_cred->dh_sec_param; + } + + if (level) + return gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, level); + + return 0; +} + +/* + * In case of a server: if a SUPPORTED_GROUPS extension type is received then it stores + * into the session security parameters the new value. The server may use gnutls_session_certificate_type_get(), + * to access it. + * + * In case of a client: If supported_eccs have been specified then we send the extension. + * + */ +static int +_gnutls_supported_groups_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + int i; + uint16_t len; + const uint8_t *p = data; + const gnutls_group_entry_st *group = NULL; + unsigned have_ffdhe = 0; + unsigned tls_id; + unsigned min_dh; + unsigned j; + int serv_ec_idx, serv_dh_idx; /* index in server's priority listing */ + int cli_ec_pos, cli_dh_pos; /* position in listing sent by client */ + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + /* A client shouldn't receive this extension in TLS1.2. It is + * possible to read that message under TLS1.3 as an encrypted + * extension. */ + return 0; + } else { /* SERVER SIDE - we must check if the sent supported ecc type is the right one + */ + if (data_size < 2) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); + + DECR_LEN(data_size, 2); + len = _gnutls_read_uint16(p); + p += 2; + + if (len % 2 != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + DECR_LEN(data_size, len); + + /* we figure what is the minimum DH allowed for this session, if any */ + min_dh = get_min_dh(session); + + serv_ec_idx = serv_dh_idx = -1; + cli_ec_pos = cli_dh_pos = -1; + + /* This extension is being processed prior to a ciphersuite being selected, + * so we cannot rely on ciphersuite information. */ + for (i = 0; i < len; i += 2) { + if (have_ffdhe == 0 && p[i] == 0x01) + have_ffdhe = 1; + + tls_id = _gnutls_read_uint16(&p[i]); + group = _gnutls_tls_id_to_group(tls_id); + + _gnutls_handshake_log("EXT[%p]: Received group %s (0x%x)\n", session, group?group->name:"unknown", tls_id); + if (group == NULL) + continue; + + if (min_dh > 0 && group->prime && group->prime->size*8 < min_dh) + continue; + + /* we simulate _gnutls_session_supports_group, but we prioritize if + * %SERVER_PRECEDENCE is given */ + for (j = 0; j < session->internals.priorities->groups.size; j++) { + if (session->internals.priorities->groups.entry[j]->id == group->id) { + if (session->internals.priorities->server_precedence) { + if (group->pk == GNUTLS_PK_DH) { + if (serv_dh_idx != -1 && (int)j > serv_dh_idx) + break; + serv_dh_idx = j; + cli_dh_pos = i; + } else if (IS_EC(group->pk)) { + if (serv_ec_idx != -1 && (int)j > serv_ec_idx) + break; + serv_ec_idx = j; + cli_ec_pos = i; + } + } else { + if (group->pk == GNUTLS_PK_DH) { + if (cli_dh_pos != -1) + break; + cli_dh_pos = i; + serv_dh_idx = j; + } else if (IS_EC(group->pk)) { + if (cli_ec_pos != -1) + break; + cli_ec_pos = i; + serv_ec_idx = j; + } + } + break; + } + } + } + + /* serv_dh/ec_pos contain the index of the groups we want to use. + */ + if (serv_dh_idx != -1) { + session->internals.cand_dh_group = session->internals.priorities->groups.entry[serv_dh_idx]; + session->internals.cand_group = session->internals.cand_dh_group; + } + + if (serv_ec_idx != -1) { + session->internals.cand_ec_group = session->internals.priorities->groups.entry[serv_ec_idx]; + if (session->internals.cand_group == NULL || + (session->internals.priorities->server_precedence && serv_ec_idx < serv_dh_idx) || + (!session->internals.priorities->server_precedence && cli_ec_pos < cli_dh_pos)) { + session->internals.cand_group = session->internals.cand_ec_group; + } + } + + if (session->internals.cand_group) + _gnutls_handshake_log("EXT[%p]: Selected group %s\n", session, session->internals.cand_group->name); + + if (have_ffdhe) + session->internals.hsk_flags |= HSK_HAVE_FFDHE; + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +_gnutls_supported_groups_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + unsigned len, i; + int ret; + uint16_t p; + + /* this extension is only being sent on client side */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + + len = session->internals.priorities->groups.size; + if (len > 0) { + ret = + _gnutls_buffer_append_prefix(extdata, 16, + len * 2); + if (ret < 0) + return gnutls_assert_val(ret); + + for (i = 0; i < len; i++) { + p = session->internals.priorities->groups.entry[i]->tls_id; + + _gnutls_handshake_log("EXT[%p]: Sent group %s (0x%x)\n", session, + session->internals.priorities->groups.entry[i]->name, (unsigned)p); + + ret = + _gnutls_buffer_append_prefix(extdata, + 16, p); + if (ret < 0) + return gnutls_assert_val(ret); + } + return (len + 1) * 2; + } + + } + + return 0; +} + +/* Returns 0 if the given ECC curve is allowed in the current + * session. A negative error value is returned otherwise. + */ +int +_gnutls_session_supports_group(gnutls_session_t session, + unsigned int group) +{ + unsigned i; + + for (i = 0; i < session->internals.priorities->groups.size; i++) { + if (session->internals.priorities->groups.entry[i]->id == group) + return 0; + } + + return GNUTLS_E_ECC_UNSUPPORTED_CURVE; +} diff --git a/lib/ext/supported_groups.h b/lib/ext/supported_groups.h new file mode 100644 index 0000000..769b3be --- /dev/null +++ b/lib/ext/supported_groups.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2011-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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SUPPORTED_GROUPS_H +#define GNUTLS_LIB_EXT_SUPPORTED_GROUPS_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_supported_groups; + +int +_gnutls_session_supports_group(gnutls_session_t session, + unsigned int group); + +#endif /* GNUTLS_LIB_EXT_SUPPORTED_GROUPS_H */ diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c new file mode 100644 index 0000000..157a0a7 --- /dev/null +++ b/lib/ext/supported_versions.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2001-2012 Free Software Foundation, Inc. + * Copyright (C) 2017-2018 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +/* This file contains the code for the Max Record Size TLS extension. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include "num.h" +#include <hello_ext.h> +#include <ext/supported_versions.h> +#include "handshake.h" + +static int supported_versions_recv_params(gnutls_session_t session, + const uint8_t * data, + size_t data_size); +static int supported_versions_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata); + +const hello_ext_entry_st ext_mod_supported_versions = { + .name = "Supported Versions", + .tls_id = 43, + .gid = GNUTLS_EXTENSION_SUPPORTED_VERSIONS, + .validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | + GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | GNUTLS_EXT_FLAG_HRR|GNUTLS_EXT_FLAG_TLS, + .client_parse_point = GNUTLS_EXT_VERSION_NEG, /* force parsing prior to EXT_TLS extensions */ + .server_parse_point = GNUTLS_EXT_VERSION_NEG, + .recv_func = supported_versions_recv_params, + .send_func = supported_versions_send_params, + .pack_func = NULL, + .unpack_func = NULL, + .deinit_func = NULL, + .cannot_be_overriden = 1 +}; + +static int +supported_versions_recv_params(gnutls_session_t session, + const uint8_t * data, size_t data_size) +{ + const version_entry_st *vers; + uint8_t major, minor; + size_t bytes; + int ret; + + if (session->security_parameters.entity == GNUTLS_SERVER) { + const version_entry_st *old_vers; + const version_entry_st *cli_vers = NULL; + + vers = _gnutls_version_max(session); + old_vers = get_version(session); + + /* do not parse this extension when we haven't TLS1.3 + * enabled. That is because we cannot handle earlier protocol + * negotiation (such as SSL3.0) with this */ + if (vers && !vers->tls13_sem) + return 0; + + DECR_LEN(data_size, 1); + bytes = data[0]; + data++; + + if (bytes % 2 == 1) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + DECR_LEN(data_size, bytes); + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + while (bytes > 0) { + major = data[0]; + minor = data[1]; + data += 2; + bytes -= 2; + + _gnutls_handshake_log("EXT[%p]: Found version: %d.%d\n", + session, (int)major, (int)minor); + + if (!_gnutls_nversion_is_supported(session, major, minor)) + continue; + + /* Prefer the latest possible version + * regardless of the client's precedence. See + * https://gitlab.com/gnutls/gnutls/issues/837 + * for the rationale. + */ + if (!cli_vers || + major > cli_vers->major || + (major == cli_vers->major && + minor > cli_vers->minor)) + cli_vers = nversion_to_entry(major, minor); + } + + if (!cli_vers) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET); + + session->security_parameters.pversion = cli_vers; + + _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n", + session, + (int)cli_vers->major, + (int)cli_vers->minor); + + if (old_vers != cli_vers) { + /* regenerate the random value to set + * downgrade sentinel if necessary + */ + ret = _gnutls_gen_server_random(session, cli_vers->id); + if (ret < 0) + return gnutls_assert_val(ret); + } + + return 0; + } else { /* client */ + + if (!have_creds_for_tls13(session)) { + /* if we don't have certificate or PSK (which work under TLS1.3) + * don't try to negotiate version using the extension. We fallback + * instead to the normal TLS negotiation which has a cap on TLS1.2. + */ + return 0; + } + + DECR_LEN(data_size, 2); + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + major = data[0]; + minor = data[1]; + + vers = nversion_to_entry(major, minor); + if (!vers) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET); + + set_adv_version(session, major, minor); + + _gnutls_handshake_log("EXT[%p]: Negotiated version: %d.%d\n", + session, (int)major, (int)minor); + + if (!vers->tls13_sem) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_negotiate_version(session, major, minor, 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + return 0; +} + +/* returns data_size or a negative number on failure + */ +static int +supported_versions_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + uint8_t versions[32]; + size_t versions_size; + const version_entry_st *vers; + int ret; + + /* this function sends the client extension data (dnsname) */ + if (session->security_parameters.entity == GNUTLS_CLIENT) { + vers = _gnutls_version_max(session); + + /* Do not advertise this extension if we are not doing certificate + * or PSK authentication; i.e., do not try to do TLS1.3 if we have + * credentials which do not fit it. */ + if (!have_creds_for_tls13(session)) { + /* if we don't have certificate or PSK (which work under TLS1.3) + * don't try to negotiate version using the extension. We fallback + * instead to the normal TLS negotiation which has a cap on TLS1.2. + */ + return 0; + } + + /* do not advertise this extension when we haven't TLS1.3 + * enabled. */ + if (vers && !vers->tls13_sem) + return 0; + + ret = _gnutls_write_supported_versions(session, versions, sizeof(versions)); + if (ret <= 0) /* if this function doesn't succeed do not send anything */ + return 0; + + versions_size = ret; + + ret = _gnutls_buffer_append_data_prefix(extdata, 8, versions, versions_size); + if (ret < 0) + return gnutls_assert_val(ret); + + return versions_size+2; + } else { + vers = get_version(session); + if (unlikely(vers == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + /* don't use this extension to negotiate versions <= 1.2, + * pretend we don't support it, so that we use a single + * code path to negotiate these protocols. */ + if (!vers->tls13_sem) + return 0; + + ret = _gnutls_buffer_append_data(extdata, &vers->major, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_data(extdata, &vers->minor, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + return 2; + } + + return 0; +} diff --git a/lib/ext/supported_versions.h b/lib/ext/supported_versions.h new file mode 100644 index 0000000..f7dfb9e --- /dev/null +++ b/lib/ext/supported_versions.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXT_SUPPORTED_VERSIONS_H +#define GNUTLS_LIB_EXT_SUPPORTED_VERSIONS_H + +#include <hello_ext.h> + +extern const hello_ext_entry_st ext_mod_supported_versions; + +#endif /* GNUTLS_LIB_EXT_SUPPORTED_VERSIONS_H */ diff --git a/lib/extras/Makefile.am b/lib/extras/Makefile.am new file mode 100644 index 0000000..7e5274b --- /dev/null +++ b/lib/extras/Makefile.am @@ -0,0 +1,39 @@ +## Process this file with automake to produce Makefile.in +# Copyright (C) 2002-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 3 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 this program. If not, see <https://www.gnu.org/licenses/> + +include $(top_srcdir)/lib/common.mk + +AM_CPPFLAGS = \ + -I$(srcdir)/../../gl \ + -I$(builddir)/../../gl \ + -I$(srcdir)/../includes \ + -I$(builddir)/../includes \ + -I$(builddir)/../../gl \ + -I$(srcdir)/.. + +EXTRA_DIST = licenses/CC0 + +if ENABLE_MINITASN1 +AM_CPPFLAGS += -I$(srcdir)/../minitasn1 +endif + +noinst_LTLIBRARIES = libgnutls_extras.la + +libgnutls_extras_la_SOURCES = randomart.c randomart.h hex.c hex.h diff --git a/lib/extras/Makefile.in b/lib/extras/Makefile.in new file mode 100644 index 0000000..c934bed --- /dev/null +++ b/lib/extras/Makefile.in @@ -0,0 +1,2391 @@ +# 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-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 3 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 this program. If not, see <https://www.gnu.org/licenses/> + +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@ +@ENABLE_MINITASN1_TRUE@am__append_1 = -I$(srcdir)/../minitasn1 +subdir = lib/extras +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) +libgnutls_extras_la_LIBADD = +am_libgnutls_extras_la_OBJECTS = randomart.lo hex.lo +libgnutls_extras_la_OBJECTS = $(am_libgnutls_extras_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)/hex.Plo ./$(DEPDIR)/randomart.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 = $(libgnutls_extras_la_SOURCES) +DIST_SOURCES = $(libgnutls_extras_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 = -I$(srcdir)/../../gl -I$(builddir)/../../gl \ + -I$(srcdir)/../includes -I$(builddir)/../includes \ + -I$(builddir)/../../gl -I$(srcdir)/.. $(am__append_1) +EXTRA_DIST = licenses/CC0 +noinst_LTLIBRARIES = libgnutls_extras.la +libgnutls_extras_la_SOURCES = randomart.c randomart.h hex.c hex.h +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/extras/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/extras/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}; \ + } + +libgnutls_extras.la: $(libgnutls_extras_la_OBJECTS) $(libgnutls_extras_la_DEPENDENCIES) $(EXTRA_libgnutls_extras_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libgnutls_extras_la_OBJECTS) $(libgnutls_extras_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hex.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/randomart.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)/hex.Plo + -rm -f ./$(DEPDIR)/randomart.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)/hex.Plo + -rm -f ./$(DEPDIR)/randomart.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/extras/hex.c b/lib/extras/hex.c new file mode 100644 index 0000000..b88777f --- /dev/null +++ b/lib/extras/hex.c @@ -0,0 +1,63 @@ +/* CC0 license (public domain) - see LICENSE file for details */ +#include <config.h> +#include <hex.h> +#include <stdio.h> +#include <stdlib.h> + +static bool char_to_hex(unsigned char *val, char c) +{ + if (c >= '0' && c <= '9') { + *val = c - '0'; + return true; + } + if (c >= 'a' && c <= 'f') { + *val = c - 'a' + 10; + return true; + } + if (c >= 'A' && c <= 'F') { + *val = c - 'A' + 10; + return true; + } + return false; +} + +bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize) +{ + unsigned char v1, v2; + unsigned char *p = buf; + + while (slen > 1) { + if (!char_to_hex(&v1, str[0]) || !char_to_hex(&v2, str[1])) + return false; + if (!bufsize) + return false; + *(p++) = (v1 << 4) | v2; + str += 2; + slen -= 2; + bufsize--; + } + return slen == 0 && bufsize == 0; +} + +static const char HEX_CHARS[] = "0123456789abcdef"; + +bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize) +{ + size_t used = 0; + + if (destsize < 1) + return false; + + while (used < bufsize) { + unsigned int c = ((const unsigned char *)buf)[used]; + if (destsize < 3) + return false; + *(dest++) = HEX_CHARS[(c >> 4) & 0xF]; + *(dest++) = HEX_CHARS[c & 0xF]; + used++; + destsize -= 2; + } + *dest = '\0'; + + return used + 1; +} diff --git a/lib/extras/hex.h b/lib/extras/hex.h new file mode 100644 index 0000000..5fcac98 --- /dev/null +++ b/lib/extras/hex.h @@ -0,0 +1,77 @@ +/* CC0 (Public domain) - see LICENSE file for details */ + +#ifndef GNUTLS_LIB_EXTRAS_HEX_H +#define GNUTLS_LIB_EXTRAS_HEX_H + +#include "config.h" +#include <stdbool.h> +#include <stdlib.h> + +/** + * hex_decode - Unpack a hex string. + * @str: the hexadecimal string + * @slen: the length of @str + * @buf: the buffer to write the data into + * @bufsize: the length of @buf + * + * Returns false if there are any characters which aren't 0-9, a-f or A-F, + * of the string wasn't the right length for @bufsize. + * + * Example: + * unsigned char data[20]; + * + * if (!hex_decode(argv[1], strlen(argv[1]), data, 20)) + * printf("String is malformed!\n"); + */ + +bool hex_decode(const char *str, size_t slen, void *buf, size_t bufsize); + +/** + * hex_encode - Create a nul-terminated hex string + * @buf: the buffer to read the data from + * @bufsize: the length of @buf + * @dest: the string to fill + * @destsize: the max size of the string + * + * Returns true if the string, including terminator, fit in @destsize; + * + * Example: + * unsigned char buf[] = { 0x1F, 0x2F }; + * char str[5]; + * + * if (!hex_encode(buf, sizeof(buf), str, sizeof(str))) + * abort(); + */ +bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize); + +/** + * hex_str_size - Calculate how big a nul-terminated hex string is + * @bytes: bytes of data to represent + * + * Example: + * unsigned char buf[] = { 0x1F, 0x2F }; + * char str[hex_str_size(sizeof(buf))]; + * + * hex_encode(buf, sizeof(buf), str, sizeof(str)); + */ +static inline size_t hex_str_size(size_t bytes) +{ + return 2 * bytes + 1; +} + +/** + * hex_data_size - Calculate how many bytes of data in a hex string + * @strlen: the length of the string (with or without NUL) + * + * Example: + * const char str[] = "1F2F"; + * unsigned char buf[hex_data_size(sizeof(str))]; + * + * hex_decode(str, strlen(str), buf, sizeof(buf)); + */ +static inline size_t hex_data_size(size_t slen) +{ + return slen / 2; +} + +#endif /* GNUTLS_LIB_EXTRAS_HEX_H */ diff --git a/lib/extras/licenses/CC0 b/lib/extras/licenses/CC0 new file mode 100644 index 0000000..feb9b11 --- /dev/null +++ b/lib/extras/licenses/CC0 @@ -0,0 +1,28 @@ +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + moral rights retained by the original author(s) and/or performer(s); + publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + rights protecting the extraction, dissemination, use and reuse of data in a Work; + database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + +4. Limitations and Disclaimers. + + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. diff --git a/lib/extras/randomart.c b/lib/extras/randomart.c new file mode 100644 index 0000000..cfd7e1c --- /dev/null +++ b/lib/extras/randomart.c @@ -0,0 +1,172 @@ +/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */ +/* + * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. + * Copyright (c) 2008 Alexander von Gernler. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include <randomart.h> + +/* + * Draw an ASCII-Art representing the fingerprint so human brain can + * profit from its built-in pattern recognition ability. + * This technique is called "random art" and can be found in some + * scientific publications like this original paper: + * + * "Hash Visualization: a New Technique to improve Real-World Security", + * Perrig A. and Song D., 1999, International Workshop on Cryptographic + * Techniques and E-Commerce (CrypTEC '99) + * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf + * + * The subject came up in a talk by Dan Kaminsky, too. + * + * If you see the picture is different, the key is different. + * If the picture looks the same, you still know nothing. + * + * The algorithm used here is a worm crawling over a discrete plane, + * leaving a trace (augmenting the field) everywhere it goes. + * Movement is taken from dgst_raw 2bit-wise. Bumping into walls + * makes the respective movement vector be ignored for this turn. + * Graphs are not unambiguous, because circles in graphs can be + * walked in either direction. + */ + +/* + * Field sizes for the random art. Have to be odd, so the starting point + * can be in the exact middle of the picture, and FLDBASE should be >=8 . + * Else pictures would be too dense, and drawing the frame would + * fail, too, because the key type would not fit in anymore. + */ +#define FLDBASE 8 +#define FLDSIZE_Y (FLDBASE + 1) +#define FLDSIZE_X (FLDBASE * 2 + 1) +char *_gnutls_key_fingerprint_randomart(uint8_t * dgst_raw, + u_int dgst_raw_len, + const char *key_type, + unsigned int key_size, + const char *prefix) +{ + /* + * Chars to be used after each other every time the worm + * intersects with itself. Matter of taste. + */ + const char augmentation_string[] = " .o+=*BOX@%&#/^SE"; + char *retval, *p; + uint8_t field[FLDSIZE_X][FLDSIZE_Y]; + char size_txt[16]; + unsigned int i, b; + int x, y; + const size_t len = sizeof(augmentation_string) - 2; + unsigned int prefix_len = 0; + + if (prefix) + prefix_len = strlen(prefix); + + retval = + gnutls_calloc(1, + (FLDSIZE_X + 3 + prefix_len) * (FLDSIZE_Y + 2)); + if (retval == NULL) { + gnutls_assert(); + return NULL; + } + + /* initialize field */ + memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); + x = FLDSIZE_X / 2; + y = FLDSIZE_Y / 2; + + /* process raw key */ + for (i = 0; i < dgst_raw_len; i++) { + int input; + /* each byte conveys four 2-bit move commands */ + input = dgst_raw[i]; + for (b = 0; b < 4; b++) { + /* evaluate 2 bit, rest is shifted later */ + x += (input & 0x1) ? 1 : -1; + y += (input & 0x2) ? 1 : -1; + + /* assure we are still in bounds */ + x = MAX(x, 0); + y = MAX(y, 0); + x = MIN(x, FLDSIZE_X - 1); + y = MIN(y, FLDSIZE_Y - 1); + + /* augment the field */ + if (field[x][y] < len - 2) + field[x][y]++; + input = input >> 2; + } + } + + /* mark starting point and end point */ + field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; + field[x][y] = len; + + if (key_size > 0) + snprintf(size_txt, sizeof(size_txt), " %4u", key_size); + else + size_txt[0] = 0; + + /* fill in retval */ + if (prefix_len) + snprintf(retval, FLDSIZE_X + prefix_len, "%s+--[%4s%s]", + prefix, key_type, size_txt); + else + snprintf(retval, FLDSIZE_X, "+--[%4s%s]", key_type, + size_txt); + p = strchr(retval, '\0'); + + /* output upper border */ + for (i = p - retval - 1; i < FLDSIZE_X + prefix_len; i++) + *p++ = '-'; + *p++ = '+'; + *p++ = '\n'; + + if (prefix_len) { + memcpy(p, prefix, prefix_len); + p += prefix_len; + } + + /* output content */ + for (y = 0; y < FLDSIZE_Y; y++) { + *p++ = '|'; + for (x = 0; x < FLDSIZE_X; x++) + *p++ = augmentation_string[MIN(field[x][y], len)]; + *p++ = '|'; + *p++ = '\n'; + + if (prefix_len) { + memcpy(p, prefix, prefix_len); + p += prefix_len; + } + } + + /* output lower border */ + *p++ = '+'; + for (i = 0; i < FLDSIZE_X; i++) + *p++ = '-'; + *p++ = '+'; + + return retval; +} diff --git a/lib/extras/randomart.h b/lib/extras/randomart.h new file mode 100644 index 0000000..b468eb4 --- /dev/null +++ b/lib/extras/randomart.h @@ -0,0 +1,10 @@ +#ifndef GNUTLS_LIB_EXTRAS_RANDOMART_H +#define GNUTLS_LIB_EXTRAS_RANDOMART_H + +char *_gnutls_key_fingerprint_randomart(uint8_t * dgst_raw, + u_int dgst_raw_len, + const char *key_type, + unsigned int key_size, + const char *prefix); + +#endif /* GNUTLS_LIB_EXTRAS_RANDOMART_H */ diff --git a/lib/extv.c b/lib/extv.c new file mode 100644 index 0000000..0c0c46f --- /dev/null +++ b/lib/extv.c @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2017-2018 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "hello_ext.h" +#include "errors.h" +#include "extv.h" + +/* Iterates through all extensions found, and calls the cb() + * function with their data */ +int _gnutls_extv_parse(void *ctx, + gnutls_ext_raw_process_func cb, + const uint8_t * data, int data_size) +{ + int next, ret; + int pos = 0; + uint16_t tls_id; + const uint8_t *sdata; + uint16_t size; + + if (data_size == 0) + return 0; + + DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + next = _gnutls_read_uint16(data); + pos += 2; + + DECR_LENGTH_RET(data_size, next, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + + if (next == 0 && data_size == 0) /* field is present, but has zero length? Ignore it. */ + return 0; + else if (data_size > 0) /* forbid unaccounted data */ + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + + do { + DECR_LENGTH_RET(next, 2, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + tls_id = _gnutls_read_uint16(&data[pos]); + pos += 2; + + DECR_LENGTH_RET(next, 2, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + size = _gnutls_read_uint16(&data[pos]); + pos += 2; + + DECR_LENGTH_RET(next, size, GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + sdata = &data[pos]; + pos += size; + + ret = cb(ctx, tls_id, sdata, size); + if (ret < 0) + return gnutls_assert_val(ret); + } + while (next > 2); + + /* forbid leftovers */ + if (next > 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_EXTENSIONS_LENGTH); + + return 0; +} + +#define HANDSHAKE_SESSION_ID_POS (34) +/** + * gnutls_ext_raw_parse: + * @ctx: a pointer to pass to callback function + * @cb: callback function to process each extension found + * @data: TLS extension data + * @flags: should be zero or %GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO or %GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO + * + * This function iterates through the TLS extensions as passed in + * @data, passing the individual extension data to callback. The + * @data must conform to Extension extensions<0..2^16-1> format. + * + * If flags is %GNUTLS_EXT_RAW_TLS_FLAG_CLIENT_HELLO then this function + * will parse the extension data from the position, as if the packet in + * @data is a client hello (without record or handshake headers) - + * as provided by gnutls_handshake_set_hook_function(). + * + * The return value of the callback will be propagated. + * + * Returns: %GNUTLS_E_SUCCESS on success, or an error code. On unknown + * flags it returns %GNUTLS_E_INVALID_REQUEST. + * + * Since: 3.6.3 + **/ +int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + const gnutls_datum_t *data, unsigned int flags) +{ + if (flags & GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO) { + size_t size = data->size; + size_t len; + uint8_t *p = data->data; + + DECR_LEN(size, HANDSHAKE_SESSION_ID_POS); + + if (p[0] != 0x03) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET); + + p += HANDSHAKE_SESSION_ID_POS; + + /* skip session id */ + DECR_LEN(size, 1); + len = p[0]; + p++; + DECR_LEN(size, len); + p += len; + + /* CipherSuites */ + DECR_LEN(size, 2); + len = _gnutls_read_uint16(p); + p += 2; + DECR_LEN(size, len); + p += len; + + /* legacy_compression_methods */ + DECR_LEN(size, 1); + len = p[0]; + p++; + DECR_LEN(size, len); + p += len; + + if (size == 0) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + return _gnutls_extv_parse(ctx, cb, p, size); + } else if (flags & GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO) { + size_t size = data->size; + size_t len; + uint8_t *p = data->data; + + DECR_LEN(size, HANDSHAKE_SESSION_ID_POS); + + if (p[0] != 254) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET); + + p += HANDSHAKE_SESSION_ID_POS; + + /* skip session id */ + DECR_LEN(size, 1); + len = p[0]; + p++; + DECR_LEN(size, len); + p += len; + + /* skip cookie */ + DECR_LEN(size, 1); + len = p[0]; + p++; + DECR_LEN(size, len); + p += len; + + /* CipherSuites */ + DECR_LEN(size, 2); + len = _gnutls_read_uint16(p); + p += 2; + DECR_LEN(size, len); + p += len; + + /* legacy_compression_methods */ + DECR_LEN(size, 1); + len = p[0]; + p++; + DECR_LEN(size, len); + p += len; + + if (size == 0) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + return _gnutls_extv_parse(ctx, cb, p, size); + } + + if (flags != 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + return _gnutls_extv_parse(ctx, cb, data->data, data->size); +} + +/* Returns: + * * On success the number of bytes appended (always positive), or zero if not sent + * * On failure, a negative error code. + */ +int _gnutls_extv_append(gnutls_buffer_st *buf, + uint16_t tls_id, + void *ctx, + int (*cb)(void *ctx, gnutls_buffer_st *buf)) +{ + int size_pos, appended, ret; + size_t size_prev; + + ret = _gnutls_buffer_append_prefix(buf, 16, tls_id); + if (ret < 0) + return gnutls_assert_val(ret); + + size_pos = buf->length; + ret = _gnutls_buffer_append_prefix(buf, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + size_prev = buf->length; + ret = cb(ctx, buf); + if (ret < 0 && ret != GNUTLS_E_INT_RET_0) { + return gnutls_assert_val(ret); + } + + /* returning GNUTLS_E_INT_RET_0 means to send an empty + * extension of this type. + */ + appended = buf->length - size_prev; + + if (appended > 0 || ret == GNUTLS_E_INT_RET_0) { + if (ret == GNUTLS_E_INT_RET_0) + appended = 0; + + /* write the real size */ + _gnutls_write_uint16(appended, + &buf->data[size_pos]); + } else if (appended == 0) { + buf->length -= 4; /* reset type and size */ + return 0; + } + + return appended + 4; +} + diff --git a/lib/extv.h b/lib/extv.h new file mode 100644 index 0000000..3c0bd33 --- /dev/null +++ b/lib/extv.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 Red Hat, 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. + * + * 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#ifndef GNUTLS_LIB_EXTV_H +#define GNUTLS_LIB_EXTV_H + +#include <gnutls/gnutls.h> +#include "str.h" + +/* Iterates through all TLS-type extensions in data, and + * calls the callback function for each of them. The ctx, flags + * and parse_type are passed verbatim to callback. */ +int _gnutls_extv_parse(void *ctx, + gnutls_ext_raw_process_func cb, + const uint8_t * data, int data_size); + +inline static +int _gnutls_extv_append_init(gnutls_buffer_st *buf) +{ + unsigned pos; + int ret; + + pos = buf->length; + + ret = _gnutls_buffer_append_prefix(buf, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + return pos; +} + +/* its input is the buffer and the return value of _gnutls_extv_append_init() + * @is_hello: should be true for client and server hello messages. + */ +inline static +int _gnutls_extv_append_final(gnutls_buffer_st *buf, unsigned init, unsigned is_hello) +{ + unsigned size = buf->length - init - 2; + + if (size > UINT16_MAX) /* sent too many extensions */ + return gnutls_assert_val(GNUTLS_E_HANDSHAKE_TOO_LARGE); + + if (size > 0) + _gnutls_write_uint16(size, &buf->data[init]); + else if (is_hello && size == 0) { + /* there is no point to send empty extension bytes, and + * they are known to break certain clients */ + buf->length -= 2; + } + + return 0; +} + +typedef int (*extv_append_func)(void *ctx, gnutls_buffer_st *buf); + +int _gnutls_extv_append(gnutls_buffer_st *buf, + uint16_t tls_id, + void *ctx, + extv_append_func cb); + + +#endif /* GNUTLS_LIB_EXTV_H */ |