diff options
Diffstat (limited to 'lib/auth')
-rw-r--r-- | lib/auth/Makefile.am | 41 | ||||
-rw-r--r-- | lib/auth/Makefile.in | 2447 | ||||
-rw-r--r-- | lib/auth/anon.c | 131 | ||||
-rw-r--r-- | lib/auth/anon.h | 52 | ||||
-rw-r--r-- | lib/auth/anon_ecdh.c | 139 | ||||
-rw-r--r-- | lib/auth/cert.c | 1914 | ||||
-rw-r--r-- | lib/auth/cert.h | 189 | ||||
-rw-r--r-- | lib/auth/dh_common.c | 379 | ||||
-rw-r--r-- | lib/auth/dh_common.h | 50 | ||||
-rw-r--r-- | lib/auth/dhe.c | 152 | ||||
-rw-r--r-- | lib/auth/dhe_psk.c | 506 | ||||
-rw-r--r-- | lib/auth/ecdhe.c | 522 | ||||
-rw-r--r-- | lib/auth/ecdhe.h | 52 | ||||
-rw-r--r-- | lib/auth/psk.c | 334 | ||||
-rw-r--r-- | lib/auth/psk.h | 110 | ||||
-rw-r--r-- | lib/auth/psk_passwd.c | 273 | ||||
-rw-r--r-- | lib/auth/psk_passwd.h | 36 | ||||
-rw-r--r-- | lib/auth/rsa.c | 316 | ||||
-rw-r--r-- | lib/auth/rsa_common.h | 39 | ||||
-rw-r--r-- | lib/auth/rsa_psk.c | 436 | ||||
-rw-r--r-- | lib/auth/srp_kx.c | 1021 | ||||
-rw-r--r-- | lib/auth/srp_kx.h | 74 | ||||
-rw-r--r-- | lib/auth/srp_passwd.c | 470 | ||||
-rw-r--r-- | lib/auth/srp_passwd.h | 46 | ||||
-rw-r--r-- | lib/auth/srp_rsa.c | 265 | ||||
-rw-r--r-- | lib/auth/srp_sb64.c | 453 | ||||
-rw-r--r-- | lib/auth/vko_gost.c | 323 |
27 files changed, 10770 insertions, 0 deletions
diff --git a/lib/auth/Makefile.am b/lib/auth/Makefile.am new file mode 100644 index 0000000..e85eaae --- /dev/null +++ b/lib/auth/Makefile.am @@ -0,0 +1,41 @@ +## 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_auth.la + +libgnutls_auth_la_SOURCES = anon.c cert.c dh_common.c dhe.c \ + rsa_psk.c dhe_psk.c psk.c psk_passwd.c rsa.c srp_kx.c \ + srp_passwd.c srp_rsa.c srp_sb64.c anon.h cert.h dh_common.h \ + psk.h psk_passwd.h srp_kx.h srp_passwd.h anon_ecdh.c \ + ecdhe.c ecdhe.h rsa_common.h vko_gost.c diff --git a/lib/auth/Makefile.in b/lib/auth/Makefile.in new file mode 100644 index 0000000..5f7e6f1 --- /dev/null +++ b/lib/auth/Makefile.in @@ -0,0 +1,2447 @@ +# 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/auth +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_auth_la_LIBADD = +am_libgnutls_auth_la_OBJECTS = anon.lo cert.lo dh_common.lo dhe.lo \ + rsa_psk.lo dhe_psk.lo psk.lo psk_passwd.lo rsa.lo srp_kx.lo \ + srp_passwd.lo srp_rsa.lo srp_sb64.lo anon_ecdh.lo ecdhe.lo \ + vko_gost.lo +libgnutls_auth_la_OBJECTS = $(am_libgnutls_auth_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)/anon.Plo ./$(DEPDIR)/anon_ecdh.Plo \ + ./$(DEPDIR)/cert.Plo ./$(DEPDIR)/dh_common.Plo \ + ./$(DEPDIR)/dhe.Plo ./$(DEPDIR)/dhe_psk.Plo \ + ./$(DEPDIR)/ecdhe.Plo ./$(DEPDIR)/psk.Plo \ + ./$(DEPDIR)/psk_passwd.Plo ./$(DEPDIR)/rsa.Plo \ + ./$(DEPDIR)/rsa_psk.Plo ./$(DEPDIR)/srp_kx.Plo \ + ./$(DEPDIR)/srp_passwd.Plo ./$(DEPDIR)/srp_rsa.Plo \ + ./$(DEPDIR)/srp_sb64.Plo ./$(DEPDIR)/vko_gost.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_auth_la_SOURCES) +DIST_SOURCES = $(libgnutls_auth_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) +noinst_LTLIBRARIES = libgnutls_auth.la +libgnutls_auth_la_SOURCES = anon.c cert.c dh_common.c dhe.c \ + rsa_psk.c dhe_psk.c psk.c psk_passwd.c rsa.c srp_kx.c \ + srp_passwd.c srp_rsa.c srp_sb64.c anon.h cert.h dh_common.h \ + psk.h psk_passwd.h srp_kx.h srp_passwd.h anon_ecdh.c \ + ecdhe.c ecdhe.h rsa_common.h vko_gost.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/lib/common.mk $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/auth/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign lib/auth/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_auth.la: $(libgnutls_auth_la_OBJECTS) $(libgnutls_auth_la_DEPENDENCIES) $(EXTRA_libgnutls_auth_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libgnutls_auth_la_OBJECTS) $(libgnutls_auth_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/anon.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/anon_ecdh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dh_common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhe.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dhe_psk.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ecdhe.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psk_passwd.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsa_psk.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp_kx.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp_passwd.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp_rsa.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/srp_sb64.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vko_gost.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)/anon.Plo + -rm -f ./$(DEPDIR)/anon_ecdh.Plo + -rm -f ./$(DEPDIR)/cert.Plo + -rm -f ./$(DEPDIR)/dh_common.Plo + -rm -f ./$(DEPDIR)/dhe.Plo + -rm -f ./$(DEPDIR)/dhe_psk.Plo + -rm -f ./$(DEPDIR)/ecdhe.Plo + -rm -f ./$(DEPDIR)/psk.Plo + -rm -f ./$(DEPDIR)/psk_passwd.Plo + -rm -f ./$(DEPDIR)/rsa.Plo + -rm -f ./$(DEPDIR)/rsa_psk.Plo + -rm -f ./$(DEPDIR)/srp_kx.Plo + -rm -f ./$(DEPDIR)/srp_passwd.Plo + -rm -f ./$(DEPDIR)/srp_rsa.Plo + -rm -f ./$(DEPDIR)/srp_sb64.Plo + -rm -f ./$(DEPDIR)/vko_gost.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)/anon.Plo + -rm -f ./$(DEPDIR)/anon_ecdh.Plo + -rm -f ./$(DEPDIR)/cert.Plo + -rm -f ./$(DEPDIR)/dh_common.Plo + -rm -f ./$(DEPDIR)/dhe.Plo + -rm -f ./$(DEPDIR)/dhe_psk.Plo + -rm -f ./$(DEPDIR)/ecdhe.Plo + -rm -f ./$(DEPDIR)/psk.Plo + -rm -f ./$(DEPDIR)/psk_passwd.Plo + -rm -f ./$(DEPDIR)/rsa.Plo + -rm -f ./$(DEPDIR)/rsa_psk.Plo + -rm -f ./$(DEPDIR)/srp_kx.Plo + -rm -f ./$(DEPDIR)/srp_passwd.Plo + -rm -f ./$(DEPDIR)/srp_rsa.Plo + -rm -f ./$(DEPDIR)/srp_sb64.Plo + -rm -f ./$(DEPDIR)/vko_gost.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/auth/anon.c b/lib/auth/anon.c new file mode 100644 index 0000000..2fc2cd7 --- /dev/null +++ b/lib/auth/anon.c @@ -0,0 +1,131 @@ +/* + * 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/> + * + */ + +/* This file contains the Anonymous Diffie-Hellman key exchange part of + * the anonymous authentication. The functions here are used in the + * handshake. + */ + +#include "gnutls_int.h" + +#if defined(ENABLE_ANON) && defined(ENABLE_DHE) + +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include "auth/anon.h" +#include "num.h" +#include "mpi.h" +#include <state.h> +#include <auth/dh_common.h> + +static int gen_anon_server_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_anon_client_kx(gnutls_session_t, uint8_t *, size_t); +static int proc_anon_server_kx(gnutls_session_t, uint8_t *, size_t); + +const mod_auth_st anon_auth_struct = { + "ANON", + NULL, + NULL, + gen_anon_server_kx, + _gnutls_gen_dh_common_client_kx, /* this can be shared */ + NULL, + NULL, + + NULL, + NULL, /* certificate */ + proc_anon_server_kx, + proc_anon_client_kx, + NULL, + NULL +}; + +static int +gen_anon_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret; + gnutls_anon_server_credentials_t cred; + + cred = (gnutls_anon_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_ANON); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_ANON, + sizeof(anon_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + ret = _gnutls_figure_dh_params(session, cred->dh_params, cred->params_func, cred->dh_sec_param); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = + _gnutls_dh_common_print_server_kx(session, data); + if (ret < 0) { + gnutls_assert(); + } + + return ret; +} + + +static int +proc_anon_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + return + _gnutls_proc_dh_common_client_kx(session, data, _data_size, NULL); + +} + +int +proc_anon_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + + int ret; + + /* set auth_info */ + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_ANON, + sizeof(anon_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + ret = _gnutls_proc_dh_common_server_kx(session, data, _data_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +#endif /* ENABLE_ANON */ diff --git a/lib/auth/anon.h b/lib/auth/anon.h new file mode 100644 index 0000000..3a8db4b --- /dev/null +++ b/lib/auth/anon.h @@ -0,0 +1,52 @@ +/* + * 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_AUTH_ANON_H +#define GNUTLS_LIB_AUTH_ANON_H + +/* this is not to be included by gnutls_anon.c */ +#include <auth.h> +#include <auth/dh_common.h> + +typedef struct gnutls_anon_server_credentials_st { + gnutls_dh_params_t dh_params; + unsigned deinit_dh_params; + gnutls_sec_param_t dh_sec_param; + + /* this callback is used to retrieve the DH or RSA + * parameters. + */ + gnutls_params_function *params_func; +} anon_server_credentials_st; + +typedef struct gnutls_anon_client_credentials_st { + int dummy; +} anon_client_credentials_st; + +typedef struct anon_auth_info_st { + dh_info_st dh; + gnutls_ecc_curve_t curve; +} *anon_auth_info_t; + +typedef struct anon_auth_info_st anon_auth_info_st; + +#endif /* GNUTLS_LIB_AUTH_ANON_H */ diff --git a/lib/auth/anon_ecdh.c b/lib/auth/anon_ecdh.c new file mode 100644 index 0000000..48da739 --- /dev/null +++ b/lib/auth/anon_ecdh.c @@ -0,0 +1,139 @@ +/* + * 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/> + * + */ + +/* This file contains the Anonymous Diffie-Hellman key exchange part of + * the anonymous authentication. The functions here are used in the + * handshake. + */ + +#include "gnutls_int.h" + +#if defined(ENABLE_ANON) && defined(ENABLE_ECDHE) + +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include "auth/anon.h" +#include "num.h" +#include "mpi.h" +#include <state.h> +#include <auth/ecdhe.h> +#include <ext/supported_groups.h> + +static int gen_anon_ecdh_server_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_anon_ecdh_client_kx(gnutls_session_t, uint8_t *, size_t); +static int proc_anon_ecdh_server_kx(gnutls_session_t, uint8_t *, size_t); + +const mod_auth_st anon_ecdh_auth_struct = { + "ANON ECDH", + NULL, + NULL, + gen_anon_ecdh_server_kx, + _gnutls_gen_ecdh_common_client_kx, /* this can be shared */ + NULL, + NULL, + + NULL, + NULL, /* certificate */ + proc_anon_ecdh_server_kx, + proc_anon_ecdh_client_kx, + NULL, + NULL +}; + +static int +gen_anon_ecdh_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret; + gnutls_anon_server_credentials_t cred; + + cred = (gnutls_anon_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_ANON); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_ANON, + sizeof(anon_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_ecdh_common_print_server_kx(session, data, + get_group + (session)); + if (ret < 0) { + gnutls_assert(); + } + + return ret; +} + + +static int +proc_anon_ecdh_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + gnutls_anon_server_credentials_t cred; + + cred = (gnutls_anon_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_ANON); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + return _gnutls_proc_ecdh_common_client_kx(session, data, + _data_size, + get_group + (session), NULL); +} + +int +proc_anon_ecdh_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + + int ret; + + /* set auth_info */ + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_ANON, + sizeof(anon_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_proc_ecdh_common_server_kx(session, data, _data_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +#endif /* ENABLE_ANON */ diff --git a/lib/auth/cert.c b/lib/auth/cert.c new file mode 100644 index 0000000..4540706 --- /dev/null +++ b/lib/auth/cert.c @@ -0,0 +1,1914 @@ +/* + * Copyright (C) 2001-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/> + * + */ + +/* The certificate authentication functions which are needed in the handshake, + * and are common to RSA and DHE key exchange, are in this file. + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include <auth/cert.h> +#include "dh.h" +#include "num.h" +#include "libtasn1.h" +#include "datum.h" +#include "ext/signature.h" +#include <pk.h> +#include <algorithms.h> +#include <global.h> +#include <record.h> +#include <tls-sig.h> +#include <state.h> +#include <pk.h> +#include <x509.h> +#include <x509/verify-high.h> +#include <gnutls/abstract.h> +#include "abstract_int.h" +#include "debug.h" + +static void +selected_certs_set(gnutls_session_t session, + gnutls_pcert_st * certs, int ncerts, + gnutls_ocsp_data_st *ocsp, unsigned nocsp, + gnutls_privkey_t key, int need_free, + gnutls_status_request_ocsp_func ocsp_func, + void *ocsp_func_ptr); + +#define MAX_CLIENT_SIGN_ALGOS 5 +#define CERTTYPE_SIZE (MAX_CLIENT_SIGN_ALGOS+1) +typedef enum CertificateSigType { RSA_SIGN = 1, DSA_SIGN = 2, ECDSA_SIGN = 64, +#ifdef ENABLE_GOST + GOSTR34102012_256_SIGN = 67, + GOSTR34102012_512_SIGN = 68 +#endif +} CertificateSigType; + +enum CertificateSigTypeFlags { + RSA_SIGN_FLAG = 1, + DSA_SIGN_FLAG = 1 << 1, + ECDSA_SIGN_FLAG = 1 << 2, +#ifdef ENABLE_GOST + GOSTR34102012_256_SIGN_FLAG = 1 << 3, + GOSTR34102012_512_SIGN_FLAG = 1 << 4 +#endif +}; + +/* Moves data from an internal certificate struct (gnutls_pcert_st) to + * another internal certificate struct (cert_auth_info_t), and deinitializes + * the former. + */ +int _gnutls_pcert_to_auth_info(cert_auth_info_t info, gnutls_pcert_st * certs, size_t ncerts) +{ + size_t i, j; + + if (info->raw_certificate_list != NULL) { + for (j = 0; j < info->ncerts; j++) + _gnutls_free_datum(&info->raw_certificate_list[j]); + gnutls_free(info->raw_certificate_list); + } + + if (ncerts == 0) { + info->raw_certificate_list = NULL; + info->ncerts = 0; + return 0; + } + + info->raw_certificate_list = + gnutls_calloc(ncerts, sizeof(gnutls_datum_t)); + if (info->raw_certificate_list == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + info->cert_type = certs[0].type; + info->ncerts = ncerts; + + for (i = 0; i < ncerts; i++) { + info->raw_certificate_list[i].data = certs[i].cert.data; + info->raw_certificate_list[i].size = certs[i].cert.size; + certs[i].cert.data = NULL; + gnutls_pcert_deinit(&certs[i]); + } + gnutls_free(certs); + + return 0; +} + +/* returns 0 if the algo_to-check exists in the pk_algos list, + * -1 otherwise. + */ +inline static int +check_pk_algo_in_list(const gnutls_pk_algorithm_t * + pk_algos, int pk_algos_length, + gnutls_pk_algorithm_t algo_to_check) +{ + int i; + for (i = 0; i < pk_algos_length; i++) { + if (algo_to_check == pk_algos[i]) { + return 0; + } + } + return -1; +} + +/* Returns the issuer's Distinguished name in odn, of the certificate + * specified in cert. + */ +static int cert_get_issuer_dn(gnutls_pcert_st * cert, gnutls_datum_t * odn) +{ + asn1_node dn; + int len, result; + int start, end; + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.Certificate", &dn)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = asn1_der_decoding(&dn, cert->cert.data, cert->cert.size, NULL); + if (result != ASN1_SUCCESS) { + /* couldn't decode DER */ + gnutls_assert(); + asn1_delete_structure(&dn); + return _gnutls_asn2err(result); + } + + result = + asn1_der_decoding_startEnd(dn, cert->cert.data, + cert->cert.size, + "tbsCertificate.issuer", &start, &end); + + if (result != ASN1_SUCCESS) { + /* couldn't decode DER */ + gnutls_assert(); + asn1_delete_structure(&dn); + return _gnutls_asn2err(result); + } + asn1_delete_structure(&dn); + + len = end - start + 1; + + odn->size = len; + odn->data = &cert->cert.data[start]; + + return 0; +} + +/* Locates the most appropriate x509 certificate using the + * given DN. If indx == -1 then no certificate was found. + * + * That is to guess which certificate to use, based on the + * CAs and sign algorithms supported by the peer server. + */ +static int +find_x509_client_cert(gnutls_session_t session, + const gnutls_certificate_credentials_t cred, + const uint8_t * _data, size_t _data_size, + const gnutls_pk_algorithm_t * pk_algos, + int pk_algos_length, int *indx) +{ + unsigned size; + gnutls_datum_t odn = { NULL, 0 }, asked_dn; + const uint8_t *data = _data; + ssize_t data_size = _data_size; + unsigned i, j; + int result, cert_pk; + unsigned key_usage; + + *indx = -1; + + /* If peer doesn't send any issuers and we have a single certificate + * then send that one. + */ + if (cred->ncerts == 1 && + (data_size == 0 + || (session->internals.flags & GNUTLS_FORCE_CLIENT_CERT))) { + if (cred->certs[0].cert_list[0].type == GNUTLS_CRT_X509) { + + key_usage = get_key_usage(session, cred->certs[0].cert_list[0].pubkey); + + /* For client certificates we require signatures */ + result = _gnutls_check_key_usage_for_sig(session, key_usage, 1); + if (result < 0) { + _gnutls_debug_log("Client certificate is not suitable for signing\n"); + return gnutls_assert_val(result); + } + + *indx = 0; + return 0; + } + } + + do { + DECR_LENGTH_RET(data_size, 2, 0); + size = _gnutls_read_uint16(data); + DECR_LENGTH_RET(data_size, size, 0); + data += 2; + + asked_dn.data = (void*)data; + asked_dn.size = size; + _gnutls_dn_log("Peer requested CA", &asked_dn); + + for (i = 0; i < cred->ncerts; i++) { + for (j = 0; j < cred->certs[i].cert_list_length; j++) { + if ((result = + cert_get_issuer_dn(&cred->certs + [i].cert_list + [j], &odn)) < 0) { + gnutls_assert(); + return result; + } + + if (odn.size == 0 || odn.size != asked_dn.size) + continue; + + key_usage = get_key_usage(session, cred->certs[i].cert_list[0].pubkey); + + /* For client certificates we require signatures */ + if (_gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0) { + _gnutls_debug_log("Client certificate is not suitable for signing\n"); + continue; + } + + /* If the DN matches and + * the *_SIGN algorithm matches + * the cert is our cert! + */ + cert_pk = + gnutls_pubkey_get_pk_algorithm(cred->certs + [i].cert_list + [0].pubkey, + NULL); + + if ((memcmp(odn.data, asked_dn.data, asked_dn.size) == 0) && + (check_pk_algo_in_list + (pk_algos, pk_algos_length, + cert_pk) == 0)) { + *indx = i; + break; + } + } + if (*indx != -1) + break; + } + + if (*indx != -1) + break; + + /* move to next record */ + data += size; + } + while (1); + + return 0; + +} + + +/* Locates the first raw public-key. + * Currently it only makes sense to associate one raw pubkey per session. + * Associating more raw pubkeys with a session has no use because we + * don't know how to select the correct one. + */ +static int +find_rawpk_client_cert(gnutls_session_t session, + const gnutls_certificate_credentials_t cred, + const gnutls_pk_algorithm_t* pk_algos, + int pk_algos_length, int* indx) +{ + unsigned i; + int ret; + gnutls_pk_algorithm_t pk; + + *indx = -1; + + for (i = 0; i < cred->ncerts; i++) { + /* We know that our list length will be 1, therefore we can + * ignore the rest. + */ + if (cred->certs[i].cert_list_length == 1 && cred->certs[i].cert_list[0].type == GNUTLS_CRT_RAWPK) { + pk = gnutls_pubkey_get_pk_algorithm(cred->certs[i].cert_list[0].pubkey, NULL); + + /* For client certificates we require signatures */ + ret = _gnutls_check_key_usage_for_sig(session, get_key_usage(session, cred->certs[i].cert_list[0].pubkey), 1); + if (ret < 0) { + /* we return an error instead of skipping so that the user is notified about + * the key incompatibility */ + _gnutls_debug_log("Client certificate is not suitable for signing\n"); + return gnutls_assert_val(ret); + } + + /* Check whether the public-key algorithm of our credential is in + * the list with supported public-key algorithms and whether the + * cert type matches. */ + if ((check_pk_algo_in_list(pk_algos, pk_algos_length, pk) == 0)) { + // We found a compatible credential + *indx = i; + break; + } + } + } + + return 0; +} + + +/* Returns the number of issuers in the server's + * certificate request packet. + */ +static int +get_issuers_num(gnutls_session_t session, const uint8_t * data, ssize_t data_size) +{ + int issuers_dn_len = 0; + unsigned size; + + /* Count the number of the given issuers; + * This is used to allocate the issuers_dn without + * using realloc(). + */ + + if (data_size == 0 || data == NULL) + return 0; + + while (data_size > 0) { + /* This works like DECR_LEN() + */ + DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + size = _gnutls_read_uint16(data); + + DECR_LENGTH_RET(data_size, size, GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + data += 2; + + if (size > 0) { + issuers_dn_len++; + data += size; + } + } + + return issuers_dn_len; +} + +/* Returns the issuers in the server's certificate request + * packet. + */ +static int +get_issuers(gnutls_session_t session, + gnutls_datum_t * issuers_dn, int issuers_len, + const uint8_t * data, size_t data_size) +{ + int i; + unsigned size; + + if (get_certificate_type(session, GNUTLS_CTYPE_CLIENT) != GNUTLS_CRT_X509) + return 0; + + /* put the requested DNs to req_dn, only in case + * of X509 certificates. + */ + if (issuers_len > 0) { + + for (i = 0; i < issuers_len; i++) { + /* The checks here for the buffer boundaries + * are not needed since the buffer has been + * parsed above. + */ + data_size -= 2; + + size = _gnutls_read_uint16(data); + + data += 2; + + issuers_dn[i].data = (void*)data; + issuers_dn[i].size = size; + + _gnutls_dn_log("Peer requested CA", &issuers_dn[i]); + + data += size; + } + } + + return 0; +} + +/* Calls the client or server certificate get callback. + */ +static int +call_get_cert_callback(gnutls_session_t session, + const gnutls_datum_t * issuers_dn, + int issuers_dn_length, + gnutls_pk_algorithm_t * pk_algos, int pk_algos_length) +{ + gnutls_privkey_t local_key = NULL; + int ret = GNUTLS_E_INTERNAL_ERROR; + gnutls_certificate_type_t type; + gnutls_certificate_credentials_t cred; + gnutls_pcert_st *pcert = NULL; + gnutls_ocsp_data_st *ocsp = NULL; + unsigned int ocsp_length = 0; + unsigned int pcert_length = 0; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + /* Correctly set the certificate type for ourselves */ + type = get_certificate_type(session, GNUTLS_CTYPE_OURS); + + /* Check whether a callback is set and call it */ + if (cred->get_cert_callback3) { + struct gnutls_cert_retr_st info; + unsigned int flags = 0; + + memset(&info, 0, sizeof(info)); + info.req_ca_rdn = issuers_dn; + info.nreqs = issuers_dn_length; + info.pk_algos = pk_algos; + info.pk_algos_length = pk_algos_length; + info.cred = cred; + + /* we avoid all allocations and transformations */ + ret = + cred->get_cert_callback3(session, &info, + &pcert, &pcert_length, + &ocsp, &ocsp_length, + &local_key, &flags); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_USER_ERROR); + + if (pcert_length > 0 && type != pcert[0].type) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (pcert_length == 0) { + pcert = NULL; + local_key = NULL; + } + + selected_certs_set(session, pcert, pcert_length, + ocsp, ocsp_length, + local_key, (flags&GNUTLS_CERT_RETR_DEINIT_ALL)?1:0, + cred->glob_ocsp_func, cred->glob_ocsp_func_ptr); + + return 0; + } else { + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } +} + +/* Finds the appropriate certificate depending on the cA Distinguished name + * advertized by the server. If none matches then returns 0 and -1 as index. + * In case of an error a negative error code, is returned. + * + * 20020128: added ability to select a certificate depending on the SIGN + * algorithm (only in automatic mode). + */ +int +_gnutls_select_client_cert(gnutls_session_t session, + const uint8_t * _data, size_t _data_size, + gnutls_pk_algorithm_t * pk_algos, int pk_algos_length) +{ + int result; + int indx = -1; + gnutls_certificate_credentials_t cred; + const uint8_t *data = _data; + ssize_t data_size = _data_size; + int issuers_dn_length; + gnutls_datum_t *issuers_dn = NULL; + gnutls_certificate_type_t cert_type; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT); + + if (cred->get_cert_callback3 != NULL) { + + /* use a callback to get certificate + */ + if (cert_type == GNUTLS_CRT_X509) { + issuers_dn_length = + get_issuers_num(session, data, data_size); + if (issuers_dn_length < 0) { + gnutls_assert(); + return issuers_dn_length; + } + + if (issuers_dn_length > 0) { + issuers_dn = + gnutls_malloc(sizeof(gnutls_datum_t) * + issuers_dn_length); + if (issuers_dn == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + result = + get_issuers(session, issuers_dn, + issuers_dn_length, data, + data_size); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + } + } else { + issuers_dn_length = 0; + } + + result = + call_get_cert_callback(session, issuers_dn, + issuers_dn_length, pk_algos, + pk_algos_length); + goto cleanup; + + } else { + /* If we have no callbacks, try to guess. + */ + switch (cert_type) { + case GNUTLS_CRT_X509: + result = find_x509_client_cert(session, cred, _data, + _data_size, pk_algos, + pk_algos_length, &indx); + break; + case GNUTLS_CRT_RAWPK: + result = find_rawpk_client_cert(session, cred, + pk_algos, pk_algos_length, &indx); + break; + default: + result = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + break; + } + + if (result < 0) { + return gnutls_assert_val(result); + } + + if (indx >= 0) { + selected_certs_set(session, + &cred->certs[indx]. + cert_list[0], + cred->certs[indx]. + cert_list_length, + cred->certs[indx].ocsp_data, + cred->certs[indx].ocsp_data_length, + cred->certs[indx].pkey, 0, + NULL, NULL); + } else { + selected_certs_set(session, NULL, 0, NULL, 0, + NULL, 0, NULL, NULL); + } + + result = 0; + } + + cleanup: + gnutls_free(issuers_dn); + return result; + +} + +/* Generate certificate message + */ +static int gen_x509_crt(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret, i; + gnutls_pcert_st *apr_cert_list; + gnutls_privkey_t apr_pkey; + int apr_cert_list_length; + unsigned init_pos = data->length; + + /* find the appropriate certificate + */ + if ((ret = + _gnutls_get_selected_cert(session, &apr_cert_list, + &apr_cert_list_length, &apr_pkey)) < 0) { + gnutls_assert(); + return ret; + } + + ret = 3; + for (i = 0; i < apr_cert_list_length; i++) { + ret += apr_cert_list[i].cert.size + 3; + /* hold size + * for uint24 */ + } + + /* if no certificates were found then send: + * 0B 00 00 03 00 00 00 // Certificate with no certs + * instead of: + * 0B 00 00 00 // empty certificate handshake + * + * ( the above is the whole handshake message, not + * the one produced here ) + */ + + ret = _gnutls_buffer_append_prefix(data, 24, ret - 3); + if (ret < 0) + return gnutls_assert_val(ret); + + for (i = 0; i < apr_cert_list_length; i++) { + ret = + _gnutls_buffer_append_data_prefix(data, 24, + apr_cert_list[i]. + cert.data, + apr_cert_list[i]. + cert.size); + if (ret < 0) + return gnutls_assert_val(ret); + } + + return data->length - init_pos; +} + + +/* Generates a Raw Public Key certificate message that holds only the + * SubjectPublicKeyInfo part of a regular certificate message. + * + * Returns the number of bytes sent or a negative error code. + */ +int +_gnutls_gen_rawpk_crt(gnutls_session_t session, gnutls_buffer_st* data) +{ + int ret; + gnutls_pcert_st *apr_cert_list; + gnutls_privkey_t apr_pkey; + int apr_cert_list_length; + + if((ret = _gnutls_get_selected_cert(session, &apr_cert_list, + &apr_cert_list_length, &apr_pkey)) < 0) { + return gnutls_assert_val(ret); + } + + /* Since we are transmitting a raw public key with no additional + * certificate credentials attached to it, it doesn't make sense to + * have more than one certificate set (i.e. to have a certificate chain). + */ + assert(apr_cert_list_length <= 1); + + /* Write our certificate containing only the SubjectPublicKeyInfo to + * the output buffer. We always have exactly one certificate that + * contains our raw public key. Our message looks like: + * <length++certificate> where + * length = 3 bytes (or 24 bits) and + * certificate = length bytes. + */ + if (apr_cert_list_length == 0) { + ret = _gnutls_buffer_append_prefix(data, 24, 0); + } else { + ret = _gnutls_buffer_append_data_prefix(data, 24, + apr_cert_list[0].cert.data, + apr_cert_list[0].cert.size); + } + + + if (ret < 0) return gnutls_assert_val(ret); + + return data->length; +} + + +int +_gnutls_gen_cert_client_crt(gnutls_session_t session, gnutls_buffer_st * data) +{ + gnutls_certificate_type_t cert_type; + + // Retrieve the (negotiated) certificate type for the client + cert_type = get_certificate_type(session, GNUTLS_CTYPE_CLIENT); + + switch (cert_type) { + case GNUTLS_CRT_X509: + return gen_x509_crt(session, data); + case GNUTLS_CRT_RAWPK: + return _gnutls_gen_rawpk_crt(session, data); + default: + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } +} + +int +_gnutls_gen_cert_server_crt(gnutls_session_t session, gnutls_buffer_st * data) +{ + gnutls_certificate_type_t cert_type; + + // Retrieve the (negotiated) certificate type for the server + cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER); + + switch (cert_type) { + case GNUTLS_CRT_X509: + return gen_x509_crt(session, data); + case GNUTLS_CRT_RAWPK: + return _gnutls_gen_rawpk_crt(session, data); + default: + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } +} + +static +int check_pk_compat(gnutls_session_t session, gnutls_pubkey_t pubkey) +{ + unsigned cert_pk; + unsigned kx; + + if (session->security_parameters.entity != GNUTLS_CLIENT) + return 0; + + cert_pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL); + if (cert_pk == GNUTLS_PK_UNKNOWN) { + gnutls_assert(); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + kx = session->security_parameters.cs->kx_algorithm; + + if (_gnutls_map_kx_get_cred(kx, 1) == GNUTLS_CRD_CERTIFICATE && + !_gnutls_kx_supports_pk(kx, cert_pk)) { + gnutls_assert(); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + return 0; +} + +/* Process server certificate + */ +#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) gnutls_pcert_deinit(&peer_certificate_list[x]) +static int +_gnutls_proc_x509_crt(gnutls_session_t session, + uint8_t * data, size_t data_size) +{ + int size, len, ret; + uint8_t *p = data; + cert_auth_info_t info; + gnutls_certificate_credentials_t cred; + ssize_t dsize = data_size; + int i; + gnutls_pcert_st *peer_certificate_list; + size_t peer_certificate_list_size = 0, j, x; + gnutls_datum_t tmp; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, + sizeof(cert_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + if (unlikely(!info)) { + gnutls_assert(); + return ret; + } + + if (data == NULL || data_size == 0) { + gnutls_assert(); + /* no certificate was sent */ + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } + + DECR_LEN(dsize, 3); + size = _gnutls_read_uint24(p); + p += 3; + + /* ensure no discrepancy in data */ + if (size != dsize) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* some implementations send 0B 00 00 06 00 00 03 00 00 00 + * instead of just 0B 00 00 03 00 00 00 as an empty certificate message. + */ + if (size == 0 || (size == 3 && memcmp(p, "\x00\x00\x00", 3) == 0)) { + gnutls_assert(); + /* no certificate was sent */ + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } + + i = dsize; + while (i > 0) { + DECR_LEN(dsize, 3); + len = _gnutls_read_uint24(p); + p += 3; + DECR_LEN(dsize, len); + peer_certificate_list_size++; + p += len; + i -= len + 3; + } + + if (dsize != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (peer_certificate_list_size == 0) { + gnutls_assert(); + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } + + /* Ok we now allocate the memory to hold the + * certificate list + */ + + peer_certificate_list = + gnutls_calloc(1, + sizeof(gnutls_pcert_st) * + (peer_certificate_list_size)); + if (peer_certificate_list == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + p = data + 3; + + /* Now we start parsing the list (again). + * We don't use DECR_LEN since the list has + * been parsed before. + */ + + for (j = 0; j < peer_certificate_list_size; j++) { + len = _gnutls_read_uint24(p); + p += 3; + + tmp.size = len; + tmp.data = p; + + ret = + gnutls_pcert_import_x509_raw(&peer_certificate_list + [j], &tmp, + GNUTLS_X509_FMT_DER, 0); + if (ret < 0) { + gnutls_assert(); + peer_certificate_list_size = j; + ret = GNUTLS_E_CERTIFICATE_ERROR; + goto cleanup; + } + + p += len; + } + + ret = check_pk_compat(session, peer_certificate_list[0].pubkey); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = + _gnutls_pcert_to_auth_info(info, + peer_certificate_list, + peer_certificate_list_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + return 0; + + cleanup: + CLEAR_CERTS; + gnutls_free(peer_certificate_list); + return ret; + +} + + +int _gnutls_proc_rawpk_crt(gnutls_session_t session, + uint8_t * data, size_t data_size) +{ + int cert_size, ret; + cert_auth_info_t info; + gnutls_pcert_st* peer_certificate; + gnutls_datum_t tmp_cert; + + uint8_t *p = data; + ssize_t dsize = data_size; + + /* We assume data != null and data_size > 0 because + * the caller checks this for us. */ + + /* Read the length of our certificate. We always have exactly + * one certificate that contains our raw public key. Our message + * looks like: + * <length++certificate> where + * length = 3 bytes and + * certificate = length bytes. + */ + DECR_LEN(dsize, 3); + cert_size = _gnutls_read_uint24(p); + p += 3; + + /* Ensure no discrepancy in data */ + if (cert_size != dsize) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + + if (cert_size == 0) { + // No certificate was sent. This is not OK. + return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND); + } + + DECR_LEN_FINAL(dsize, cert_size); + + /* We are now going to read our certificate and store it into + * the authentication info structure. + */ + tmp_cert.size = cert_size; + tmp_cert.data = p; + + peer_certificate = gnutls_calloc(1, sizeof(*peer_certificate)); + if (peer_certificate == NULL) { + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + } + + // Import our raw certificate holding only a raw public key into this pcert + ret = gnutls_pcert_import_rawpk_raw(peer_certificate, &tmp_cert, GNUTLS_X509_FMT_DER, 0, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + // Check whether the PK algo is compatible with the negotiated KX + ret = check_pk_compat(session, peer_certificate->pubkey); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, + sizeof(cert_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + if (unlikely(!info)) { + gnutls_assert(); + goto cleanup; + } + + /* Copy our imported certificate into the auth info structure + * and free our temporary cert storage peer_certificate. + */ + ret = _gnutls_pcert_to_auth_info(info, peer_certificate, 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + return GNUTLS_E_SUCCESS; + +cleanup: + if (peer_certificate != NULL) { + gnutls_pcert_deinit(peer_certificate); + gnutls_free(peer_certificate); + } + + return ret; +} + + +int _gnutls_proc_crt(gnutls_session_t session, uint8_t * data, size_t data_size) +{ + gnutls_certificate_credentials_t cred; + gnutls_certificate_type_t cert_type; + + cred = + (gnutls_certificate_credentials_t) _gnutls_get_cred(session, + GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + /* Determine what certificate type we need to process. + * We need to process the certificate of the peer. */ + cert_type = get_certificate_type(session, GNUTLS_CTYPE_PEERS); + + switch (cert_type) { + case GNUTLS_CRT_X509: + return _gnutls_proc_x509_crt(session, data, data_size); + case GNUTLS_CRT_RAWPK: + return _gnutls_proc_rawpk_crt(session, data, data_size); + default: + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } +} + +/* Checks if we support the given signature algorithm + * (RSA or DSA). Returns the corresponding gnutls_pk_algorithm_t + * if true; + */ +inline static int _gnutls_check_supported_sign_algo(CertificateSigType algo) +{ + switch (algo) { + case RSA_SIGN: + return GNUTLS_PK_RSA; + case DSA_SIGN: + return GNUTLS_PK_DSA; + case ECDSA_SIGN: + return GNUTLS_PK_EC; +#ifdef ENABLE_GOST + case GOSTR34102012_256_SIGN: + return GNUTLS_PK_GOST_12_256; + case GOSTR34102012_512_SIGN: + return GNUTLS_PK_GOST_12_512; +#endif + } + + return -1; +} + +int +_gnutls_proc_cert_cert_req(gnutls_session_t session, uint8_t * data, + size_t data_size) +{ + int size, ret; + uint8_t *p; + gnutls_certificate_credentials_t cred; + ssize_t dsize; + int i; + gnutls_pk_algorithm_t pk_algos[MAX_CLIENT_SIGN_ALGOS]; + int pk_algos_length; + const version_entry_st *ver = get_version(session); + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, + sizeof(cert_auth_info_st), 0)) < 0) { + gnutls_assert(); + return ret; + } + + p = data; + dsize = data_size; + + DECR_LEN(dsize, 1); + size = p[0]; + p++; + /* check if the sign algorithm is supported. + */ + pk_algos_length = 0; + for (i = 0; i < size; i++, p++) { + DECR_LEN(dsize, 1); + if ((ret = _gnutls_check_supported_sign_algo(*p)) > 0) { + if (pk_algos_length < MAX_CLIENT_SIGN_ALGOS) { + pk_algos[pk_algos_length++] = ret; + } + } + } + + if (pk_algos_length == 0) { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_PK_ALGORITHM; + } + + if (_gnutls_version_has_selectable_sighash(ver)) { + /* read supported hashes */ + int hash_num; + DECR_LEN(dsize, 2); + hash_num = _gnutls_read_uint16(p); + p += 2; + DECR_LEN(dsize, hash_num); + + ret = _gnutls_sign_algorithm_parse_data(session, p, hash_num); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + p += hash_num; + } + + /* read the certificate authorities */ + DECR_LEN(dsize, 2); + size = _gnutls_read_uint16(p); + p += 2; + + DECR_LEN_FINAL(dsize, size); + + /* We should reply with a certificate message, + * even if we have no certificate to send. + */ + session->internals.hsk_flags |= HSK_CRT_ASKED; + + /* now we ask the user to tell which one + * he wants to use. + */ + if ((ret = + _gnutls_select_client_cert(session, p, size, pk_algos, + pk_algos_length)) < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +int +_gnutls_gen_cert_client_crt_vrfy(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret; + gnutls_pcert_st *apr_cert_list; + gnutls_privkey_t apr_pkey; + int apr_cert_list_length; + gnutls_datum_t signature = { NULL, 0 }; + gnutls_sign_algorithm_t sign_algo; + const version_entry_st *ver = get_version(session); + unsigned init_pos = data->length; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + /* find the appropriate certificate */ + if ((ret = + _gnutls_get_selected_cert(session, &apr_cert_list, + &apr_cert_list_length, &apr_pkey)) < 0) { + gnutls_assert(); + return ret; + } + + if (apr_cert_list_length > 0) { + if ((ret = + _gnutls_handshake_sign_crt_vrfy(session, + &apr_cert_list[0], + apr_pkey, + &signature)) < 0) { + gnutls_assert(); + return ret; + } + sign_algo = ret; + } else { + return 0; + } + + if (_gnutls_version_has_selectable_sighash(ver)) { + const sign_algorithm_st *aid; + uint8_t p[2]; + /* error checking is not needed here since we have used those algorithms */ + aid = _gnutls_sign_to_tls_aid(sign_algo); + if (aid == NULL) + return gnutls_assert_val(GNUTLS_E_UNKNOWN_ALGORITHM); + + p[0] = aid->id[0]; + p[1] = aid->id[1]; + ret = _gnutls_buffer_append_data(data, p, 2); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + ret = + _gnutls_buffer_append_data_prefix(data, 16, signature.data, + signature.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + + cleanup: + _gnutls_free_datum(&signature); + return ret; +} + +int +_gnutls_proc_cert_client_crt_vrfy(gnutls_session_t session, + uint8_t * data, size_t data_size) +{ + int size, ret; + ssize_t dsize = data_size; + uint8_t *pdata = data; + gnutls_datum_t sig; + cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + gnutls_pcert_st peer_cert; + gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; + const version_entry_st *ver = get_version(session); + gnutls_certificate_credentials_t cred; + unsigned vflags; + + if (unlikely(info == NULL || info->ncerts == 0 || ver == NULL)) { + gnutls_assert(); + /* we need this in order to get peer's certificate */ + return GNUTLS_E_INTERNAL_ERROR; + } + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + vflags = cred->verify_flags | session->internals.additional_verify_flags; + + if (_gnutls_version_has_selectable_sighash(ver)) { + DECR_LEN(dsize, 2); + + sign_algo = _gnutls_tls_aid_to_sign(pdata[0], pdata[1], ver); + if (sign_algo == GNUTLS_SIGN_UNKNOWN) { + gnutls_assert(); + return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; + } + pdata += 2; + } + + ret = _gnutls_session_sign_algo_enabled(session, sign_algo); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); + + DECR_LEN(dsize, 2); + size = _gnutls_read_uint16(pdata); + pdata += 2; + + DECR_LEN_FINAL(dsize, size); + + sig.data = pdata; + sig.size = size; + + ret = _gnutls_get_auth_info_pcert(&peer_cert, + session->security_parameters. + client_ctype, info); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if ((ret = + _gnutls_handshake_verify_crt_vrfy(session, vflags, &peer_cert, &sig, + sign_algo)) < 0) { + gnutls_assert(); + gnutls_pcert_deinit(&peer_cert); + return ret; + } + gnutls_pcert_deinit(&peer_cert); + + return 0; +} + +int +_gnutls_gen_cert_server_cert_req(gnutls_session_t session, + gnutls_buffer_st * data) +{ + gnutls_certificate_credentials_t cred; + int ret, i; + uint8_t tmp_data[CERTTYPE_SIZE]; + const version_entry_st *ver = get_version(session); + unsigned init_pos = data->length; + enum CertificateSigTypeFlags flags; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + /* Now we need to generate the RDN sequence. This is + * already in the CERTIFICATE_CRED structure, to improve + * performance. + */ + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if (_gnutls_version_has_selectable_sighash(ver)) { + size_t j; + + flags = 0; + for (j = 0; j < session->internals.priorities->sigalg.size; j++) { + const gnutls_sign_entry_st *se = + session->internals.priorities->sigalg.entry[j]; + switch (se->pk) { + case GNUTLS_PK_RSA: + case GNUTLS_PK_RSA_PSS: + flags |= RSA_SIGN_FLAG; + break; + case GNUTLS_PK_DSA: + flags |= DSA_SIGN_FLAG; + break; + case GNUTLS_PK_ECDSA: + flags |= ECDSA_SIGN_FLAG; + break; +#ifdef ENABLE_GOST + case GNUTLS_PK_GOST_12_256: + flags |= GOSTR34102012_256_SIGN_FLAG; + break; + case GNUTLS_PK_GOST_12_512: + flags |= GOSTR34102012_512_SIGN_FLAG; + break; +#endif + default: + gnutls_assert(); + _gnutls_debug_log( + "%s is unsupported for cert request\n", + gnutls_pk_get_name(se->pk)); + } + } + + } else { +#ifdef ENABLE_GOST + if (_gnutls_kx_is_vko_gost(session->security_parameters. + cs->kx_algorithm)) { + flags = GOSTR34102012_256_SIGN_FLAG | + GOSTR34102012_512_SIGN_FLAG; + } else +#endif + { + flags = RSA_SIGN_FLAG | DSA_SIGN_FLAG | ECDSA_SIGN_FLAG; + } + } + + i = 1; + if (flags & RSA_SIGN_FLAG) { + tmp_data[i++] = RSA_SIGN; + } + if (flags & DSA_SIGN_FLAG) { + tmp_data[i++] = DSA_SIGN; + } + if (flags & ECDSA_SIGN_FLAG) { + tmp_data[i++] = ECDSA_SIGN; + } +#ifdef ENABLE_GOST + if (flags & GOSTR34102012_256_SIGN_FLAG) { + tmp_data[i++] = GOSTR34102012_256_SIGN; + } + if (flags & GOSTR34102012_512_SIGN_FLAG) { + tmp_data[i++] = GOSTR34102012_512_SIGN; + } +#endif + tmp_data[0] = i - 1; + + ret = _gnutls_buffer_append_data(data, tmp_data, i); + if (ret < 0) + return gnutls_assert_val(ret); + + if (_gnutls_version_has_selectable_sighash(ver)) { + ret = + _gnutls_sign_algorithm_write_params(session, data); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + if (session->security_parameters.client_ctype == GNUTLS_CRT_X509 && + session->internals.ignore_rdn_sequence == 0) { + + ret = + _gnutls_buffer_append_data_prefix(data, 16, + cred-> + tlist->x509_rdn_sequence. + data, + cred-> + tlist->x509_rdn_sequence. + size); + if (ret < 0) + return gnutls_assert_val(ret); + } else { + ret = _gnutls_buffer_append_prefix(data, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + } + + return data->length - init_pos; +} + +/* This function will return the appropriate certificate to use. + * Fills in the apr_cert_list, apr_cert_list_length and apr_pkey. + * The return value is a negative error code on error. + * + * It is normal to return 0 with no certificates in client side. + * + */ +int +_gnutls_get_selected_cert(gnutls_session_t session, + gnutls_pcert_st ** apr_cert_list, + int *apr_cert_list_length, + gnutls_privkey_t * apr_pkey) +{ + if (session->security_parameters.entity == GNUTLS_SERVER) { + + *apr_cert_list = session->internals.selected_cert_list; + *apr_pkey = session->internals.selected_key; + *apr_cert_list_length = + session->internals.selected_cert_list_length; + + if (*apr_cert_list_length == 0 || *apr_cert_list == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + } else { /* CLIENT SIDE */ + /* _gnutls_select_client_cert() must have been called before. + */ + *apr_cert_list = session->internals.selected_cert_list; + *apr_cert_list_length = + session->internals.selected_cert_list_length; + *apr_pkey = session->internals.selected_key; + + } + + return 0; +} + + +void _gnutls_selected_certs_deinit(gnutls_session_t session) +{ + if (session->internals.selected_need_free != 0) { + int i; + + for (i = 0; + i < session->internals.selected_cert_list_length; i++) { + gnutls_pcert_deinit(&session->internals. + selected_cert_list[i]); + } + gnutls_free(session->internals.selected_cert_list); + + for (i = 0; + i < session->internals.selected_ocsp_length; i++) { + _gnutls_free_datum(&session->internals. + selected_ocsp[i].response); + } + gnutls_free(session->internals.selected_ocsp); + + gnutls_privkey_deinit(session->internals.selected_key); + } + session->internals.selected_ocsp_func = NULL; + + session->internals.selected_cert_list = NULL; + session->internals.selected_cert_list_length = 0; + + session->internals.selected_key = NULL; + + return; +} + +static void +selected_certs_set(gnutls_session_t session, + gnutls_pcert_st * certs, int ncerts, + gnutls_ocsp_data_st *ocsp, unsigned nocsp, + gnutls_privkey_t key, int need_free, + gnutls_status_request_ocsp_func ocsp_func, + void *ocsp_func_ptr) +{ + _gnutls_selected_certs_deinit(session); + + session->internals.selected_cert_list = certs; + session->internals.selected_cert_list_length = ncerts; + + session->internals.selected_ocsp = ocsp; + session->internals.selected_ocsp_length = nocsp; + + session->internals.selected_key = key; + session->internals.selected_need_free = need_free; + + session->internals.selected_ocsp_func = ocsp_func; + session->internals.selected_ocsp_func_ptr = ocsp_func_ptr; +} + +static void get_server_name(gnutls_session_t session, uint8_t * name, + size_t max_name_size) +{ + int ret, i; + size_t max_name; + unsigned int type; + + ret = 0; + for (i = 0; !(ret < 0); i++) { + max_name = max_name_size; + ret = + gnutls_server_name_get(session, name, &max_name, &type, i); + if (ret >= 0 && type == GNUTLS_NAME_DNS) + return; + } + + name[0] = 0; + + return; +} + +/* Checks the compatibility of the pubkey in the certificate with the + * ciphersuite and selects a signature algorithm (if required by the + * ciphersuite and TLS version) appropriate for the certificate. If none + * can be selected returns an error. + * + * IMPORTANT + * Currently this function is only called from _gnutls_select_server_cert, + * i.e. it is only called at the server. We therefore retrieve the + * negotiated server certificate type within this function. + * If, in the future, this routine is called at the client then we + * need to adapt the implementation accordingly. + */ +static +int cert_select_sign_algorithm(gnutls_session_t session, + gnutls_pcert_st * cert, + gnutls_privkey_t pkey, + const gnutls_cipher_suite_entry_st *cs) +{ + gnutls_pubkey_t pubkey = cert->pubkey; + gnutls_certificate_type_t cert_type = cert->type; + unsigned pk = pubkey->params.algo; + unsigned key_usage; + gnutls_sign_algorithm_t algo; + const version_entry_st *ver = get_version(session); + gnutls_certificate_type_t ctype; + + assert(IS_SERVER(session)); + + /* Retrieve the server certificate type */ + ctype = get_certificate_type(session, GNUTLS_CTYPE_SERVER); + + if (ctype != cert_type) { + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + } + + key_usage = get_key_usage(session, pubkey); + + /* In TLS1.3 we support only signatures; ensure the selected key supports them */ + if (ver->tls13_sem && _gnutls_check_key_usage_for_sig(session, key_usage, 1) < 0) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + if (!ver->tls13_sem && !_gnutls_kx_supports_pk_usage(cs->kx_algorithm, pk, key_usage)) { + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + } + + if (!ver->tls13_sem && _gnutls_kx_encipher_type(cs->kx_algorithm) != CIPHER_SIGN) + return 0; + + if (!_gnutls_version_has_selectable_sighash(ver)) { + /* For SSL3.0 and TLS1.0 we lie as we cannot express md5-sha1 as + * signature algorithm. */ + algo = gnutls_pk_to_sign(cert->pubkey->params.algo, GNUTLS_DIG_SHA1); + gnutls_sign_algorithm_set_server(session, algo); + return 0; + } + + algo = _gnutls_session_get_sign_algo(session, cert, pkey, 0, cs->kx_algorithm); + if (algo == GNUTLS_SIGN_UNKNOWN) + return gnutls_assert_val(GNUTLS_E_INCOMPATIBLE_SIG_WITH_KEY); + + gnutls_sign_algorithm_set_server(session, algo); + _gnutls_handshake_log("Selected signature algorithm: %s\n", gnutls_sign_algorithm_get_name(algo)); + + return 0; +} + +/* finds the most appropriate certificate in the cert list. + * The 'appropriate' is defined by the user. + * + * requested_algo holds the parameters required by the peer (RSA, DSA + * or -1 for any). + * + * Returns 0 on success and a negative error code on error. The + * selected certificate will be in session->internals.selected_*. + * + */ +int +_gnutls_select_server_cert(gnutls_session_t session, const gnutls_cipher_suite_entry_st *cs) +{ + unsigned i, j; + int idx, ret; + gnutls_certificate_credentials_t cred; + char server_name[MAX_CN]; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); /* we don't need to select a cert */ + return 0; + } + + /* When a callback is set, we call it once to get the + * certificate and then check its compatibility with + * the ciphersuites. + */ + if (cred->get_cert_callback3) { + if (session->internals.selected_cert_list_length == 0) { + ret = call_get_cert_callback(session, NULL, 0, NULL, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + if (session->internals.selected_cert_list_length == 0) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + _gnutls_debug_log("Selected (%s) cert\n", + gnutls_pk_get_name(session->internals.selected_cert_list[0].pubkey->params.algo)); + } + + ret = cert_select_sign_algorithm(session, + &session->internals.selected_cert_list[0], + session->internals.selected_key, + cs); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; + } + + /* Otherwise... we check the compatibility of the ciphersuite + * with all the certificates available. */ + + get_server_name(session, (unsigned char *)server_name, + sizeof(server_name)); + + _gnutls_handshake_log ("HSK[%p]: Requested server name: '%s'\n", + session, server_name); + idx = -1; /* default is use no certificate */ + + /* find certificates that match the requested server_name + */ + + if (server_name[0] != 0) { + for (j = 0; j < cred->ncerts; j++) { + i = cred->sorted_cert_idx[j]; + + if (cred->certs[i].names != NULL + && _gnutls_str_array_match(cred->certs[i].names, + server_name) != 0) { + /* if requested algorithms are also compatible select it */ + + ret = cert_select_sign_algorithm(session, + &cred->certs[i].cert_list[0], + cred->certs[i].pkey, + cs); + if (ret >= 0) { + idx = i; + _gnutls_debug_log("Selected (%s) cert based on ciphersuite %x.%x: %s\n", + gnutls_pk_get_name(cred->certs[i].cert_list[0].pubkey->params.algo), + (unsigned)cs->id[0], + (unsigned)cs->id[1], + cs->name); + /* found */ + goto finished; + } + } + } + } + + /* no name match */ + for (j = 0; j < cred->ncerts; j++) { + i = cred->sorted_cert_idx[j]; + + _gnutls_handshake_log + ("HSK[%p]: checking compat of %s with certificate[%d] (%s/%s)\n", + session, cs->name, i, + gnutls_pk_get_name(cred->certs[i].cert_list[0].pubkey-> + params.algo), + gnutls_certificate_type_get_name(cred->certs[i]. + cert_list[0].type)); + + ret = cert_select_sign_algorithm(session, + &cred->certs[i].cert_list[0], + cred->certs[i].pkey, + cs); + if (ret >= 0) { + idx = i; + _gnutls_debug_log("Selected (%s) cert based on ciphersuite %x.%x: %s\n", + gnutls_pk_get_name(cred->certs[i].cert_list[0].pubkey->params.algo), + (unsigned)cs->id[0], + (unsigned)cs->id[1], + cs->name); + /* found */ + goto finished; + } + } + + /* store the certificate pointer for future use, in the handshake. + * (This will allow not calling this callback again.) + */ + finished: + if (idx >= 0) { + gnutls_status_request_ocsp_func ocsp_func = NULL; + void *ocsp_ptr = NULL; + gnutls_ocsp_data_st *ocsp = NULL; + unsigned nocsp = 0; + + if (cred->certs[idx].ocsp_data_length > 0) { + ocsp = &cred->certs[idx].ocsp_data[0]; + nocsp = cred->certs[idx].ocsp_data_length; + } else if (cred->glob_ocsp_func != NULL) { + ocsp_func = cred->glob_ocsp_func; + ocsp_ptr = cred->glob_ocsp_func_ptr; + } else if (cred->certs[idx].ocsp_func != NULL) { + ocsp_func = cred->certs[idx].ocsp_func; + ocsp_ptr = cred->certs[idx].ocsp_func_ptr; + } + + selected_certs_set(session, + &cred->certs[idx].cert_list[0], + cred->certs[idx].cert_list_length, + ocsp, nocsp, + cred->certs[idx].pkey, 0, + ocsp_func, + ocsp_ptr); + } else { + /* Certificate does not support REQUESTED_ALGO. */ + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + } + + return 0; +} + +int _gnutls_gen_dhe_signature(gnutls_session_t session, + gnutls_buffer_st * data, uint8_t * plain, + unsigned plain_size) +{ + gnutls_pcert_st *apr_cert_list; + gnutls_privkey_t apr_pkey; + int apr_cert_list_length; + gnutls_datum_t signature = { NULL, 0 }, ddata; + gnutls_sign_algorithm_t sign_algo; + const version_entry_st *ver = get_version(session); + int ret; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ddata.data = plain; + ddata.size = plain_size; + + /* find the appropriate certificate */ + if ((ret = + _gnutls_get_selected_cert(session, &apr_cert_list, + &apr_cert_list_length, &apr_pkey)) < 0) { + gnutls_assert(); + return ret; + } + + if (apr_cert_list_length > 0) { + if ((ret = + _gnutls_handshake_sign_data(session, + &apr_cert_list[0], + apr_pkey, &ddata, + &signature, &sign_algo)) < 0) { + gnutls_assert(); + goto cleanup; + } + } else { + gnutls_assert(); + ret = 0; /* ANON-DH, do not put a signature - ILLEGAL! */ + goto cleanup; + } + + if (_gnutls_version_has_selectable_sighash(ver)) { + const sign_algorithm_st *aid; + uint8_t p[2]; + + if (sign_algo == GNUTLS_SIGN_UNKNOWN) { + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; + } + + aid = _gnutls_sign_to_tls_aid(sign_algo); + if (aid == NULL) { + gnutls_assert(); + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; + } + + p[0] = aid->id[0]; + p[1] = aid->id[1]; + + ret = _gnutls_buffer_append_data(data, p, 2); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + ret = + _gnutls_buffer_append_data_prefix(data, 16, signature.data, + signature.size); + if (ret < 0) { + gnutls_assert(); + } + + ret = 0; + + cleanup: + _gnutls_free_datum(&signature); + return ret; +} + +int +_gnutls_proc_dhe_signature(gnutls_session_t session, uint8_t * data, + size_t _data_size, gnutls_datum_t * vparams) +{ + int sigsize; + gnutls_datum_t signature; + int ret; + cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + ssize_t data_size = _data_size; + gnutls_pcert_st peer_cert; + gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; + const version_entry_st *ver = get_version(session); + gnutls_certificate_credentials_t cred; + unsigned vflags; + gnutls_certificate_type_t cert_type; + + if (unlikely(info == NULL || info->ncerts == 0 || ver == NULL)) { + gnutls_assert(); + /* we need this in order to get peer's certificate */ + return GNUTLS_E_INTERNAL_ERROR; + } + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + vflags = cred->verify_flags | session->internals.additional_verify_flags; + + /* VERIFY SIGNATURE */ + if (_gnutls_version_has_selectable_sighash(ver)) { + uint8_t id[2]; + + DECR_LEN(data_size, 1); + id[0] = *data++; + DECR_LEN(data_size, 1); + id[1] = *data++; + + sign_algo = _gnutls_tls_aid_to_sign(id[0], id[1], ver); + if (sign_algo == GNUTLS_SIGN_UNKNOWN) { + _gnutls_debug_log("unknown signature %d.%d\n", + (int)id[0], (int)id[1]); + gnutls_assert(); + return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; + } + } + DECR_LEN(data_size, 2); + sigsize = _gnutls_read_uint16(data); + data += 2; + + DECR_LEN_FINAL(data_size, sigsize); + signature.data = data; + signature.size = sigsize; + + // Retrieve the negotiated certificate type + cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER); + + if ((ret = + _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info)) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_handshake_verify_data(session, vflags, &peer_cert, vparams, + &signature, sign_algo); + + gnutls_pcert_deinit(&peer_cert); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} diff --git a/lib/auth/cert.h b/lib/auth/cert.h new file mode 100644 index 0000000..29b7220 --- /dev/null +++ b/lib/auth/cert.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2016-2019 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_AUTH_CERT_H +#define GNUTLS_LIB_AUTH_CERT_H + +#include "auth.h" +#include <auth/dh_common.h> +#include <x509/x509_int.h> +#include <gnutls/abstract.h> +#include <gnutls/compat.h> +#include <str_array.h> +#include "abstract_int.h" + +#define MAX_OCSP_RESPONSES 8 + +/* We use the structure below to hold a certificate chain + * with corresponding public/private key pair. This structure will + * also be used when raw public keys are used. The cert_list will + * then not hold the cert chain but only a raw public-key. In that case + * the list length is always 1. + */ +typedef struct { + gnutls_pcert_st *cert_list; /* a certificate chain */ + unsigned int cert_list_length; /* its length */ + gnutls_str_array_t names; /* the names in the first certificate */ + + gnutls_status_request_ocsp_func ocsp_func; + void *ocsp_func_ptr; /* corresponding OCSP response function + ptr */ + + gnutls_ocsp_data_st ocsp_data[MAX_OCSP_RESPONSES]; + unsigned int ocsp_data_length; + + /* the private key corresponding to certificate */ + gnutls_privkey_t pkey; +} certs_st; + +/* This structure may be complex, but it's the only way to + * support a server that has multiple certificates + */ +typedef struct gnutls_certificate_credentials_st { + gnutls_dh_params_t dh_params; + unsigned deinit_dh_params; /* if the internal values are set */ + gnutls_sec_param_t dh_sec_param; /* used in RFC7919 negotiation */ + + /* this callback is used to retrieve the DH or RSA + * parameters. + */ + gnutls_params_function *params_func; + + certs_st *certs; + unsigned ncerts; /* the number of certs */ + + /* contains sorted index values for certs. Sorted in a way + * that RSA-PSS keys always take precedence over plain RSA keys + * to ensure that we use only RSA-PSS keys if present for RSA-PSS + * operations. We keep indexes to certs structures above. + */ + unsigned int *sorted_cert_idx; + + /* X509 specific stuff */ + gnutls_x509_trust_list_t tlist; + unsigned flags; /* gnutls_certificate_flags */ + unsigned int verify_flags; /* flags to be used at + * certificate verification. + */ + unsigned int verify_depth; + unsigned int verify_bits; + + /* It's a mess here. However we need to keep the old 3 functions + * for compatibility */ + gnutls_certificate_retrieve_function *legacy_cert_cb1; /* deprecated */ + gnutls_certificate_retrieve_function2 *legacy_cert_cb2; + gnutls_certificate_retrieve_function3 *get_cert_callback3; + + gnutls_certificate_verify_function *verify_callback; + + struct pin_info_st pin; + /* temporarily hold the PIN if set_key_file2() is used with a PIN */ + char pin_tmp[GNUTLS_PKCS11_MAX_PIN_LEN]; + + /* OCSP */ + gnutls_status_request_ocsp_func glob_ocsp_func; + void *glob_ocsp_func_ptr; /* corresponding OCSP response function */ + + /* This is only used by server to indicate whether this + * credentials can be used for signing in TLS 1.3. */ + bool tls13_ok; +} certificate_credentials_st; + +/* This is the information we keep for the peer + * certificate. + */ +typedef struct cert_auth_info_st { + /* These (dh/rsa) are just copies from the credentials_t structure. + * They must be freed. + */ + dh_info_st dh; + + /* we store the peer's OCSP responses received during + * this session. */ + gnutls_datum_t *raw_ocsp_list; + unsigned int nocsp; + + /* we store the peer's certificates received during + * this ession */ + gnutls_datum_t *raw_certificate_list; + unsigned int ncerts; + + gnutls_certificate_type_t cert_type; +} *cert_auth_info_t; + +typedef struct cert_auth_info_st cert_auth_info_st; + +/* AUTH X509 functions */ +int _gnutls_gen_cert_server_crt(gnutls_session_t, gnutls_buffer_st *); +int _gnutls_gen_cert_client_crt(gnutls_session_t, gnutls_buffer_st *); +int _gnutls_gen_cert_client_crt_vrfy(gnutls_session_t, gnutls_buffer_st *); +int _gnutls_gen_cert_server_cert_req(gnutls_session_t, gnutls_buffer_st *); +int _gnutls_proc_cert_cert_req(gnutls_session_t, uint8_t *, size_t); +int _gnutls_proc_cert_client_crt_vrfy(gnutls_session_t, uint8_t *, size_t); +int _gnutls_proc_crt(gnutls_session_t, uint8_t *, size_t); +int _gnutls_get_selected_cert(gnutls_session_t session, + gnutls_pcert_st ** apr_cert_list, + int *apr_cert_list_length, + gnutls_privkey_t * apr_pkey); + +int +_gnutls_select_client_cert(gnutls_session_t session, + const uint8_t * _data, size_t _data_size, + gnutls_pk_algorithm_t * pk_algos, int pk_algos_length); + +int _gnutls_pcert_to_auth_info(cert_auth_info_t info, gnutls_pcert_st * certs, size_t ncerts); + +int +_gnutls_select_server_cert(gnutls_session_t session, const gnutls_cipher_suite_entry_st *cs); +void _gnutls_selected_certs_deinit(gnutls_session_t session); + +int _gnutls_get_auth_info_pcert(gnutls_pcert_st * gcert, + gnutls_certificate_type_t type, + cert_auth_info_t info); + +int _gnutls_selected_cert_supported_kx(struct gnutls_session_int *session, + gnutls_kx_algorithm_t * alg, + int *alg_size); + +int _gnutls_check_key_cert_match(gnutls_certificate_credentials_t res); + +int _gnutls_gen_dhe_signature(gnutls_session_t session, + gnutls_buffer_st * data, uint8_t * plain, + unsigned plain_size); +int _gnutls_proc_dhe_signature(gnutls_session_t session, uint8_t * data, + size_t _data_size, + gnutls_datum_t * vparams); + +int _gnutls_gen_rawpk_crt(gnutls_session_t session, gnutls_buffer_st* data); +int _gnutls_proc_rawpk_crt(gnutls_session_t session, + uint8_t * data, size_t data_size); + +inline static unsigned get_key_usage(gnutls_session_t session, gnutls_pubkey_t pubkey) +{ + if (unlikely(session->internals.priorities && + session->internals.priorities->allow_server_key_usage_violation)) + return 0; + else + return pubkey->key_usage; +} + +#endif /* GNUTLS_LIB_AUTH_CERT_H */ diff --git a/lib/auth/dh_common.c b/lib/auth/dh_common.c new file mode 100644 index 0000000..fcd696d --- /dev/null +++ b/lib/auth/dh_common.c @@ -0,0 +1,379 @@ +/* + * 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/> + * + */ + +/* This file contains common stuff in Ephemeral Diffie-Hellman (DHE) + * and Anonymous DH key exchange(DHA). These are used in the handshake + * procedure of the certificate and anonymous authentication. + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include "num.h" +#include "tls-sig.h" +#include <datum.h> +#include <x509.h> +#include <state.h> +#include <pk.h> +#include <auth/dh_common.h> +#include <algorithms.h> +#include <auth/psk.h> + +#if defined(ENABLE_DHE) || defined(ENABLE_ANON) + +/* Frees the dh_info_st structure. + */ +void _gnutls_free_dh_info(dh_info_st * dh) +{ + dh->secret_bits = 0; + _gnutls_free_datum(&dh->prime); + _gnutls_free_datum(&dh->generator); + _gnutls_free_datum(&dh->public_key); +} + +int +_gnutls_proc_dh_common_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size, + gnutls_datum_t * psk_key) +{ + uint16_t n_Y; + size_t _n_Y; + int ret; + ssize_t data_size = _data_size; + gnutls_datum_t tmp_dh_key = {NULL, 0}; + gnutls_pk_params_st peer_pub; + + gnutls_pk_params_init(&peer_pub); + + DECR_LEN(data_size, 2); + n_Y = _gnutls_read_uint16(&data[0]); + _n_Y = n_Y; + + DECR_LEN(data_size, n_Y); + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.client_Y, &data[2], _n_Y)) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* most likely zero or illegal size */ + } + + _gnutls_dh_set_peer_public(session, session->key.proto.tls12.dh.client_Y); + + peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y; + + /* calculate the key after calculating the message */ + ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.proto.tls12.dh.params, &peer_pub); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + if (psk_key == NULL) { + session->key.key.data = tmp_dh_key.data; + session->key.key.size = tmp_dh_key.size; + } else { /* In DHE_PSK the key is set differently */ + ret = + _gnutls_set_psk_session_key(session, psk_key, + &tmp_dh_key); + _gnutls_free_temp_key_datum(&tmp_dh_key); + } + + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = 0; + error: + _gnutls_mpi_release(&session->key.proto.tls12.dh.client_Y); + gnutls_pk_params_clear(&session->key.proto.tls12.dh.params); + + return ret; +} + +int _gnutls_gen_dh_common_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + return _gnutls_gen_dh_common_client_kx_int(session, data, NULL); +} + +int +_gnutls_gen_dh_common_client_kx_int(gnutls_session_t session, + gnutls_buffer_st * data, + gnutls_datum_t * pskkey) +{ + int ret; + gnutls_pk_params_st peer_pub; + gnutls_datum_t tmp_dh_key = {NULL, 0}; + unsigned init_pos = data->length; + + gnutls_pk_params_init(&peer_pub); + + ret = + _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, + &session->key.proto.tls12.dh.params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_X])); + + ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_Y], 0); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y; + + /* calculate the key after calculating the message */ + ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.proto.tls12.dh.params, &peer_pub); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + if (session->security_parameters.cs->kx_algorithm != GNUTLS_KX_DHE_PSK) { + session->key.key.data = tmp_dh_key.data; + session->key.key.size = tmp_dh_key.size; + } else { /* In DHE_PSK the key is set differently */ + ret = + _gnutls_set_psk_session_key(session, pskkey, + &tmp_dh_key); + _gnutls_free_temp_key_datum(&tmp_dh_key); + } + + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = data->length - init_pos; + + error: + gnutls_pk_params_clear(&session->key.proto.tls12.dh.params); + return ret; +} + +/* Returns the bytes parsed */ +int +_gnutls_proc_dh_common_server_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size) +{ + uint16_t n_Y, n_g, n_p; + size_t _n_Y, _n_g, _n_p, _n_q; + uint8_t *data_p; + uint8_t *data_g; + uint8_t *data_Y; + uint8_t *data_q = NULL; + int i, bits, ret, p_bits; + unsigned j; + ssize_t data_size = _data_size; + + /* just in case we are resuming a session */ + gnutls_pk_params_release(&session->key.proto.tls12.dh.params); + + gnutls_pk_params_init(&session->key.proto.tls12.dh.params); + + i = 0; + + DECR_LEN(data_size, 2); + n_p = _gnutls_read_uint16(&data[i]); + i += 2; + + DECR_LEN(data_size, n_p); + data_p = &data[i]; + i += n_p; + + DECR_LEN(data_size, 2); + n_g = _gnutls_read_uint16(&data[i]); + i += 2; + + DECR_LEN(data_size, n_g); + data_g = &data[i]; + i += n_g; + + DECR_LEN(data_size, 2); + n_Y = _gnutls_read_uint16(&data[i]); + i += 2; + + DECR_LEN(data_size, n_Y); + data_Y = &data[i]; + + _n_Y = n_Y; + _n_g = n_g; + _n_p = n_p; + + if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.client_Y, data_Y, _n_Y) != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + /* if we are doing RFC7919 */ + if (session->internals.priorities->groups.have_ffdhe != 0) { + /* verify whether the received parameters match the advertised, otherwise + * log that. */ + for (j=0;j<session->internals.priorities->groups.size;j++) { + if (session->internals.priorities->groups.entry[j]->generator && + session->internals.priorities->groups.entry[j]->generator->size == n_g && + session->internals.priorities->groups.entry[j]->prime->size == n_p && + memcmp(session->internals.priorities->groups.entry[j]->generator->data, + data_g, n_g) == 0 && + memcmp(session->internals.priorities->groups.entry[j]->prime->data, + data_p, n_p) == 0) { + + session->internals.hsk_flags |= HSK_USED_FFDHE; + _gnutls_session_group_set(session, session->internals.priorities->groups.entry[j]); + session->key.proto.tls12.dh.params.qbits = *session->internals.priorities->groups.entry[j]->q_bits; + data_q = session->internals.priorities->groups.entry[j]->q->data; + _n_q = session->internals.priorities->groups.entry[j]->q->size; + break; + } + } + + if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) { + _gnutls_audit_log(session, "FFDHE groups advertised, but server didn't support it; falling back to server's choice\n"); + } + } + +#ifdef ENABLE_FIPS140 + if (gnutls_fips140_mode_enabled() && + !_gnutls_dh_prime_match_fips_approved(data_p, n_p, data_g, n_g, NULL, NULL)) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } +#endif + + if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_G], data_g, _n_g) != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_P], data_p, _n_p) != 0) { + gnutls_assert(); + /* we release now because session->key.proto.tls12.dh.params.params_nr is not yet set */ + _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + if (data_q && _gnutls_mpi_init_scan_nz( + &session->key.proto.tls12.dh.params.params[DH_Q], + data_q, _n_q) != 0) { + /* we release now because params_nr is not yet set */ + _gnutls_mpi_release( + &session->key.proto.tls12.dh.params.params[DH_P]); + _gnutls_mpi_release( + &session->key.proto.tls12.dh.params.params[DH_G]); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + /* include, possibly empty, q */ + session->key.proto.tls12.dh.params.params_nr = 3; + session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH; + + if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) { + bits = _gnutls_dh_get_min_prime_bits(session); + if (bits < 0) { + gnutls_assert(); + return bits; + } + + p_bits = _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_P]); + if (p_bits < bits) { + /* the prime used by the peer is not acceptable + */ + gnutls_assert(); + _gnutls_debug_log + ("Received a prime of %u bits, limit is %u\n", + (unsigned) _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_P]), + (unsigned) bits); + return GNUTLS_E_DH_PRIME_UNACCEPTABLE; + } + + if (p_bits >= DEFAULT_MAX_VERIFY_BITS) { + gnutls_assert(); + _gnutls_debug_log + ("Received a prime of %u bits, limit is %u\n", + (unsigned) p_bits, + (unsigned) DEFAULT_MAX_VERIFY_BITS); + return GNUTLS_E_DH_PRIME_UNACCEPTABLE; + } + } + + _gnutls_dh_save_group(session, session->key.proto.tls12.dh.params.params[DH_G], + session->key.proto.tls12.dh.params.params[DH_P]); + _gnutls_dh_set_peer_public(session, session->key.proto.tls12.dh.client_Y); + + ret = n_Y + n_p + n_g + 6; + + return ret; +} + +int +_gnutls_dh_common_print_server_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret; + unsigned q_bits = session->key.proto.tls12.dh.params.qbits; + unsigned init_pos = data->length; + + if (q_bits < 192 && q_bits != 0) { + gnutls_assert(); + _gnutls_debug_log("too small q_bits value for DH: %u\n", q_bits); + q_bits = 0; /* auto-detect */ + } + + /* Y=g^x mod p */ + ret = + _gnutls_pk_generate_keys(GNUTLS_PK_DH, q_bits, + &session->key.proto.tls12.dh.params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_X])); + + ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_P], 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_G], 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_Y], 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + +cleanup: + return ret; +} + +#endif diff --git a/lib/auth/dh_common.h b/lib/auth/dh_common.h new file mode 100644 index 0000000..7584f89 --- /dev/null +++ b/lib/auth/dh_common.h @@ -0,0 +1,50 @@ +/* + * 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_AUTH_DH_COMMON_H +#define GNUTLS_LIB_AUTH_DH_COMMON_H + +#include <auth.h> + +typedef struct { + int secret_bits; + + gnutls_datum_t prime; + gnutls_datum_t generator; + gnutls_datum_t public_key; +} dh_info_st; + +void _gnutls_free_dh_info(dh_info_st * dh); + +int _gnutls_gen_dh_common_client_kx_int(gnutls_session_t, + gnutls_buffer_st *, + gnutls_datum_t * pskkey); +int _gnutls_gen_dh_common_client_kx(gnutls_session_t, gnutls_buffer_st *); +int _gnutls_proc_dh_common_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size, + gnutls_datum_t * psk_key); +int _gnutls_dh_common_print_server_kx(gnutls_session_t, + gnutls_buffer_st * data); +int _gnutls_proc_dh_common_server_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size); + +#endif /* GNUTLS_LIB_AUTH_DH_COMMON_H */ diff --git a/lib/auth/dhe.c b/lib/auth/dhe.c new file mode 100644 index 0000000..1d16cde --- /dev/null +++ b/lib/auth/dhe.c @@ -0,0 +1,152 @@ +/* + * 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/> + * + */ + +/* This file contains everything for the Ephemeral Diffie-Hellman + * (DHE) key exchange. This is used in the handshake procedure of the + * certificate authentication. + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include "num.h" +#include "tls-sig.h" +#include <datum.h> +#include <algorithms.h> +#include <auth/cert.h> +#include <x509.h> +#include <state.h> +#include <auth/dh_common.h> +#include <auth/ecdhe.h> + +static int gen_dhe_server_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_dhe_server_kx(gnutls_session_t, uint8_t *, size_t); +static int proc_dhe_client_kx(gnutls_session_t, uint8_t *, size_t); + +#ifdef ENABLE_DHE + +const mod_auth_st dhe_rsa_auth_struct = { + "DHE_RSA", + _gnutls_gen_cert_server_crt, + _gnutls_gen_cert_client_crt, + gen_dhe_server_kx, + _gnutls_gen_dh_common_client_kx, + _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */ + _gnutls_gen_cert_server_cert_req, /* server cert request */ + + _gnutls_proc_crt, + _gnutls_proc_crt, + proc_dhe_server_kx, + proc_dhe_client_kx, + _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */ + _gnutls_proc_cert_cert_req /* proc server cert request */ +}; + +const mod_auth_st dhe_dss_auth_struct = { + "DHE_DSS", + _gnutls_gen_cert_server_crt, + _gnutls_gen_cert_client_crt, + gen_dhe_server_kx, + _gnutls_gen_dh_common_client_kx, + _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */ + _gnutls_gen_cert_server_cert_req, /* server cert request */ + + _gnutls_proc_crt, + _gnutls_proc_crt, + proc_dhe_server_kx, + proc_dhe_client_kx, + _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */ + _gnutls_proc_cert_cert_req /* proc server cert request */ +}; + +#endif + +static int +gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret = 0; + gnutls_certificate_credentials_t cred; + unsigned sig_pos; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, + sizeof(cert_auth_info_st), + 1)) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_figure_dh_params(session, cred->dh_params, cred->params_func, cred->dh_sec_param); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + sig_pos = data->length; + + ret = + _gnutls_dh_common_print_server_kx(session, data); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Generate the signature. */ + return _gnutls_gen_dhe_signature(session, data, &data->data[sig_pos], + data->length-sig_pos); +} + + +static int +proc_dhe_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + gnutls_datum_t vdata; + int ret; + + ret = _gnutls_proc_dh_common_server_kx(session, data, _data_size); + if (ret < 0) + return gnutls_assert_val(ret); + + vdata.data = data; + vdata.size = ret; + + return _gnutls_proc_dhe_signature(session, data + ret, + _data_size - ret, &vdata); +} + + +static int +proc_dhe_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + return _gnutls_proc_dh_common_client_kx(session, data, _data_size, + NULL); +} diff --git a/lib/auth/dhe_psk.c b/lib/auth/dhe_psk.c new file mode 100644 index 0000000..81e0e1a --- /dev/null +++ b/lib/auth/dhe_psk.c @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2005-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 PSK Diffie-Hellman key exchange part of the + * PSK authentication. The functions here are used in the handshake. + */ + +#include "gnutls_int.h" + +#ifdef ENABLE_PSK + +/* Contains PSK code for DHE and ECDHE + */ + +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include <auth/psk.h> +#include "num.h" +#include "mpi.h" +#include <state.h> +#include <auth/dh_common.h> +#include <auth/ecdhe.h> +#include <datum.h> +#include <auth/psk_passwd.h> + +static int +proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size); +static int gen_dhe_psk_server_kx(gnutls_session_t, gnutls_buffer_st *); +static int gen_dhe_psk_client_kx(gnutls_session_t, gnutls_buffer_st *); +static int gen_ecdhe_psk_client_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_ecdhe_psk_client_kx(gnutls_session_t, uint8_t *, size_t); +static int proc_dhe_psk_server_kx(gnutls_session_t, uint8_t *, size_t); +static int gen_ecdhe_psk_server_kx(gnutls_session_t session, + gnutls_buffer_st * data); +static int proc_dhe_psk_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size); +#ifdef ENABLE_DHE +const mod_auth_st dhe_psk_auth_struct = { + "DHE PSK", + NULL, + NULL, + gen_dhe_psk_server_kx, + gen_dhe_psk_client_kx, + NULL, + NULL, + + NULL, + NULL, /* certificate */ + proc_dhe_psk_server_kx, + proc_dhe_psk_client_kx, + NULL, + NULL +}; +#endif + +#ifdef ENABLE_ECDHE +const mod_auth_st ecdhe_psk_auth_struct = { + "ECDHE PSK", + NULL, + NULL, + gen_ecdhe_psk_server_kx, + gen_ecdhe_psk_client_kx, + NULL, + NULL, + + NULL, + NULL, /* certificate */ + proc_ecdhe_psk_server_kx, + proc_ecdhe_psk_client_kx, + NULL, + NULL +}; +#endif + +static int +gen_ecdhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret, free; + gnutls_psk_client_credentials_t cred; + gnutls_datum_t username, key; + unsigned init_pos = data->length; + + cred = (gnutls_psk_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) + return + gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + ret = _gnutls_find_psk_key(session, cred, &username, &key, &free); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data_prefix(data, 16, username.data, + username.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* The PSK key is set in there */ + ret = _gnutls_gen_ecdh_common_client_kx_int(session, data, &key); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + + cleanup: + if (free) { + _gnutls_free_datum(&username); + _gnutls_free_temp_key_datum(&key); + } + + return ret; +} + +static int +gen_dhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret, free; + gnutls_psk_client_credentials_t cred; + gnutls_datum_t username, key; + unsigned init_pos = data->length; + + cred = (gnutls_psk_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) + return + gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + ret = _gnutls_find_psk_key(session, cred, &username, &key, &free); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data_prefix(data, 16, username.data, + username.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* The PSK key is set in there */ + ret = _gnutls_gen_dh_common_client_kx_int(session, data, &key); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + + cleanup: + if (free) { + _gnutls_free_datum(&username); + _gnutls_free_temp_key_datum(&key); + } + + return ret; +} + +static int +gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret; + gnutls_psk_server_credentials_t cred; + gnutls_datum_t hint = {NULL, 0}; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_figure_dh_params(session, cred->dh_params, cred->params_func, cred->dh_sec_param); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (cred->hint) { + hint.data = (uint8_t *) cred->hint; + hint.size = strlen(cred->hint); + } + + ret = _gnutls_buffer_append_data_prefix(data, 16, hint.data, hint.size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_dh_common_print_server_kx(session, data); + if (ret < 0) + gnutls_assert(); + + return ret; +} + +static int +gen_ecdhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret; + gnutls_psk_server_credentials_t cred; + gnutls_datum_t hint = {NULL, 0}; + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if (cred->hint) { + hint.data = (uint8_t *) cred->hint; + hint.size = strlen(cred->hint); + } + + ret = _gnutls_buffer_append_data_prefix(data, 16, hint.data, hint.size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_ecdh_common_print_server_kx(session, data, + get_group + (session)); + if (ret < 0) + gnutls_assert(); + + return ret; +} + + +static int +proc_dhe_psk_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + int ret; + gnutls_datum_t psk_key; + gnutls_psk_server_credentials_t cred; + psk_auth_info_t info; + gnutls_datum_t username; + ssize_t data_size = _data_size; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + DECR_LEN(data_size, 2); + username.size = _gnutls_read_uint16(&data[0]); + + DECR_LEN(data_size, username.size); + + username.data = &data[2]; + + /* copy the username to the auth info structures + */ + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (username.size > MAX_USERNAME_SIZE) { + gnutls_assert(); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; + } + + ret = _gnutls_copy_psk_username(info, username); + if (ret < 0) + return gnutls_assert_val(ret); + + /* Adjust the data */ + data += username.size + 2; + + ret = + _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_proc_dh_common_client_kx(session, data, data_size, + &psk_key); + + _gnutls_free_key_datum(&psk_key); + + return ret; + +} + +static int +proc_ecdhe_psk_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + int ret; + gnutls_psk_server_credentials_t cred; + gnutls_datum_t psk_key; + psk_auth_info_t info; + gnutls_datum_t username; + ssize_t data_size = _data_size; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + DECR_LEN(data_size, 2); + username.size = _gnutls_read_uint16(&data[0]); + + DECR_LEN(data_size, username.size); + + username.data = &data[2]; + + /* copy the username to the auth info structures + */ + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + + if (username.size > MAX_USERNAME_SIZE) { + gnutls_assert(); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; + } + + ret = _gnutls_copy_psk_username(info, username); + if (ret < 0) + return gnutls_assert_val(ret); + + /* Adjust the data */ + data += username.size + 2; + + /* should never fail. It will always return a key even if it is + * a random one */ + ret = + _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_proc_ecdh_common_client_kx(session, data, data_size, + get_group + (session), &psk_key); + + _gnutls_free_key_datum(&psk_key); + + return ret; +} + +static int +proc_dhe_psk_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + + int ret; + ssize_t data_size = _data_size; + psk_auth_info_t info; + gnutls_datum_t hint; + + /* set auth_info */ + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + DECR_LEN(data_size, 2); + + hint.size = _gnutls_read_uint16(&data[0]); + hint.data = &data[2]; + + DECR_LEN(data_size, hint.size); + data += 2 + hint.size; + + ret = _gnutls_proc_dh_common_server_kx(session, data, data_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + if (hint.size > MAX_USERNAME_SIZE) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME); + + ret = _gnutls_copy_psk_hint(info, hint); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +static int +proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + + int ret; + ssize_t data_size = _data_size; + psk_auth_info_t info; + gnutls_datum_t hint; + + /* set auth_info */ + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + DECR_LEN(data_size, 2); + + hint.size = _gnutls_read_uint16(&data[0]); + hint.data = &data[2]; + + DECR_LEN(data_size, hint.size); + data += 2 + hint.size; + + ret = _gnutls_proc_ecdh_common_server_kx(session, data, data_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + if (hint.size > MAX_USERNAME_SIZE) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME); + + ret = _gnutls_copy_psk_hint(info, hint); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +#endif /* ENABLE_PSK */ diff --git a/lib/auth/ecdhe.c b/lib/auth/ecdhe.c new file mode 100644 index 0000000..9f53b1b --- /dev/null +++ b/lib/auth/ecdhe.c @@ -0,0 +1,522 @@ +/* + * 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 common stuff in Ephemeral Diffie-Hellman (DHE) + * and Anonymous DH key exchange(DHA). These are used in the handshake + * procedure of the certificate and anonymous authentication. + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include "num.h" +#include "tls-sig.h" +#include <state.h> +#include <datum.h> +#include <x509.h> +#include <auth/ecdhe.h> +#include <ecc.h> +#include <ext/supported_groups.h> +#include <algorithms.h> +#include <auth/psk.h> +#include <auth/cert.h> +#include <pk.h> + +static int gen_ecdhe_server_kx(gnutls_session_t, gnutls_buffer_st *); +static int +proc_ecdhe_server_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size); +static int +proc_ecdhe_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size); + +#if defined(ENABLE_ECDHE) +const mod_auth_st ecdhe_ecdsa_auth_struct = { + "ECDHE_ECDSA", + _gnutls_gen_cert_server_crt, + _gnutls_gen_cert_client_crt, + gen_ecdhe_server_kx, + _gnutls_gen_ecdh_common_client_kx, /* This is the only difference */ + _gnutls_gen_cert_client_crt_vrfy, + _gnutls_gen_cert_server_cert_req, + + _gnutls_proc_crt, + _gnutls_proc_crt, + proc_ecdhe_server_kx, + proc_ecdhe_client_kx, + _gnutls_proc_cert_client_crt_vrfy, + _gnutls_proc_cert_cert_req +}; + +const mod_auth_st ecdhe_rsa_auth_struct = { + "ECDHE_RSA", + _gnutls_gen_cert_server_crt, + _gnutls_gen_cert_client_crt, + gen_ecdhe_server_kx, + _gnutls_gen_ecdh_common_client_kx, /* This is the only difference */ + _gnutls_gen_cert_client_crt_vrfy, + _gnutls_gen_cert_server_cert_req, + + _gnutls_proc_crt, + _gnutls_proc_crt, + proc_ecdhe_server_kx, + proc_ecdhe_client_kx, + _gnutls_proc_cert_client_crt_vrfy, + _gnutls_proc_cert_cert_req +}; + +static int calc_ecdh_key(gnutls_session_t session, + gnutls_datum_t * psk_key, + const gnutls_ecc_curve_entry_st *ecurve) +{ + gnutls_pk_params_st pub; + int ret; + gnutls_datum_t tmp_dh_key; + + gnutls_pk_params_init(&pub); + pub.params[ECC_X] = session->key.proto.tls12.ecdh.x; + pub.params[ECC_Y] = session->key.proto.tls12.ecdh.y; + pub.raw_pub.data = session->key.proto.tls12.ecdh.raw.data; + pub.raw_pub.size = session->key.proto.tls12.ecdh.raw.size; + pub.curve = ecurve->id; + + ret = + _gnutls_pk_derive(ecurve->pk, &tmp_dh_key, + &session->key.proto.tls12.ecdh.params, &pub); + if (ret < 0) { + ret = gnutls_assert_val(ret); + goto cleanup; + } + + if (psk_key == NULL) { + memcpy(&session->key.key, &tmp_dh_key, sizeof(gnutls_datum_t)); + tmp_dh_key.data = NULL; /* no longer needed */ + } else { + ret = + _gnutls_set_psk_session_key(session, psk_key, + &tmp_dh_key); + _gnutls_free_temp_key_datum(&tmp_dh_key); + + if (ret < 0) { + ret = gnutls_assert_val(ret); + goto cleanup; + } + } + + ret = 0; + + cleanup: + /* no longer needed */ + _gnutls_mpi_release(&session->key.proto.tls12.ecdh.x); + _gnutls_mpi_release(&session->key.proto.tls12.ecdh.y); + _gnutls_free_datum(&session->key.proto.tls12.ecdh.raw); + gnutls_pk_params_release(&session->key.proto.tls12.ecdh.params); + return ret; +} + +int _gnutls_proc_ecdh_common_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size, + const struct gnutls_group_entry_st *group, + gnutls_datum_t * psk_key) +{ + ssize_t data_size = _data_size; + int ret, i = 0; + unsigned point_size; + const gnutls_ecc_curve_entry_st *ecurve; + + if (group == NULL) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + + ecurve = _gnutls_ecc_curve_get_params(group->curve); + if (ecurve == NULL) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + + DECR_LEN(data_size, 1); + point_size = data[i]; + i += 1; + + if (point_size == 0) { + ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + goto cleanup; + } + + DECR_LEN(data_size, point_size); + + if (ecurve->pk == GNUTLS_PK_EC) { + ret = + _gnutls_ecc_ansi_x962_import(&data[i], point_size, + &session->key.proto.tls12.ecdh.x, + &session->key.proto.tls12.ecdh.y); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } else if (ecurve->pk == GNUTLS_PK_ECDH_X25519 || + ecurve->pk == GNUTLS_PK_ECDH_X448) { + if (ecurve->size != point_size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_set_datum(&session->key.proto.tls12.ecdh.raw, + &data[i], point_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* RFC7748 requires to mask the MSB in the final byte + * for X25519 (not X448) */ + if (ecurve->id == GNUTLS_ECC_CURVE_X25519) { + session->key.proto.tls12.ecdh.raw.data[point_size-1] &= 0x7f; + } + } else { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* generate pre-shared key */ + ret = calc_ecdh_key(session, psk_key, ecurve); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + cleanup: + gnutls_pk_params_clear(&session->key.proto.tls12.ecdh.params); + return ret; +} + +static int +proc_ecdhe_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size) +{ + gnutls_certificate_credentials_t cred; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + return _gnutls_proc_ecdh_common_client_kx(session, data, + _data_size, + get_group + (session), NULL); +} + +int +_gnutls_gen_ecdh_common_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + return _gnutls_gen_ecdh_common_client_kx_int(session, data, NULL); +} + +int +_gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session, + gnutls_buffer_st * data, + gnutls_datum_t * psk_key) +{ + int ret; + gnutls_datum_t out; + const gnutls_group_entry_st *group = get_group(session); + const gnutls_ecc_curve_entry_st *ecurve; + int pk; + unsigned init_pos = data->length; + + if (group == NULL) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + + ecurve = _gnutls_ecc_curve_get_params(group->curve); + if (ecurve == NULL) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + + pk = ecurve->pk; + + /* generate temporal key */ + ret = + _gnutls_pk_generate_keys(pk, ecurve->id, + &session->key.proto.tls12.ecdh.params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + if (pk == GNUTLS_PK_EC) { + ret = + _gnutls_ecc_ansi_x962_export(ecurve->id, + session->key.proto.tls12.ecdh.params. + params[ECC_X] /* x */ , + session->key.proto.tls12.ecdh.params. + params[ECC_Y] /* y */ , &out); + + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = + _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size); + + _gnutls_free_datum(&out); + + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } else if (pk == GNUTLS_PK_ECDH_X25519 || pk == GNUTLS_PK_ECDH_X448) { + ret = + _gnutls_buffer_append_data_prefix(data, 8, + session->key.proto.tls12.ecdh.params.raw_pub.data, + session->key.proto.tls12.ecdh.params.raw_pub.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + /* generate pre-shared key */ + ret = calc_ecdh_key(session, psk_key, ecurve); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + cleanup: + gnutls_pk_params_clear(&session->key.proto.tls12.ecdh.params); + return ret; +} + +static int +proc_ecdhe_server_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size) +{ + int ret; + gnutls_datum_t vparams; + + ret = + _gnutls_proc_ecdh_common_server_kx(session, data, _data_size); + if (ret < 0) + return gnutls_assert_val(ret); + + vparams.data = data; + vparams.size = ret; + + return _gnutls_proc_dhe_signature(session, data + ret, + _data_size - ret, &vparams); +} + +int +_gnutls_proc_ecdh_common_server_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size) +{ + int i, ret; + unsigned point_size; + const gnutls_group_entry_st *group; + ssize_t data_size = _data_size; + const gnutls_ecc_curve_entry_st *ecurve; + + /* just in case we are resuming a session */ + gnutls_pk_params_release(&session->key.proto.tls12.ecdh.params); + + gnutls_pk_params_init(&session->key.proto.tls12.ecdh.params); + + i = 0; + DECR_LEN(data_size, 1); + if (data[i++] != 3) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + + DECR_LEN(data_size, 2); + + group = _gnutls_tls_id_to_group(_gnutls_read_uint16(&data[i])); + if (group == NULL || group->curve == 0) { + _gnutls_debug_log("received unknown curve %u.%u\n", (unsigned)data[i], (unsigned)data[i+1]); + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } else { + _gnutls_debug_log("received curve %s\n", group->name); + } + + i += 2; + + ret = _gnutls_session_supports_group(session, group->id); + if (ret < 0) + return gnutls_assert_val(ret); + + ecurve = _gnutls_ecc_curve_get_params(group->curve); + if (ecurve == NULL) { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + _gnutls_session_group_set(session, group); + + DECR_LEN(data_size, 1); + point_size = data[i]; + i++; + + DECR_LEN(data_size, point_size); + + if (ecurve->pk == GNUTLS_PK_EC) { + ret = + _gnutls_ecc_ansi_x962_import(&data[i], point_size, + &session->key.proto.tls12.ecdh.x, + &session->key.proto.tls12.ecdh.y); + if (ret < 0) + return gnutls_assert_val(ret); + + } else if (ecurve->pk == GNUTLS_PK_ECDH_X25519 || + ecurve->pk == GNUTLS_PK_ECDH_X448) { + if (ecurve->size != point_size) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + ret = _gnutls_set_datum(&session->key.proto.tls12.ecdh.raw, + &data[i], point_size); + if (ret < 0) + return gnutls_assert_val(ret); + + /* RFC7748 requires to mask the MSB in the final byte + * for X25519 (not X448) */ + if (ecurve->id == GNUTLS_ECC_CURVE_X25519) { + session->key.proto.tls12.ecdh.raw.data[point_size-1] &= 0x7f; + } + } else { + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + i += point_size; + + return i; +} + +/* If the psk flag is set, then an empty psk_identity_hint will + * be inserted */ +int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session, + gnutls_buffer_st * data, + const gnutls_group_entry_st *group) +{ + uint8_t p; + int ret; + gnutls_datum_t out; + unsigned init_pos = data->length; + + if (group == NULL || group->curve == 0) + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + + /* just in case we are resuming a session */ + gnutls_pk_params_release(&session->key.proto.tls12.ecdh.params); + + gnutls_pk_params_init(&session->key.proto.tls12.ecdh.params); + + /* curve type */ + p = 3; + + ret = _gnutls_buffer_append_data(data, &p, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_prefix(data, 16, + group->tls_id); + if (ret < 0) + return gnutls_assert_val(ret); + + + /* generate temporal key */ + ret = + _gnutls_pk_generate_keys(group->pk, group->curve, + &session->key.proto.tls12.ecdh.params, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + if (group->pk == GNUTLS_PK_EC) { + ret = + _gnutls_ecc_ansi_x962_export(group->curve, + session->key.proto.tls12.ecdh.params. + params[ECC_X] /* x */ , + session->key.proto.tls12.ecdh.params. + params[ECC_Y] /* y */ , &out); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size); + + _gnutls_free_datum(&out); + + if (ret < 0) + return gnutls_assert_val(ret); + + } else if (group->pk == GNUTLS_PK_ECDH_X25519 || + group->pk == GNUTLS_PK_ECDH_X448) { + ret = + _gnutls_buffer_append_data_prefix(data, 8, + session->key.proto.tls12.ecdh.params.raw_pub.data, + session->key.proto.tls12.ecdh.params.raw_pub.size); + if (ret < 0) + return gnutls_assert_val(ret); + } else { + return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); + } + + + return data->length - init_pos; +} + +static int +gen_ecdhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + int ret = 0; + gnutls_certificate_credentials_t cred; + unsigned sig_pos; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, + sizeof(cert_auth_info_st), + 1)) < 0) { + gnutls_assert(); + return ret; + } + + sig_pos = data->length; + + ret = + _gnutls_ecdh_common_print_server_kx(session, data, + get_group + (session)); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Generate the signature. */ + return _gnutls_gen_dhe_signature(session, data, &data->data[sig_pos], + data->length-sig_pos); +} + +#endif diff --git a/lib/auth/ecdhe.h b/lib/auth/ecdhe.h new file mode 100644 index 0000000..e80e1ba --- /dev/null +++ b/lib/auth/ecdhe.h @@ -0,0 +1,52 @@ +/* + * 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/> + * + */ + +#ifndef GNUTLS_LIB_AUTH_ECDHE_H +#define GNUTLS_LIB_AUTH_ECDHE_H + +#include <auth.h> + +int +_gnutls_gen_ecdh_common_client_kx(gnutls_session_t session, + gnutls_buffer_st * data); + +int +_gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session, + gnutls_buffer_st * data, + gnutls_datum_t * psk_key); + +int +_gnutls_proc_ecdh_common_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size, + const struct gnutls_group_entry_st *group, + gnutls_datum_t * psk_key); + +int _gnutls_ecdh_common_print_server_kx(gnutls_session_t, + gnutls_buffer_st * data, + const struct gnutls_group_entry_st *group); +int _gnutls_proc_ecdh_common_server_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size); + + + +#endif /* GNUTLS_LIB_AUTH_ECDHE_H */ diff --git a/lib/auth/psk.c b/lib/auth/psk.c new file mode 100644 index 0000000..cdb1f1b --- /dev/null +++ b/lib/auth/psk.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2005-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" + +#ifdef ENABLE_PSK + +#include "errors.h" +#include "auth.h" +#include "debug.h" +#include "num.h" +#include <auth/psk.h> +#include <auth/psk_passwd.h> +#include <str.h> +#include <datum.h> + + +static int _gnutls_proc_psk_client_kx(gnutls_session_t, uint8_t *, size_t); +static int +_gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size); + + +const mod_auth_st psk_auth_struct = { + "PSK", + NULL, + NULL, + _gnutls_gen_psk_server_kx, + _gnutls_gen_psk_client_kx, + NULL, + NULL, + + NULL, + NULL, /* certificate */ + _gnutls_proc_psk_server_kx, + _gnutls_proc_psk_client_kx, + NULL, + NULL +}; + +/* Set the PSK premaster secret. + */ +int +_gnutls_set_psk_session_key(gnutls_session_t session, + gnutls_datum_t * ppsk /* key */ , + gnutls_datum_t * dh_secret) +{ + gnutls_datum_t pwd_psk = { NULL, 0 }; + size_t dh_secret_size; + uint8_t *p; + int ret; + + if (dh_secret == NULL) + dh_secret_size = ppsk->size; + else + dh_secret_size = dh_secret->size; + + /* set the session key + */ + session->key.key.size = 4 + dh_secret_size + ppsk->size; + session->key.key.data = gnutls_malloc(session->key.key.size); + if (session->key.key.data == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } + + /* format of the premaster secret: + * (uint16_t) psk_size + * psk_size bytes of (0)s + * (uint16_t) psk_size + * the psk + */ + p = session->key.key.data; + _gnutls_write_uint16(dh_secret_size, p); + p += 2; + if (dh_secret == NULL) + memset(p, 0, dh_secret_size); + else + memcpy(p, dh_secret->data, dh_secret->size); + + p += dh_secret_size; + _gnutls_write_uint16(ppsk->size, p); + if (ppsk->data != NULL) + memcpy(p + 2, ppsk->data, ppsk->size); + + ret = 0; + + error: + _gnutls_free_temp_key_datum(&pwd_psk); + return ret; +} + + +/* Generates the PSK client key exchange + * + * + * struct { + * select (KeyExchangeAlgorithm) { + * uint8_t psk_identity<0..2^16-1>; + * } exchange_keys; + * } ClientKeyExchange; + * + */ +int +_gnutls_gen_psk_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret, free; + gnutls_datum_t username = {NULL, 0}; + gnutls_datum_t key; + gnutls_psk_client_credentials_t cred; + psk_auth_info_t info; + + cred = (gnutls_psk_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + ret = _gnutls_find_psk_key(session, cred, &username, &key, &free); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_set_psk_session_key(session, &key, NULL); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = + _gnutls_buffer_append_data_prefix(data, 16, username.data, + username.size); + if (ret < 0) { + gnutls_assert(); + } + + if (username.size > MAX_USERNAME_SIZE) { + gnutls_assert(); + ret = GNUTLS_E_ILLEGAL_SRP_USERNAME; + goto cleanup; + } + + assert(username.data != NULL); + ret = _gnutls_copy_psk_username(info, username); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + cleanup: + if (free) { + gnutls_free(username.data); + _gnutls_free_temp_key_datum(&key); + } + + return ret; +} + + +/* just read the username from the client key exchange. + */ +static int +_gnutls_proc_psk_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + ssize_t data_size = _data_size; + int ret; + gnutls_datum_t username, psk_key; + gnutls_psk_server_credentials_t cred; + psk_auth_info_t info; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1)) < 0) { + gnutls_assert(); + return ret; + } + + DECR_LEN(data_size, 2); + username.size = _gnutls_read_uint16(&data[0]); + + DECR_LEN(data_size, username.size); + + username.data = &data[2]; + + + /* copy the username to the auth info structures + */ + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (username.size > MAX_USERNAME_SIZE) { + gnutls_assert(); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; + } + + ret = _gnutls_copy_psk_username(info, username); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_set_psk_session_key(session, &psk_key, NULL); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = 0; + + error: + _gnutls_free_key_datum(&psk_key); + + return ret; +} + + +/* Generates the PSK server key exchange + * + * struct { + * select (KeyExchangeAlgorithm) { + * // other cases for rsa, diffie_hellman, etc. + * case psk: // NEW + * uint8_t psk_identity_hint<0..2^16-1>; + * }; + * } ServerKeyExchange; + * + */ +int +_gnutls_gen_psk_server_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + gnutls_psk_server_credentials_t cred; + gnutls_datum_t hint; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + /* Abort sending this message if there is no PSK identity hint. */ + if (cred->hint == NULL) { + gnutls_assert(); + return GNUTLS_E_INT_RET_0; + } + + hint.data = (uint8_t *) cred->hint; + hint.size = strlen(cred->hint); + + return _gnutls_buffer_append_data_prefix(data, 16, hint.data, + hint.size); +} + +/* Read the hint from the server key exchange */ +static int +_gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) +{ + int ret; + ssize_t data_size = _data_size; + gnutls_psk_client_credentials_t cred; + psk_auth_info_t info; + gnutls_datum_t hint; + + cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); + if (cred == NULL) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1); + if (ret < 0) + return gnutls_assert_val(ret); + + DECR_LENGTH_RET(data_size, 2, 0); + hint.size = _gnutls_read_uint16(&data[0]); + + DECR_LEN(data_size, hint.size); + hint.data = &data[2]; + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + if (hint.size > MAX_USERNAME_SIZE) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME); + + ret = _gnutls_copy_psk_hint(info, hint); + return ret; +} + +#endif /* ENABLE_PSK */ diff --git a/lib/auth/psk.h b/lib/auth/psk.h new file mode 100644 index 0000000..202ee05 --- /dev/null +++ b/lib/auth/psk.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-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_AUTH_PSK_H +#define GNUTLS_LIB_AUTH_PSK_H + +#include <auth.h> +#include <auth/dh_common.h> + +#define _gnutls_copy_psk_username(info, datum) \ + _gnutls_copy_psk_string(&(info)->username, &(info)->username_len, (datum)) + +#define _gnutls_copy_psk_hint(info, datum) \ + _gnutls_copy_psk_string(&(info)->hint, &(info)->hint_len, (datum)) + +typedef struct gnutls_psk_client_credentials_st { + gnutls_datum_t username; + gnutls_datum_t key; + gnutls_psk_client_credentials_function2 *get_function; + gnutls_psk_client_credentials_function *get_function_legacy; + /* TLS 1.3 - The HMAC algorithm to use to compute the binder values */ + const mac_entry_st *binder_algo; +} psk_client_credentials_st; + +typedef struct gnutls_psk_server_credentials_st { + char *password_file; + /* callback function, instead of reading the + * password files. + */ + gnutls_psk_server_credentials_function2 *pwd_callback; + gnutls_psk_server_credentials_function *pwd_callback_legacy; + + /* For DHE_PSK */ + gnutls_dh_params_t dh_params; + unsigned int deinit_dh_params; + gnutls_sec_param_t dh_sec_param; + /* this callback is used to retrieve the DH or RSA + * parameters. + */ + gnutls_params_function *params_func; + + /* Identity hint. */ + char *hint; + /* TLS 1.3 - HMAC algorithm for the binder values */ + const mac_entry_st *binder_algo; +} psk_server_cred_st; + +typedef struct psk_auth_info_st { + char *username; + uint16_t username_len; + dh_info_st dh; + char *hint; + uint16_t hint_len; +} *psk_auth_info_t; + +typedef struct psk_auth_info_st psk_auth_info_st; + +inline static int +_gnutls_copy_psk_string(char **dest, uint16_t *dest_len, const gnutls_datum_t str) +{ + char *_tmp; + + assert(MAX_USERNAME_SIZE >= str.size); + + _tmp = gnutls_malloc(str.size + 1); + if (_tmp == NULL) + return GNUTLS_E_MEMORY_ERROR; + memcpy(_tmp, str.data, str.size); + _tmp[str.size] = '\0'; + + gnutls_free(*dest); + *dest = _tmp; + *dest_len = str.size; + + return GNUTLS_E_SUCCESS; +} + +#ifdef ENABLE_PSK + +int +_gnutls_set_psk_session_key(gnutls_session_t session, gnutls_datum_t * key, + gnutls_datum_t * psk2); +int _gnutls_gen_psk_server_kx(gnutls_session_t session, + gnutls_buffer_st * data); +int _gnutls_gen_psk_client_kx(gnutls_session_t, gnutls_buffer_st *); + +#else +#define _gnutls_set_psk_session_key(x,y,z) GNUTLS_E_UNIMPLEMENTED_FEATURE +#endif /* ENABLE_PSK */ + +#endif /* GNUTLS_LIB_AUTH_PSK_H */ diff --git a/lib/auth/psk_passwd.c b/lib/auth/psk_passwd.c new file mode 100644 index 0000000..2953c2d --- /dev/null +++ b/lib/auth/psk_passwd.c @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2005-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/> + * + */ + +/* Functions for operating in an PSK passwd file are included here */ + +#include "gnutls_int.h" + +#include "x509_b64.h" +#include "errors.h" +#include <auth/psk_passwd.h> +#include <auth/psk.h> +#include "auth.h" +#include "dh.h" +#include "debug.h" +#include <str.h> +#include <datum.h> +#include <num.h> +#include <random.h> + + +/* this function parses passwd.psk file. Format is: + * string(username):hex(passwd) + */ +static int pwd_put_values(gnutls_datum_t * psk, char *str) +{ + char *p; + int len, ret; + gnutls_datum_t tmp; + + p = strchr(str, ':'); + if (p == NULL) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + *p = '\0'; + p++; + + /* skip username + */ + + /* read the key + */ + len = strlen(p); + if (p[len - 1] == '\n' || p[len - 1] == ' ') + len--; + + tmp.data = (void*)p; + tmp.size = len; + ret = gnutls_hex_decode2(&tmp, psk); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +static bool username_matches(const gnutls_datum_t *username, + const char *line, size_t line_size) +{ + int retval; + unsigned i; + gnutls_datum_t hexline, hex_username = { NULL, 0 }; + + /* + * Guard against weird behavior - we don't check 'line', + * as it's returned by getline(), which will never return NULL + * if successful. + */ + if (username->data == NULL) + return false; + + if (line_size == 0) + return (username->size == 0); + + /* move to first ':' */ + i = 0; + while ((i < line_size) && (line[i] != '\0') + && (line[i] != ':')) { + i++; + } + + /* if format is in hex, e.g. #FAFAFA */ + if (line[0] == '#' && line_size > 1) { + hexline.data = (void *) &line[1]; + hexline.size = i - 1; + + if (gnutls_hex_decode2(&hexline, &hex_username) < 0) + return gnutls_assert_val(0); + + if (hex_username.size == username->size) + retval = memcmp(username->data, hex_username.data, username->size); + else + retval = -1; + + _gnutls_free_datum(&hex_username); + } else { + retval = strncmp((const char *) username->data, line, MAX(i, username->size)); + } + + return (retval == 0); +} + + +/* Randomizes the given password entry. It actually sets a random password. + * Returns 0 on success. + */ +static int _randomize_psk(gnutls_datum_t * psk) +{ + int ret; + + psk->data = gnutls_malloc(16); + if (psk->data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + psk->size = 16; + + ret = gnutls_rnd(GNUTLS_RND_NONCE, (char *) psk->data, 16); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +/* Returns the PSK key of the given user. + * If the user doesn't exist a random password is returned instead. + */ +int +_gnutls_psk_pwd_find_entry(gnutls_session_t session, + const char *username, uint16_t username_len, + gnutls_datum_t * psk) +{ + gnutls_psk_server_credentials_t cred; + FILE *fp; + char *line = NULL; + size_t line_size = 0; + int ret; + gnutls_datum_t username_datum = { + .data = (unsigned char *) username, + .size = username_len + }; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + /* if the callback which sends the parameters is + * set, use it. + */ + if (cred->pwd_callback != NULL) { + ret = cred->pwd_callback(session, &username_datum, psk); + + if (ret == 1) { /* the user does not exist */ + ret = _randomize_psk(psk); + if (ret < 0) { + gnutls_assert(); + return ret; + } + return 0; + } + + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_ERROR; + } + + return 0; + } + + /* The callback was not set. Proceed. + */ + if (cred->password_file == NULL) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_ERROR; + } + + /* Open the selected password file. + */ + fp = fopen(cred->password_file, "re"); + if (fp == NULL) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_ERROR; + } + + while (getline(&line, &line_size, fp) > 0) { + if (username_matches(&username_datum, line, line_size)) { + ret = pwd_put_values(psk, line); + if (ret < 0) { + gnutls_assert(); + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + ret = 0; + goto cleanup; + } + } + + /* user was not found. Fake him. + */ + ret = _randomize_psk(psk); + if (ret < 0) { + goto cleanup; + } + + ret = 0; +cleanup: + if (fp != NULL) + fclose(fp); + + zeroize_key(line, line_size); + free(line); + + return ret; + +} + +/* returns the username and they key for the PSK session. + * Free is non (0) if they have to be freed. + */ +int _gnutls_find_psk_key(gnutls_session_t session, + gnutls_psk_client_credentials_t cred, + gnutls_datum_t * username, gnutls_datum_t * key, + int *free) +{ + int ret; + + *free = 0; + + if (cred->username.data != NULL && cred->key.data != NULL) { + username->data = cred->username.data; + username->size = cred->username.size; + key->data = cred->key.data; + key->size = cred->key.size; + } else if (cred->get_function != NULL) { + ret = cred->get_function(session, username, key); + + if (ret) + return gnutls_assert_val(ret); + + *free = 1; + } else + return + gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + + return 0; +} diff --git a/lib/auth/psk_passwd.h b/lib/auth/psk_passwd.h new file mode 100644 index 0000000..3d351f2 --- /dev/null +++ b/lib/auth/psk_passwd.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-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_AUTH_PSK_PASSWD_H +#define GNUTLS_LIB_AUTH_PSK_PASSWD_H + +/* this is locally allocated. It should be freed using the provided function */ +int _gnutls_psk_pwd_find_entry(gnutls_session_t, + const char *username, uint16_t username_len, + gnutls_datum_t * key); + +int _gnutls_find_psk_key(gnutls_session_t session, + gnutls_psk_client_credentials_t cred, + gnutls_datum_t * username, gnutls_datum_t * key, + int *free); + +#endif /* GNUTLS_LIB_AUTH_PSK_PASSWD_H */ diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c new file mode 100644 index 0000000..858701f --- /dev/null +++ b/lib/auth/rsa.c @@ -0,0 +1,316 @@ +/* + * 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/> + * + */ + +/* This file contains the RSA key exchange part of the certificate + * authentication. + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "dh.h" +#include "num.h" +#include "datum.h" +#include <auth/cert.h> +#include <pk.h> +#include <algorithms.h> +#include <global.h> +#include "debug.h" +#include <tls-sig.h> +#include <x509.h> +#include <random.h> +#include <mpi.h> +#include <abstract_int.h> +#include <auth/rsa_common.h> + +int _gnutls_gen_rsa_client_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_rsa_client_kx(gnutls_session_t, uint8_t *, size_t); + +const mod_auth_st rsa_auth_struct = { + "RSA", + _gnutls_gen_cert_server_crt, + _gnutls_gen_cert_client_crt, + NULL, /* gen server kx */ + _gnutls_gen_rsa_client_kx, + _gnutls_gen_cert_client_crt_vrfy, /* gen client cert vrfy */ + _gnutls_gen_cert_server_cert_req, /* server cert request */ + + _gnutls_proc_crt, + _gnutls_proc_crt, + NULL, /* proc server kx */ + proc_rsa_client_kx, /* proc client kx */ + _gnutls_proc_cert_client_crt_vrfy, /* proc client cert vrfy */ + _gnutls_proc_cert_cert_req /* proc server cert request */ +}; + +static +int check_key_usage_for_enc(gnutls_session_t session, unsigned key_usage) +{ + if (key_usage != 0) { + if (!(key_usage & GNUTLS_KEY_KEY_ENCIPHERMENT) && !(key_usage & GNUTLS_KEY_KEY_AGREEMENT)) { + gnutls_assert(); + if (session->internals.allow_key_usage_violation == 0) { + _gnutls_audit_log(session, + "Peer's certificate does not allow encryption. Key usage violation detected.\n"); + return GNUTLS_E_KEY_USAGE_VIOLATION; + } else { + _gnutls_audit_log(session, + "Peer's certificate does not allow encryption. Key usage violation detected (ignored).\n"); + } + } + } + return 0; +} + +/* This function reads the RSA parameters from peer's certificate; + * + * IMPORTANT: + * Currently this function gets only called on the client side + * during generation of the client kx msg. This function + * retrieves the RSA params from the peer's certificate. That is in + * this case the server's certificate. As of GNUTLS version 3.6.4 it is + * possible to negotiate different certificate types for client and + * server. Therefore the correct cert type needs to be retrieved to be + * used for the _gnutls_get_auth_info_pcert call. If this + * function is to be called on the server side in the future, extra + * checks need to be build in order to retrieve the correct + * certificate type. + */ +int +_gnutls_get_public_rsa_params(gnutls_session_t session, + gnutls_pk_params_st * params) +{ + int ret; + cert_auth_info_t info; + unsigned key_usage; + gnutls_pcert_st peer_cert; + gnutls_certificate_type_t cert_type; + + assert(!IS_SERVER(session)); + + /* normal non export case */ + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + + if (info == NULL || info->ncerts == 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + // Get the negotiated server certificate type + cert_type = get_certificate_type(session, GNUTLS_CTYPE_SERVER); + + ret = _gnutls_get_auth_info_pcert(&peer_cert, cert_type, info); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + gnutls_pubkey_get_key_usage(peer_cert.pubkey, &key_usage); + + ret = check_key_usage_for_enc(session, key_usage); + if (ret < 0) { + gnutls_assert(); + goto cleanup2; + } + + gnutls_pk_params_init(params); + + ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params); + if (ret < 0) { + ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + goto cleanup2; + } + + gnutls_pcert_deinit(&peer_cert); + return 0; + + cleanup2: + gnutls_pcert_deinit(&peer_cert); + + return ret; +} + +static int +proc_rsa_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + gnutls_datum_t ciphertext; + int ret, dsize; + ssize_t data_size = _data_size; + volatile uint8_t ver_maj, ver_min; + +#ifdef ENABLE_SSL3 + if (get_num_version(session) == GNUTLS_SSL3) { + /* SSL 3.0 + */ + ciphertext.data = data; + ciphertext.size = data_size; + } else +#endif + { + /* TLS 1.0+ + */ + DECR_LEN(data_size, 2); + ciphertext.data = &data[2]; + dsize = _gnutls_read_uint16(data); + + if (dsize != data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + ciphertext.size = dsize; + } + + ver_maj = _gnutls_get_adv_version_major(session); + ver_min = _gnutls_get_adv_version_minor(session); + + session->key.key.data = gnutls_malloc(GNUTLS_MASTER_SIZE); + if (session->key.key.data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + session->key.key.size = GNUTLS_MASTER_SIZE; + + /* Fallback value when decryption fails. Needs to be unpredictable. */ + ret = gnutls_rnd(GNUTLS_RND_NONCE, session->key.key.data, + GNUTLS_MASTER_SIZE); + if (ret < 0) { + gnutls_free(session->key.key.data); + session->key.key.size = 0; + gnutls_assert(); + return ret; + } + + gnutls_privkey_decrypt_data2(session->internals.selected_key, + 0, &ciphertext, session->key.key.data, + session->key.key.size); + /* After this point, any conditional on failure that cause differences + * in execution may create a timing or cache access pattern side + * channel that can be used as an oracle, so treat very carefully */ + + /* Error handling logic: + * In case decryption fails then don't inform the peer. Just use the + * random key previously generated. (in order to avoid attack against + * pkcs-1 formatting). + * + * If we get version mismatches no error is returned either. We + * proceed normally. This is to defend against the attack described + * in the paper "Attacking RSA-based sessions in SSL/TLS" by + * Vlastimil Klima, Ondej Pokorny and Tomas Rosa. + */ + + /* This is here to avoid the version check attack + * discussed above. + */ + session->key.key.data[0] = ver_maj; + session->key.key.data[1] = ver_min; + + return 0; +} + + + +/* return RSA(random) using the peers public key + */ +int +_gnutls_gen_rsa_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + cert_auth_info_t auth = session->key.auth_info; + gnutls_datum_t sdata; /* data to send */ + gnutls_pk_params_st params; + int ret; + + if (auth == NULL) { + /* this shouldn't have happened. The proc_certificate + * function should have detected that. + */ + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + session->key.key.size = GNUTLS_MASTER_SIZE; + session->key.key.data = gnutls_malloc(session->key.key.size); + + if (session->key.key.data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + ret = gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data, + session->key.key.size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (session->internals.rsa_pms_version[0] == 0) { + session->key.key.data[0] = + _gnutls_get_adv_version_major(session); + session->key.key.data[1] = + _gnutls_get_adv_version_minor(session); + } else { /* use the version provided */ + session->key.key.data[0] = + session->internals.rsa_pms_version[0]; + session->key.key.data[1] = + session->internals.rsa_pms_version[1]; + } + + /* move RSA parameters to key (session). + */ + if ((ret = _gnutls_get_public_rsa_params(session, ¶ms)) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key, + ¶ms); + + gnutls_pk_params_release(¶ms); + + if (ret < 0) + return gnutls_assert_val(ret); + + +#ifdef ENABLE_SSL3 + if (get_num_version(session) == GNUTLS_SSL3) { + /* SSL 3.0 */ + ret = + _gnutls_buffer_append_data(data, sdata.data, + sdata.size); + + _gnutls_free_datum(&sdata); + return ret; + } else +#endif + { /* TLS 1.x */ + ret = + _gnutls_buffer_append_data_prefix(data, 16, sdata.data, + sdata.size); + + _gnutls_free_datum(&sdata); + return ret; + } +} diff --git a/lib/auth/rsa_common.h b/lib/auth/rsa_common.h new file mode 100644 index 0000000..d91448b --- /dev/null +++ b/lib/auth/rsa_common.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 + * Free Software Foundation, Inc. + * + * Copyright (C) 2011 + * Bardenheuer GmbH, Munich and Bundesdruckerei GmbH, Berlin + * + * Copyright (C) 2013 + * Frank Morgner <morgner@informatik.hu-berlin.de> + * + * Author: Frank Morgner + * + * 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_AUTH_RSA_COMMON_H +#define GNUTLS_LIB_AUTH_RSA_COMMON_H + +#include <abstract_int.h> + +int +_gnutls_get_public_rsa_params(gnutls_session_t session, + gnutls_pk_params_st * params); + +#endif /* GNUTLS_LIB_AUTH_RSA_COMMON_H */ diff --git a/lib/auth/rsa_psk.c b/lib/auth/rsa_psk.c new file mode 100644 index 0000000..3909295 --- /dev/null +++ b/lib/auth/rsa_psk.c @@ -0,0 +1,436 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009, 2010 + * Free Software Foundation, Inc. + * + * Copyright (C) 2011 + * Bardenheuer GmbH, Munich and Bundesdruckerei GmbH, Berlin + * + * Copyright (C) 2013 Frank Morgner + * 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA + * + */ + +#include "gnutls_int.h" + +#ifdef ENABLE_PSK + +#include "auth.h" +#include "dh.h" +#include "errors.h" +#include "mpi.h" +#include "num.h" +#include "gnutls_int.h" +#include "pk.h" +#include "random.h" +#include <abstract_int.h> +#include <algorithms.h> +#include <auth/dh_common.h> +#include <auth/psk.h> +#include <auth/psk_passwd.h> +#include <auth/rsa_common.h> +#include <cert.h> +#include <datum.h> +#include <state.h> + +static int _gnutls_gen_rsa_psk_client_kx(gnutls_session_t session, + gnutls_buffer_st * data); +static int _gnutls_proc_rsa_psk_client_kx(gnutls_session_t, uint8_t *, + size_t); +static int +_gnutls_proc_rsa_psk_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size); + +const mod_auth_st rsa_psk_auth_struct = { + "RSA PSK", + _gnutls_gen_cert_server_crt, + NULL, /* generate_client_certificate */ + _gnutls_gen_psk_server_kx, + _gnutls_gen_rsa_psk_client_kx, + NULL, /* generate_client_cert_vrfy */ + NULL, /* generate_server_certificate_request */ + _gnutls_proc_crt, + NULL, /* process_client_certificate */ + _gnutls_proc_rsa_psk_server_kx, + _gnutls_proc_rsa_psk_client_kx, + NULL, /* process_client_cert_vrfy */ + NULL /* process_server_certificate_reuqest */ +}; + +/* Set the PSK premaster secret. + */ +static int +set_rsa_psk_session_key(gnutls_session_t session, + gnutls_datum_t * ppsk, gnutls_datum_t * rsa_secret) +{ + unsigned char *p; + size_t rsa_secret_size; + int ret; + + + rsa_secret_size = rsa_secret->size; + + /* set the session key + */ + session->key.key.size = 2 + rsa_secret_size + 2 + ppsk->size; + session->key.key.data = gnutls_malloc(session->key.key.size); + if (session->key.key.data == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto error; + } + + /* format of the premaster secret: + * (uint16_t) other_secret size (48) + * other_secret: 2 byte version + 46 byte random + * (uint16_t) psk_size + * the psk + */ + _gnutls_write_uint16(rsa_secret_size, session->key.key.data); + memcpy(&session->key.key.data[2], rsa_secret->data, + rsa_secret->size); + p = &session->key.key.data[rsa_secret_size + 2]; + _gnutls_write_uint16(ppsk->size, p); + if (ppsk->data != NULL) + memcpy(p + 2, ppsk->data, ppsk->size); + + ret = 0; + + error: + return ret; +} + +/* Generate client key exchange message + * + * + * struct { + * select (KeyExchangeAlgorithm) { + * uint8_t psk_identity<0..2^16-1>; + * EncryptedPreMasterSecret; + * } exchange_keys; + * } ClientKeyExchange; + */ +static int +_gnutls_gen_rsa_psk_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + cert_auth_info_t auth = session->key.auth_info; + gnutls_datum_t sdata; /* data to send */ + gnutls_pk_params_st params; + gnutls_psk_client_credentials_t cred; + gnutls_datum_t username, key; + int ret, free; + unsigned init_pos; + + if (auth == NULL) { + /* this shouldn't have happened. The proc_certificate + * function should have detected that. + */ + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + gnutls_datum_t premaster_secret; + premaster_secret.size = GNUTLS_MASTER_SIZE; + premaster_secret.data = + gnutls_malloc(premaster_secret.size); + + if (premaster_secret.data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* Generate random */ + ret = gnutls_rnd(GNUTLS_RND_RANDOM, premaster_secret.data, + premaster_secret.size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Set version */ + if (session->internals.rsa_pms_version[0] == 0) { + premaster_secret.data[0] = + _gnutls_get_adv_version_major(session); + premaster_secret.data[1] = + _gnutls_get_adv_version_minor(session); + } else { /* use the version provided */ + premaster_secret.data[0] = + session->internals.rsa_pms_version[0]; + premaster_secret.data[1] = + session->internals.rsa_pms_version[1]; + } + + /* move RSA parameters to key (session). + */ + if ((ret = _gnutls_get_public_rsa_params(session, ¶ms)) < 0) { + gnutls_assert(); + return ret; + } + + /* Encrypt premaster secret */ + if ((ret = + _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &premaster_secret, + ¶ms)) < 0) { + gnutls_assert(); + return ret; + } + + gnutls_pk_params_release(¶ms); + + cred = (gnutls_psk_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + ret = _gnutls_find_psk_key(session, cred, &username, &key, &free); + if (ret < 0) + return gnutls_assert_val(ret); + + /* Here we set the PSK key */ + ret = set_rsa_psk_session_key(session, &key, &premaster_secret); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Create message for client key exchange + * + * struct { + * uint8_t psk_identity<0..2^16-1>; + * EncryptedPreMasterSecret; + * } + */ + + init_pos = data->length; + + /* Write psk_identity and EncryptedPreMasterSecret into data stream + */ + ret = + _gnutls_buffer_append_data_prefix(data, 16, + username.data, + username.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = + _gnutls_buffer_append_data_prefix(data, 16, sdata.data, + sdata.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + + cleanup: + _gnutls_free_datum(&sdata); + _gnutls_free_temp_key_datum(&premaster_secret); + if (free) { + _gnutls_free_temp_key_datum(&key); + gnutls_free(username.data); + } + + return ret; +} + +/* + Process the client key exchange message +*/ +static int +_gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + gnutls_datum_t username; + psk_auth_info_t info; + gnutls_datum_t plaintext; + gnutls_datum_t ciphertext; + gnutls_datum_t pwd_psk = { NULL, 0 }; + int ret, dsize; + int randomize_key = 0; + ssize_t data_size = _data_size; + gnutls_psk_server_credentials_t cred; + gnutls_datum_t premaster_secret = { NULL, 0 }; + + cred = (gnutls_psk_server_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_PSK); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, + sizeof(psk_auth_info_st), 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /*** 1. Extract user psk_identity ***/ + + DECR_LEN(data_size, 2); + username.size = _gnutls_read_uint16(&data[0]); + + DECR_LEN(data_size, username.size); + + username.data = &data[2]; + + /* copy the username to the auth info structures + */ + info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); + if (info == NULL) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (username.size > MAX_USERNAME_SIZE) { + gnutls_assert(); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; + } + + ret = _gnutls_copy_psk_username(info, username); + if (ret < 0) + gnutls_assert_val(ret); + + /* Adjust data so it points to EncryptedPreMasterSecret */ + data += username.size + 2; + + /*** 2. Decrypt and extract EncryptedPreMasterSecret ***/ + + DECR_LEN(data_size, 2); + ciphertext.data = &data[2]; + dsize = _gnutls_read_uint16(data); + + if (dsize != data_size) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + ciphertext.size = dsize; + + ret = + gnutls_privkey_decrypt_data(session->internals.selected_key, 0, + &ciphertext, &plaintext); + if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) { + /* In case decryption fails then don't inform + * the peer. Just use a random key. (in order to avoid + * attack against pkcs-1 formatting). + */ + gnutls_assert(); + _gnutls_debug_log + ("auth_rsa_psk: Possible PKCS #1 format attack\n"); + if (ret >= 0) { + gnutls_free(plaintext.data); + } + randomize_key = 1; + } else { + /* If the secret was properly formatted, then + * check the version number. + */ + if (_gnutls_get_adv_version_major(session) != + plaintext.data[0] + || (session->internals.allow_wrong_pms == 0 + && _gnutls_get_adv_version_minor(session) != + plaintext.data[1])) { + /* No error is returned here, if the version number check + * fails. We proceed normally. + * That is to defend against the attack described in the paper + * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, + * Ondej Pokorny and Tomas Rosa. + */ + gnutls_assert(); + _gnutls_debug_log + ("auth_rsa: Possible PKCS #1 version check format attack\n"); + } + } + + + if (randomize_key != 0) { + premaster_secret.size = GNUTLS_MASTER_SIZE; + premaster_secret.data = + gnutls_malloc(premaster_secret.size); + if (premaster_secret.data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* we do not need strong random numbers here. + */ + ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data, + premaster_secret.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } else { + premaster_secret.data = plaintext.data; + premaster_secret.size = plaintext.size; + } + + /* This is here to avoid the version check attack + * discussed above. + */ + + premaster_secret.data[0] = _gnutls_get_adv_version_major(session); + premaster_secret.data[1] = _gnutls_get_adv_version_minor(session); + + /* find the key of this username + */ + ret = + _gnutls_psk_pwd_find_entry(session, info->username, strlen(info->username), &pwd_psk); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = + set_rsa_psk_session_key(session, &pwd_psk, &premaster_secret); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + cleanup: + _gnutls_free_key_datum(&pwd_psk); + _gnutls_free_temp_key_datum(&premaster_secret); + + return ret; +} + +static int +_gnutls_proc_rsa_psk_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + /* In RSA-PSK the key is calculated elsewhere. + * Moreover, since we only keep a single auth info structure, we cannot + * store the hint (as we store certificate auth info). + * Ideally we need to handle that by multiple auth info + * structures or something similar. + */ + + return 0; +} + +#endif /* ENABLE_PSK */ diff --git a/lib/auth/srp_kx.c b/lib/auth/srp_kx.c new file mode 100644 index 0000000..e6ecf24 --- /dev/null +++ b/lib/auth/srp_kx.c @@ -0,0 +1,1021 @@ +/* + * 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" + +#ifdef ENABLE_SRP + +#include "errors.h" +#include <auth/srp_passwd.h> +#include "auth.h" +#include "srp.h" +#include "num.h" +#include <auth/srp_kx.h> +#include <str.h> +#include <datum.h> +#include <ext/srp.h> + +const mod_auth_st srp_auth_struct = { + "SRP", + NULL, + NULL, + _gnutls_gen_srp_server_kx, + _gnutls_gen_srp_client_kx, + NULL, + NULL, + + NULL, + NULL, /* certificate */ + _gnutls_proc_srp_server_kx, + _gnutls_proc_srp_client_kx, + NULL, + NULL +}; + + +#define _b session->key.proto.tls12.srp.b +#define B session->key.proto.tls12.srp.B +#define _a session->key.proto.tls12.srp.a +#define A session->key.proto.tls12.srp.A +#define N session->key.proto.tls12.srp.srp_p +#define G session->key.proto.tls12.srp.srp_g +#define V session->key.proto.tls12.srp.x +#define S session->key.proto.tls12.srp.srp_key + +/* Checks if a%n==0,+1,-1%n which is a fatal srp error. + * Returns a proper error code in that case, and 0 when + * all are ok. + */ +inline static int check_param_mod_n(bigint_t a, bigint_t n, int is_a) +{ + int ret, err = 0; + bigint_t r; + + ret = _gnutls_mpi_init(&r); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_mpi_modm(r, a, n); + if (ret < 0) { + _gnutls_mpi_release(&r); + return gnutls_assert_val(ret); + } + + ret = _gnutls_mpi_cmp_ui(r, 0); + if (ret == 0) + err = 1; + + if (is_a != 0) { + ret = _gnutls_mpi_cmp_ui(r, 1); + if (ret == 0) + err = 1; + + ret = _gnutls_mpi_add_ui(r, r, 1); + if (ret < 0) { + _gnutls_mpi_release(&r); + return gnutls_assert_val(ret); + } + + ret = _gnutls_mpi_cmp(r, n); + if (ret == 0) + err = 1; + } + + _gnutls_mpi_release(&r); + + if (err != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + return 0; +} + + +/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number + * Data is allocated by the caller, and should have data_size size. + */ +int +_gnutls_gen_srp_server_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret; + SRP_PWD_ENTRY *pwd_entry; + srp_server_auth_info_t info; + size_t tmp_size, username_length; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv; + unsigned init_pos; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRP, + &epriv); + if (ret < 0) { /* peer didn't send a username */ + gnutls_assert(); + return GNUTLS_E_UNKNOWN_SRP_USERNAME; + } + priv = epriv; + + if ((ret = + _gnutls_auth_info_init(session, GNUTLS_CRD_SRP, + sizeof(srp_server_auth_info_st), + 1)) < 0) { + gnutls_assert(); + return ret; + } + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + username_length = strlen(priv->username); + if (username_length > MAX_USERNAME_SIZE) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_SRP_USERNAME); + + gnutls_free(info->username); + info->username = gnutls_strdup(priv->username); + if (info->username == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + ret = _gnutls_srp_pwd_read_entry(session, priv->username, &pwd_entry); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + init_pos = data->length; + + /* copy from pwd_entry to local variables (actually in session) */ + tmp_size = pwd_entry->g.size; + if (_gnutls_mpi_init_scan_nz(&G, pwd_entry->g.data, tmp_size) < 0) { + gnutls_assert(); + ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + goto cleanup; + } + + tmp_size = pwd_entry->n.size; + if (_gnutls_mpi_init_scan_nz(&N, pwd_entry->n.data, tmp_size) < 0) { + gnutls_assert(); + ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + goto cleanup; + } + + tmp_size = pwd_entry->v.size; + if (_gnutls_mpi_init_scan_nz(&V, pwd_entry->v.data, tmp_size) < 0) { + gnutls_assert(); + ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + goto cleanup; + } + + /* Calculate: B = (k*v + g^b) % N + */ + B = _gnutls_calc_srp_B(&_b, G, N, V); + if (B == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + /* copy N (mod n) + */ + ret = + _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->n.data, + pwd_entry->n.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* copy G (generator) to data + */ + ret = + _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->g.data, + pwd_entry->g.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* copy the salt + */ + ret = + _gnutls_buffer_append_data_prefix(data, 8, + pwd_entry->salt.data, + pwd_entry->salt.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + /* Copy the B value + */ + + ret = _gnutls_buffer_append_mpi(data, 16, B, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + _gnutls_mpi_log("SRP B: ", B); + + ret = data->length - init_pos; + + cleanup: + _gnutls_srp_entry_free(pwd_entry); + return ret; +} + +/* return A = g^a % N */ +int +_gnutls_gen_srp_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret; + char *username, *password; + gnutls_srp_client_credentials_t cred; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRP, + &epriv); + if (ret < 0) { /* peer didn't send a username */ + gnutls_assert(); + return GNUTLS_E_UNKNOWN_SRP_USERNAME; + } + priv = epriv; + + cred = (gnutls_srp_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_SRP); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if (priv->username == NULL) { + username = cred->username; + password = cred->password; + } else { + + username = priv->username; + password = priv->password; + } + + if (username == NULL || password == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + /* calc A = g^a % N + */ + if (G == NULL || N == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + A = _gnutls_calc_srp_A(&_a, G, N); + if (A == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* Rest of SRP calculations + */ + + /* calculate u */ + session->key.proto.tls12.srp.u = _gnutls_calc_srp_u(A, B, N); + if (session->key.proto.tls12.srp.u == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + _gnutls_mpi_log("SRP U: ", session->key.proto.tls12.srp.u); + + /* S = (B - g^x) ^ (a + u * x) % N */ + S = _gnutls_calc_srp_S2(B, G, session->key.proto.tls12.srp.x, _a, session->key.proto.tls12.srp.u, + N); + if (S == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + _gnutls_mpi_log("SRP B: ", B); + + zrelease_temp_mpi_key(&_b); + zrelease_temp_mpi_key(&V); + zrelease_temp_mpi_key(&session->key.proto.tls12.srp.u); + zrelease_temp_mpi_key(&B); + + ret = _gnutls_mpi_dprint(session->key.proto.tls12.srp.srp_key, &session->key.key); + zrelease_temp_mpi_key(&S); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _gnutls_buffer_append_mpi(data, 16, A, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + _gnutls_mpi_log("SRP A: ", A); + + _gnutls_mpi_release(&A); + + return data->length; +} + + +/* just read A and put it to session */ +int +_gnutls_proc_srp_client_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + ssize_t _n_A; + ssize_t data_size = _data_size; + int ret; + + DECR_LEN(data_size, 2); + _n_A = _gnutls_read_uint16(&data[0]); + + DECR_LEN(data_size, _n_A); + if (_gnutls_mpi_init_scan_nz(&A, &data[2], _n_A) || A == NULL) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + _gnutls_mpi_log("SRP A: ", A); + _gnutls_mpi_log("SRP B: ", B); + + /* Checks if A % n == 0. + */ + if ((ret = check_param_mod_n(A, N, 1)) < 0) { + gnutls_assert(); + return ret; + } + + /* Start the SRP calculations. + * - Calculate u + */ + session->key.proto.tls12.srp.u = _gnutls_calc_srp_u(A, B, N); + if (session->key.proto.tls12.srp.u == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + _gnutls_mpi_log("SRP U: ", session->key.proto.tls12.srp.u); + + /* S = (A * v^u) ^ b % N + */ + S = _gnutls_calc_srp_S1(A, _b, session->key.proto.tls12.srp.u, V, N); + if (S == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + _gnutls_mpi_log("SRP S: ", S); + + _gnutls_mpi_release(&A); + zrelease_temp_mpi_key(&_b); + zrelease_temp_mpi_key(&V); + zrelease_temp_mpi_key(&session->key.proto.tls12.srp.u); + zrelease_temp_mpi_key(&B); + + ret = _gnutls_mpi_dprint(session->key.proto.tls12.srp.srp_key, &session->key.key); + zrelease_temp_mpi_key(&S); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + + + +/* Static parameters according to draft-ietf-tls-srp-07 + * Note that if more parameters are added check_g_n() + * and _gnutls_srp_entry_free() should be changed. + */ +static const unsigned char srp_params_1024[] = { + 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, + 0x9C, 0x33, 0xF8, 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, + 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, 0x3C, 0x0B, + 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, + 0xD6, 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, + 0x38, 0x3B, 0x48, 0x13, 0xD6, 0x92, 0xC6, 0xE0, + 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, 0xE4, + 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, + 0x5D, 0xC7, 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, + 0xCE, 0x8E, 0xF4, 0xAD, 0x69, 0xB1, 0x5D, 0x49, + 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85, + 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, + 0x68, 0xED, 0xBC, 0x3C, 0x05, 0x72, 0x6C, 0xC0, + 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, 0xAA, 0x9A, + 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, + 0x9F, 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3 +}; + +static const unsigned char srp_generator = 0x02; +static const unsigned char srp3072_generator = 0x05; +static const unsigned char srp8192_generator = 19; + +const gnutls_datum_t gnutls_srp_1024_group_prime = { + (void *) srp_params_1024, sizeof(srp_params_1024) +}; + +const gnutls_datum_t gnutls_srp_1024_group_generator = { + (void *) &srp_generator, sizeof(srp_generator) +}; + +static const unsigned char srp_params_1536[] = { + 0x9D, 0xEF, 0x3C, 0xAF, 0xB9, 0x39, 0x27, 0x7A, 0xB1, + 0xF1, 0x2A, 0x86, 0x17, 0xA4, 0x7B, 0xBB, 0xDB, 0xA5, + 0x1D, 0xF4, 0x99, 0xAC, 0x4C, 0x80, 0xBE, 0xEE, 0xA9, + 0x61, 0x4B, 0x19, 0xCC, 0x4D, 0x5F, 0x4F, 0x5F, 0x55, + 0x6E, 0x27, 0xCB, 0xDE, 0x51, 0xC6, 0xA9, 0x4B, 0xE4, + 0x60, 0x7A, 0x29, 0x15, 0x58, 0x90, 0x3B, 0xA0, 0xD0, + 0xF8, 0x43, 0x80, 0xB6, 0x55, 0xBB, 0x9A, 0x22, 0xE8, + 0xDC, 0xDF, 0x02, 0x8A, 0x7C, 0xEC, 0x67, 0xF0, 0xD0, + 0x81, 0x34, 0xB1, 0xC8, 0xB9, 0x79, 0x89, 0x14, 0x9B, + 0x60, 0x9E, 0x0B, 0xE3, 0xBA, 0xB6, 0x3D, 0x47, 0x54, + 0x83, 0x81, 0xDB, 0xC5, 0xB1, 0xFC, 0x76, 0x4E, 0x3F, + 0x4B, 0x53, 0xDD, 0x9D, 0xA1, 0x15, 0x8B, 0xFD, 0x3E, + 0x2B, 0x9C, 0x8C, 0xF5, 0x6E, 0xDF, 0x01, 0x95, 0x39, + 0x34, 0x96, 0x27, 0xDB, 0x2F, 0xD5, 0x3D, 0x24, 0xB7, + 0xC4, 0x86, 0x65, 0x77, 0x2E, 0x43, 0x7D, 0x6C, 0x7F, + 0x8C, 0xE4, 0x42, 0x73, 0x4A, 0xF7, 0xCC, 0xB7, 0xAE, + 0x83, 0x7C, 0x26, 0x4A, 0xE3, 0xA9, 0xBE, 0xB8, 0x7F, + 0x8A, 0x2F, 0xE9, 0xB8, 0xB5, 0x29, 0x2E, 0x5A, 0x02, + 0x1F, 0xFF, 0x5E, 0x91, 0x47, 0x9E, 0x8C, 0xE7, 0xA2, + 0x8C, 0x24, 0x42, 0xC6, 0xF3, 0x15, 0x18, 0x0F, 0x93, + 0x49, 0x9A, 0x23, 0x4D, 0xCF, 0x76, 0xE3, 0xFE, 0xD1, + 0x35, 0xF9, 0xBB +}; + +const gnutls_datum_t gnutls_srp_1536_group_prime = { + (void *) srp_params_1536, sizeof(srp_params_1536) +}; + +const gnutls_datum_t gnutls_srp_1536_group_generator = { + (void *) &srp_generator, sizeof(srp_generator) +}; + +static const unsigned char srp_params_2048[] = { + 0xAC, 0x6B, 0xDB, 0x41, 0x32, 0x4A, 0x9A, 0x9B, 0xF1, + 0x66, 0xDE, 0x5E, 0x13, 0x89, 0x58, 0x2F, 0xAF, 0x72, + 0xB6, 0x65, 0x19, 0x87, 0xEE, 0x07, 0xFC, 0x31, 0x92, + 0x94, 0x3D, 0xB5, 0x60, 0x50, 0xA3, 0x73, 0x29, 0xCB, + 0xB4, 0xA0, 0x99, 0xED, 0x81, 0x93, 0xE0, 0x75, 0x77, + 0x67, 0xA1, 0x3D, 0xD5, 0x23, 0x12, 0xAB, 0x4B, 0x03, + 0x31, 0x0D, 0xCD, 0x7F, 0x48, 0xA9, 0xDA, 0x04, 0xFD, + 0x50, 0xE8, 0x08, 0x39, 0x69, 0xED, 0xB7, 0x67, 0xB0, + 0xCF, 0x60, 0x95, 0x17, 0x9A, 0x16, 0x3A, 0xB3, 0x66, + 0x1A, 0x05, 0xFB, 0xD5, 0xFA, 0xAA, 0xE8, 0x29, 0x18, + 0xA9, 0x96, 0x2F, 0x0B, 0x93, 0xB8, 0x55, 0xF9, 0x79, + 0x93, 0xEC, 0x97, 0x5E, 0xEA, 0xA8, 0x0D, 0x74, 0x0A, + 0xDB, 0xF4, 0xFF, 0x74, 0x73, 0x59, 0xD0, 0x41, 0xD5, + 0xC3, 0x3E, 0xA7, 0x1D, 0x28, 0x1E, 0x44, 0x6B, 0x14, + 0x77, 0x3B, 0xCA, 0x97, 0xB4, 0x3A, 0x23, 0xFB, 0x80, + 0x16, 0x76, 0xBD, 0x20, 0x7A, 0x43, 0x6C, 0x64, 0x81, + 0xF1, 0xD2, 0xB9, 0x07, 0x87, 0x17, 0x46, 0x1A, 0x5B, + 0x9D, 0x32, 0xE6, 0x88, 0xF8, 0x77, 0x48, 0x54, 0x45, + 0x23, 0xB5, 0x24, 0xB0, 0xD5, 0x7D, 0x5E, 0xA7, 0x7A, + 0x27, 0x75, 0xD2, 0xEC, 0xFA, 0x03, 0x2C, 0xFB, 0xDB, + 0xF5, 0x2F, 0xB3, 0x78, 0x61, 0x60, 0x27, 0x90, 0x04, + 0xE5, 0x7A, 0xE6, 0xAF, 0x87, 0x4E, 0x73, 0x03, 0xCE, + 0x53, 0x29, 0x9C, 0xCC, 0x04, 0x1C, 0x7B, 0xC3, 0x08, + 0xD8, 0x2A, 0x56, 0x98, 0xF3, 0xA8, 0xD0, 0xC3, 0x82, + 0x71, 0xAE, 0x35, 0xF8, 0xE9, 0xDB, 0xFB, 0xB6, 0x94, + 0xB5, 0xC8, 0x03, 0xD8, 0x9F, 0x7A, 0xE4, 0x35, 0xDE, + 0x23, 0x6D, 0x52, 0x5F, 0x54, 0x75, 0x9B, 0x65, 0xE3, + 0x72, 0xFC, 0xD6, 0x8E, 0xF2, 0x0F, 0xA7, 0x11, 0x1F, + 0x9E, 0x4A, 0xFF, 0x73 +}; + +const gnutls_datum_t gnutls_srp_2048_group_prime = { + (void *) srp_params_2048, sizeof(srp_params_2048) +}; + +const gnutls_datum_t gnutls_srp_2048_group_generator = { + (void *) &srp_generator, sizeof(srp_generator) +}; + +static const unsigned char srp_params_3072[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, + 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, + 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, + 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, + 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, + 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, + 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, + 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, + 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, + 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, + 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, + 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, + 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, + 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, + 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, + 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, + 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, + 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, + 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, + 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, + 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, + 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, + 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, + 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, + 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, + 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, + 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, + 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, + 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, + 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, + 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, + 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, + 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, + 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, + 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, + 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, + 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +const gnutls_datum_t gnutls_srp_3072_group_generator = { + (void *) &srp3072_generator, sizeof(srp3072_generator) +}; + +const gnutls_datum_t gnutls_srp_3072_group_prime = { + (void *) srp_params_3072, sizeof(srp_params_3072) +}; + +static const unsigned char srp_params_4096[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, + 0xA2, + 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, + 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, + 0xA6, + 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, + 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, + 0x6D, + 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, + 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, + 0xE9, + 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, + 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, + 0x11, + 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, + 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, + 0x36, + 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, + 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, + 0x56, + 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, + 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, + 0x08, + 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, + 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, + 0xA2, + 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, + 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, + 0x7C, + 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, + 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, + 0x0D, + 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, + 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, + 0x57, + 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, + 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, + 0xE0, + 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, + 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, + 0x73, + 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, + 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, + 0xC0, + 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, + 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, + 0x20, + 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, + 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, + 0x18, + 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, + 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, + 0xDB, + 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, + 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, + 0x4F, + 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, + 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, + 0x76, + 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, + 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, + 0xDC, + 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, + 0x99, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +const gnutls_datum_t gnutls_srp_4096_group_generator = { + (void *) &srp3072_generator, sizeof(srp3072_generator) +}; + +const gnutls_datum_t gnutls_srp_4096_group_prime = { + (void *) srp_params_4096, sizeof(srp_params_4096) +}; + +static const unsigned char srp_params_8192[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, + 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, + 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, + 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, + 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, + 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, + 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, + 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, + 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, + 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, + 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, + 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, + 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, + 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, + 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, + 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, + 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, + 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, + 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, + 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, + 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, + 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, + 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, + 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, + 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, + 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, + 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, + 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, + 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, + 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, + 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, + 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, + 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, + 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, + 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, + 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, + 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, + 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, + 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, + 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, + 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, + 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, + 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, + 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, + 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, + 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, + 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, + 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, + 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, + 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, + 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, + 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, + 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, + 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, + 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, + 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, + 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, + 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, + 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, + 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, + 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, + 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, + 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, + 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, + 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +const gnutls_datum_t gnutls_srp_8192_group_prime = { + (void *) srp_params_8192, sizeof(srp_params_8192) +}; + +const gnutls_datum_t gnutls_srp_8192_group_generator = { + (void *) &srp8192_generator, sizeof(srp8192_generator) +}; + +/* Check if G and N are parameters from the SRP draft. + */ +static int +check_g_n(const uint8_t * g, size_t n_g, const uint8_t * n, size_t n_n) +{ + + if (n_n == sizeof(srp_params_8192)) { + if (memcmp(srp_params_8192, n, n_n) == 0 && + n_g == 1 && g[0] == srp8192_generator) + return 0; + return + gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + if (n_n == sizeof(srp_params_4096)) { + if (memcmp(srp_params_4096, n, n_n) == 0 && + n_g == 1 && g[0] == srp3072_generator) + return 0; + return + gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + if (n_n == sizeof(srp_params_3072)) { + if (memcmp(srp_params_3072, n, n_n) == 0 && + n_g == 1 && g[0] == srp3072_generator) + return 0; + return + gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } + + /* 2048, 1536 and 1024 */ + if (n_g != 1 || g[0] != srp_generator) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + if (n_n == sizeof(srp_params_1024) && + memcmp(srp_params_1024, n, n_n) == 0) { + return 0; + } + + if (n_n == sizeof(srp_params_1536) && + memcmp(srp_params_1536, n, n_n) == 0) { + return 0; + } + + if (n_n == sizeof(srp_params_2048) && + memcmp(srp_params_2048, n, n_n) == 0) { + return 0; + } + + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; +} + +/* receive the key exchange message ( n, g, s, B) + */ +int +_gnutls_proc_srp_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + uint8_t n_s; + uint16_t n_g, n_n, n_b; + size_t _n_g, _n_n, _n_b; + const uint8_t *data_n; + const uint8_t *data_g; + const uint8_t *data_s; + const uint8_t *data_b; + int i, ret; + uint8_t hd[SRP_MAX_HASH_SIZE]; + char *username, *password; + ssize_t data_size = _data_size; + gnutls_srp_client_credentials_t cred; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv; + + ret = + _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_SRP, + &epriv); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_SRP_USERNAME; + } + priv = epriv; + + cred = (gnutls_srp_client_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_SRP); + + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + if (priv->username == NULL) { + username = cred->username; + password = cred->password; + } else { + username = priv->username; + password = priv->password; + } + + if (username == NULL || password == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + i = 0; + + /* Read N + */ + DECR_LEN(data_size, 2); + n_n = _gnutls_read_uint16(&data[i]); + i += 2; + + DECR_LEN(data_size, n_n); + data_n = &data[i]; + i += n_n; + + /* Read G + */ + DECR_LEN(data_size, 2); + n_g = _gnutls_read_uint16(&data[i]); + i += 2; + + DECR_LEN(data_size, n_g); + data_g = &data[i]; + i += n_g; + + /* Read salt + */ + DECR_LEN(data_size, 1); + n_s = data[i]; + i += 1; + + DECR_LEN(data_size, n_s); + data_s = &data[i]; + i += n_s; + + /* Read B + */ + DECR_LEN(data_size, 2); + n_b = _gnutls_read_uint16(&data[i]); + i += 2; + + DECR_LEN(data_size, n_b); + data_b = &data[i]; + i += n_b; + + _n_g = n_g; + _n_n = n_n; + _n_b = n_b; + + if (_gnutls_mpi_init_scan_nz(&N, data_n, _n_n) != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + if (_gnutls_mpi_init_scan_nz(&G, data_g, _n_g) != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + if (_gnutls_mpi_init_scan_nz(&B, data_b, _n_b) != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + + /* Check if the g and n are from the SRP + * draft. Otherwise check if N is a prime and G + * a generator. + */ + if ((ret = check_g_n(data_g, _n_g, data_n, _n_n)) < 0) { + _gnutls_audit_log(session, + "SRP group parameters are not in the white list; rejecting.\n"); + return gnutls_assert_val(ret); + } + + /* Checks if b % n == 0 + */ + if ((ret = check_param_mod_n(B, N, 0)) < 0) { + gnutls_assert(); + return ret; + } + + + /* generate x = SHA(s | SHA(U | ":" | p)) + * (or the equivalent using bcrypt) + */ + if ((ret = + _gnutls_calc_srp_x(username, password, (uint8_t *) data_s, + n_s, &_n_g, hd)) < 0) { + gnutls_assert(); + return ret; + } + + if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.srp.x, hd, _n_g) != 0) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } + + + return i; /* return the processed data + * needed in auth_srp_rsa. + */ +} + +#endif /* ENABLE_SRP */ diff --git a/lib/auth/srp_kx.h b/lib/auth/srp_kx.h new file mode 100644 index 0000000..3cf5252 --- /dev/null +++ b/lib/auth/srp_kx.h @@ -0,0 +1,74 @@ +/* + * 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_AUTH_SRP_KX_H +#define GNUTLS_LIB_AUTH_SRP_KX_H + +#include <auth.h> + +#define MAX_FAKE_SALT_SEED_SIZE 64 + +typedef struct gnutls_srp_client_credentials_st { + char *username; + char *password; + gnutls_srp_client_credentials_function *get_function; +} srp_client_credentials_st; + +typedef struct gnutls_srp_server_credentials_st { + char *password_file; + char *password_conf_file; + /* callback function, instead of reading the + * password files. + */ + gnutls_srp_server_credentials_function *pwd_callback; + unsigned char fake_salt_seed[MAX_FAKE_SALT_SEED_SIZE]; + unsigned int fake_salt_seed_size; + + unsigned int fake_salt_length; +} srp_server_cred_st; + +typedef struct srp_server_auth_info_st { + char *username; +} *srp_server_auth_info_t; + +#ifdef ENABLE_SRP + +int _gnutls_proc_srp_server_hello(gnutls_session_t state, + const uint8_t * data, size_t data_size); +int _gnutls_gen_srp_server_hello(gnutls_session_t state, uint8_t * data, + size_t data_size); + +int _gnutls_gen_srp_server_kx(gnutls_session_t, gnutls_buffer_st *); +int _gnutls_gen_srp_client_kx(gnutls_session_t, gnutls_buffer_st *); + +int _gnutls_proc_srp_server_kx(gnutls_session_t, uint8_t *, size_t); +int _gnutls_proc_srp_client_kx(gnutls_session_t, uint8_t *, size_t); + +typedef struct srp_server_auth_info_st srp_server_auth_info_st; + +/* MAC algorithm used to generate fake salts for unknown usernames + */ +#define SRP_FAKE_SALT_MAC GNUTLS_MAC_SHA1 + +#endif /* ENABLE_SRP */ + +#endif /* GNUTLS_LIB_AUTH_SRP_KX_H */ diff --git a/lib/auth/srp_passwd.c b/lib/auth/srp_passwd.c new file mode 100644 index 0000000..e7d8d60 --- /dev/null +++ b/lib/auth/srp_passwd.c @@ -0,0 +1,470 @@ +/* + * 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/> + * + */ + +/* Functions for operating in an SRP passwd file are included here */ + +#include "gnutls_int.h" + +#ifdef ENABLE_SRP + +#include "x509_b64.h" +#include "errors.h" +#include <auth/srp_passwd.h> +#include <auth/srp_kx.h> +#include "auth.h" +#include "srp.h" +#include "dh.h" +#include "debug.h" +#include <str.h> +#include <datum.h> +#include <num.h> +#include <random.h> +#include <algorithms.h> + +static int _randomize_pwd_entry(SRP_PWD_ENTRY * entry, + gnutls_srp_server_credentials_t cred, + const char * username); + +/* this function parses tpasswd.conf file. Format is: + * string(username):base64(v):base64(salt):int(index) + */ +static int parse_tpasswd_values(SRP_PWD_ENTRY * entry, char *str) +{ + char *p; + int len, ret; + uint8_t *verifier; + size_t verifier_size; + int indx; + + p = strrchr(str, ':'); /* we have index */ + if (p == NULL) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + *p = '\0'; + p++; + + indx = atoi(p); + if (indx == 0) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + /* now go for salt */ + p = strrchr(str, ':'); /* we have salt */ + if (p == NULL) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + *p = '\0'; + p++; + + len = strlen(p); + + entry->salt.size = + _gnutls_sbase64_decode(p, len, &entry->salt.data); + + if (entry->salt.size <= 0) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + /* now go for verifier */ + p = strrchr(str, ':'); /* we have verifier */ + if (p == NULL) { + _gnutls_free_datum(&entry->salt); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + *p = '\0'; + p++; + + len = strlen(p); + ret = _gnutls_sbase64_decode(p, len, &verifier); + if (ret <= 0) { + gnutls_assert(); + _gnutls_free_datum(&entry->salt); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + verifier_size = ret; + entry->v.data = verifier; + entry->v.size = verifier_size; + + /* now go for username */ + *p = '\0'; + + entry->username = gnutls_strdup(str); + if (entry->username == NULL) { + _gnutls_free_datum(&entry->salt); + _gnutls_free_key_datum(&entry->v); + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + return indx; +} + + +/* this function parses tpasswd.conf file. Format is: + * int(index):base64(n):int(g) + */ +static int parse_tpasswd_conf_values(SRP_PWD_ENTRY * entry, char *str) +{ + char *p; + int len; + uint8_t *tmp; + int ret; + + p = strrchr(str, ':'); /* we have g */ + if (p == NULL) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + *p = '\0'; + p++; + + /* read the generator */ + len = strlen(p); + if (p[len - 1] == '\n' || p[len - 1] == ' ') + len--; + ret = _gnutls_sbase64_decode(p, len, &tmp); + + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + entry->g.data = tmp; + entry->g.size = ret; + + /* now go for n - modulo */ + p = strrchr(str, ':'); /* we have n */ + if (p == NULL) { + _gnutls_free_datum(&entry->g); + gnutls_assert(); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + *p = '\0'; + p++; + + len = strlen(p); + ret = _gnutls_sbase64_decode(p, len, &tmp); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&entry->g); + return GNUTLS_E_SRP_PWD_PARSING_ERROR; + } + + entry->n.data = tmp; + entry->n.size = ret; + + return 0; +} + + +/* this function opens the tpasswd.conf file and reads the g and n + * values. They are put in the entry. + */ +static int +pwd_read_conf(const char *pconf_file, SRP_PWD_ENTRY * entry, int idx) +{ + FILE *fp; + char *line = NULL; + size_t line_size = 0; + unsigned i, len; + char indexstr[10]; + int ret; + + snprintf(indexstr, sizeof(indexstr), "%u", (unsigned int) idx); + + fp = fopen(pconf_file, "re"); + if (fp == NULL) { + gnutls_assert(); + return GNUTLS_E_FILE_ERROR; + } + + len = strlen(indexstr); + while (getline(&line, &line_size, fp) > 0) { + /* move to first ':' */ + i = 0; + while ((i < line_size) && (line[i] != ':') + && (line[i] != '\0')) { + i++; + } + + if (strncmp(indexstr, line, MAX(i, len)) == 0) { + if (parse_tpasswd_conf_values(entry, line) >= 0) { + ret = 0; + goto cleanup; + } else { + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + } + } + ret = GNUTLS_E_SRP_PWD_ERROR; + +cleanup: + zeroize_key(line, line_size); + free(line); + fclose(fp); + return ret; + +} + +int +_gnutls_srp_pwd_read_entry(gnutls_session_t state, char *username, + SRP_PWD_ENTRY ** _entry) +{ + gnutls_srp_server_credentials_t cred; + FILE *fp = NULL; + char *line = NULL; + size_t line_size = 0; + unsigned i, len; + int ret; + int idx; + SRP_PWD_ENTRY *entry = NULL; + + *_entry = gnutls_calloc(1, sizeof(SRP_PWD_ENTRY)); + if (*_entry == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + entry = *_entry; + + cred = (gnutls_srp_server_credentials_t) + _gnutls_get_cred(state, GNUTLS_CRD_SRP); + if (cred == NULL) { + gnutls_assert(); + ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS; + goto cleanup; + } + + /* if the callback which sends the parameters is + * set, use it. + */ + if (cred->pwd_callback != NULL) { + ret = cred->pwd_callback(state, username, &entry->salt, + &entry->v, &entry->g, &entry->n); + + if (ret == 1) { /* the user does not exist */ + if (entry->g.size != 0 && entry->n.size != 0) { + ret = _randomize_pwd_entry(entry, cred, username); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + return 0; + } else { + gnutls_assert(); + ret = -1; /* error in the callback */ + } + } + + if (ret < 0) { + gnutls_assert(); + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + + return 0; + } + + /* The callback was not set. Proceed. + */ + + if (cred->password_file == NULL) { + gnutls_assert(); + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + + /* Open the selected password file. + */ + fp = fopen(cred->password_file, "re"); + if (fp == NULL) { + gnutls_assert(); + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + + len = strlen(username); + while (getline(&line, &line_size, fp) > 0) { + /* move to first ':' */ + i = 0; + while ((i < line_size) && (line[i] != '\0') + && (line[i] != ':')) { + i++; + } + + if (strncmp(username, line, MAX(i, len)) == 0) { + if ((idx = parse_tpasswd_values(entry, line)) >= 0) { + /* Keep the last index in memory, so we can retrieve fake parameters (g,n) + * when the user does not exist. + */ + if (pwd_read_conf + (cred->password_conf_file, entry, + idx) == 0) { + ret = 0; + goto found; + } else { + gnutls_assert(); + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + } else { + gnutls_assert(); + ret = GNUTLS_E_SRP_PWD_ERROR; + goto cleanup; + } + } + } + + /* user was not found. Fake him. Actually read the g,n values from + * the last index found and randomize the entry. + */ + if (pwd_read_conf(cred->password_conf_file, entry, 1) == 0) { + ret = _randomize_pwd_entry(entry, cred, username); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + goto found; + } + + ret = GNUTLS_E_SRP_PWD_ERROR; + +cleanup: + gnutls_assert(); + _gnutls_srp_entry_free(entry); + +found: + if (line) { + zeroize_key(line, line_size); + free(line); + } + if (fp) + fclose(fp); + return ret; +} + +/* Randomizes the given password entry. It actually sets the verifier + * to random data and sets the salt based on fake_salt_seed and + * username. Returns 0 on success. + */ +static int _randomize_pwd_entry(SRP_PWD_ENTRY * entry, + gnutls_srp_server_credentials_t sc, + const char * username) +{ + int ret; + const mac_entry_st *me = mac_to_entry(SRP_FAKE_SALT_MAC); + mac_hd_st ctx; + size_t username_len = strlen(username); + + if (entry->g.size == 0 || entry->n.size == 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + entry->v.data = gnutls_malloc(20); + entry->v.size = 20; + if (entry->v.data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + ret = gnutls_rnd(GNUTLS_RND_NONCE, entry->v.data, 20); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Always allocate and work with the output size of the MAC, + * even if they don't need salts that long, for convenience. + * + * In case an error occurs 'entry' (and the salt inside) + * is deallocated by our caller: _gnutls_srp_pwd_read_entry(). + */ + entry->salt.data = gnutls_malloc(me->output_size); + if (entry->salt.data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + ret = _gnutls_mac_init(&ctx, me, sc->fake_salt_seed, + sc->fake_salt_seed_size); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + _gnutls_mac(&ctx, "salt", 4); + _gnutls_mac(&ctx, username, username_len); + _gnutls_mac_deinit(&ctx, entry->salt.data); + + /* Set length to the actual number of bytes they asked for. + * This is always less than or equal to the output size of + * the MAC, enforced by gnutls_srp_set_server_fake_salt_seed(). + */ + entry->salt.size = sc->fake_salt_length; + + return 0; +} + +/* Free all the entry parameters, except if g and n are + * the static ones defined in gnutls.h + */ +void _gnutls_srp_entry_free(SRP_PWD_ENTRY * entry) +{ + _gnutls_free_key_datum(&entry->v); + _gnutls_free_datum(&entry->salt); + + if ((entry->g.data != gnutls_srp_1024_group_generator.data) && + (entry->g.data != gnutls_srp_1536_group_generator.data) && + (entry->g.data != gnutls_srp_2048_group_generator.data) && + (entry->g.data != gnutls_srp_3072_group_generator.data) && + (entry->g.data != gnutls_srp_4096_group_generator.data) && + (entry->g.data != gnutls_srp_8192_group_generator.data)) + _gnutls_free_datum(&entry->g); + + if (entry->n.data != gnutls_srp_1024_group_prime.data && + entry->n.data != gnutls_srp_1536_group_prime.data && + entry->n.data != gnutls_srp_2048_group_prime.data && + entry->n.data != gnutls_srp_3072_group_prime.data && + entry->n.data != gnutls_srp_4096_group_prime.data && + entry->n.data != gnutls_srp_8192_group_prime.data) + _gnutls_free_datum(&entry->n); + + gnutls_free(entry->username); + gnutls_free(entry); +} + +#endif /* ENABLE SRP */ diff --git a/lib/auth/srp_passwd.h b/lib/auth/srp_passwd.h new file mode 100644 index 0000000..56ecec2 --- /dev/null +++ b/lib/auth/srp_passwd.h @@ -0,0 +1,46 @@ +/* + * 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_AUTH_SRP_PASSWD_H +#define GNUTLS_LIB_AUTH_SRP_PASSWD_H + +#ifdef ENABLE_SRP + +typedef struct { + char *username; + + gnutls_datum_t salt; + gnutls_datum_t v; + gnutls_datum_t g; + gnutls_datum_t n; +} SRP_PWD_ENTRY; + +/* this is locally allocated. It should be freed using the provided function */ +int _gnutls_srp_pwd_read_entry(gnutls_session_t state, char *username, + SRP_PWD_ENTRY **); +void _gnutls_srp_entry_free(SRP_PWD_ENTRY * entry); +int _gnutls_sbase64_decode(char *data, size_t data_size, + uint8_t ** result); + +#endif /* ENABLE_SRP */ + +#endif /* GNUTLS_LIB_AUTH_SRP_PASSWD_H */ diff --git a/lib/auth/srp_rsa.c b/lib/auth/srp_rsa.c new file mode 100644 index 0000000..2627189 --- /dev/null +++ b/lib/auth/srp_rsa.c @@ -0,0 +1,265 @@ +/* + * 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" + +#ifdef ENABLE_SRP + +#include "errors.h" +#include <auth/srp_passwd.h> +#include "auth.h" +#include "auth.h" +#include "srp.h" +#include "debug.h" +#include "num.h" +#include <auth/srp_kx.h> +#include <str.h> +#include <auth/cert.h> +#include <datum.h> +#include <tls-sig.h> +#include <x509.h> +#include <algorithms.h> + +static int gen_srp_cert_server_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_srp_cert_server_kx(gnutls_session_t, uint8_t *, size_t); + +const mod_auth_st srp_rsa_auth_struct = { + "SRP", + _gnutls_gen_cert_server_crt, + NULL, + gen_srp_cert_server_kx, + _gnutls_gen_srp_client_kx, + NULL, + NULL, + + _gnutls_proc_crt, + NULL, /* certificate */ + proc_srp_cert_server_kx, + _gnutls_proc_srp_client_kx, + NULL, + NULL +}; + +const mod_auth_st srp_dss_auth_struct = { + "SRP", + _gnutls_gen_cert_server_crt, + NULL, + gen_srp_cert_server_kx, + _gnutls_gen_srp_client_kx, + NULL, + NULL, + + _gnutls_proc_crt, + NULL, /* certificate */ + proc_srp_cert_server_kx, + _gnutls_proc_srp_client_kx, + NULL, + NULL +}; + +static int +gen_srp_cert_server_kx(gnutls_session_t session, gnutls_buffer_st * data) +{ + ssize_t ret; + gnutls_datum_t signature, ddata; + gnutls_certificate_credentials_t cred; + gnutls_pcert_st *apr_cert_list; + gnutls_privkey_t apr_pkey; + int apr_cert_list_length; + gnutls_sign_algorithm_t sign_algo; + const version_entry_st *ver = get_version(session); + unsigned init_pos; + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + init_pos = data->length; + + ret = _gnutls_gen_srp_server_kx(session, data); + + if (ret < 0) + return ret; + + ddata.data = &data->data[init_pos]; + ddata.size = data->length-init_pos; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + /* find the appropriate certificate */ + if ((ret = + _gnutls_get_selected_cert(session, &apr_cert_list, + &apr_cert_list_length, + &apr_pkey)) < 0) { + gnutls_assert(); + return ret; + } + + if ((ret = + _gnutls_handshake_sign_data(session, &apr_cert_list[0], + apr_pkey, &ddata, &signature, + &sign_algo)) < 0) { + gnutls_assert(); + return ret; + } + + if (_gnutls_version_has_selectable_sighash(ver)) { + const sign_algorithm_st *aid; + uint8_t p[2]; + + if (sign_algo == GNUTLS_SIGN_UNKNOWN) { + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; + } + + aid = _gnutls_sign_to_tls_aid(sign_algo); + if (aid == NULL) { + gnutls_assert(); + ret = GNUTLS_E_UNKNOWN_ALGORITHM; + goto cleanup; + } + + p[0] = aid->id[0]; + p[1] = aid->id[1]; + + ret = _gnutls_buffer_append_data(data, p, 2); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + ret = + _gnutls_buffer_append_data_prefix(data, 16, signature.data, + signature.size); + + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length - init_pos; + + cleanup: + _gnutls_free_datum(&signature); + return ret; +} + +static int +proc_srp_cert_server_kx(gnutls_session_t session, uint8_t * data, + size_t _data_size) +{ + ssize_t ret; + int sigsize; + gnutls_datum_t vparams, signature; + ssize_t data_size; + cert_auth_info_t info; + gnutls_pcert_st peer_cert; + uint8_t *p; + gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; + gnutls_certificate_credentials_t cred; + unsigned vflags; + const version_entry_st *ver = get_version(session); + + if (unlikely(ver == NULL)) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = _gnutls_proc_srp_server_kx(session, data, _data_size); + if (ret < 0) + return ret; + + data_size = _data_size - ret; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) { + gnutls_assert(); + return GNUTLS_E_INSUFFICIENT_CREDENTIALS; + } + + vflags = cred->verify_flags | session->internals.additional_verify_flags; + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + if (info == NULL || info->ncerts == 0) { + gnutls_assert(); + /* we need this in order to get peer's certificate */ + return GNUTLS_E_INTERNAL_ERROR; + } + + /* VERIFY SIGNATURE */ + + vparams.size = ret; /* all the data minus the signature */ + vparams.data = data; + + p = &data[vparams.size]; + if (_gnutls_version_has_selectable_sighash(ver)) { + uint8_t id[2]; + + DECR_LEN(data_size, 1); + id[0] = *p++; + DECR_LEN(data_size, 1); + id[1] = *p++; + + sign_algo = _gnutls_tls_aid_to_sign(id[0], id[1], ver); + if (sign_algo == GNUTLS_SIGN_UNKNOWN) { + _gnutls_debug_log("unknown signature %d.%d\n", + (int)id[0], (int)id[1]); + gnutls_assert(); + return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; + } + } + + DECR_LEN(data_size, 2); + sigsize = _gnutls_read_uint16(p); + + DECR_LEN(data_size, sigsize); + signature.data = &p[2]; + signature.size = sigsize; + + ret = + _gnutls_get_auth_info_pcert(&peer_cert, + session->security_parameters.server_ctype, info); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_handshake_verify_data(session, vflags, &peer_cert, &vparams, + &signature, sign_algo); + + gnutls_pcert_deinit(&peer_cert); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + + +#endif /* ENABLE_SRP */ diff --git a/lib/auth/srp_sb64.c b/lib/auth/srp_sb64.c new file mode 100644 index 0000000..16945e9 --- /dev/null +++ b/lib/auth/srp_sb64.c @@ -0,0 +1,453 @@ +/* + * 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 "errors.h" +#include <datum.h> +#include <auth/srp_passwd.h> + +#ifdef ENABLE_SRP + +/* this is a modified base64 for srp !!! + * It seems that everybody makes their own base64 conversion. + */ +static const uint8_t b64table[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; + +static const uint8_t asciitable[128] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3e, 0x3f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, + 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, + 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, + 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, + 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, + 0xff, 0xff +}; + +inline static int encode(uint8_t * result, const uint8_t * rdata, unsigned left) +{ + + int data_len; + int c, ret = 4; + uint8_t data[3]; + + if (left > 3) + data_len = 3; + else + data_len = left; + + data[0] = data[1] = data[2] = 0; + memcpy(data, rdata, data_len); + + switch (data_len) { + case 3: + result[0] = b64table[((data[0] & 0xfc) >> 2)]; + result[1] = + b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) | + ((data[1] & 0xf0) >> 4))]; + result[2] = + b64table[((((data[1] & 0x0f) << 2) & 0xff) | + ((data[2] & 0xc0) >> 6))]; + result[3] = b64table[(data[2] & 0x3f) & 0xff]; + break; + case 2: + if ((c = ((data[0] & 0xf0) >> 4)) != 0) { + result[0] = b64table[c]; + result[1] = + b64table[((((data[0] & 0x0f) << 2) & 0xff) | + ((data[1] & 0xc0) >> 6))]; + result[2] = b64table[(data[1] & 0x3f) & 0xff]; + result[3] = '\0'; + ret -= 1; + } else { + if ((c = + ((data[0] & 0x0f) << 2) | ((data[1] & 0xc0) >> + 6)) != 0) { + result[0] = b64table[c]; + result[1] = b64table[data[1] & 0x3f]; + result[2] = '\0'; + result[3] = '\0'; + ret -= 2; + } else { + result[0] = b64table[data[0] & 0x3f]; + result[1] = '\0'; + result[2] = '\0'; + result[3] = '\0'; + ret -= 3; + } + } + break; + case 1: + if ((c = ((data[0] & 0xc0) >> 6)) != 0) { + result[0] = b64table[c]; + result[1] = b64table[(data[0] & 0x3f) & 0xff]; + result[2] = '\0'; + result[3] = '\0'; + ret -= 2; + } else { + result[0] = b64table[(data[0] & 0x3f) & 0xff]; + result[1] = '\0'; + result[2] = '\0'; + result[3] = '\0'; + ret -= 3; + } + break; + default: + return GNUTLS_E_BASE64_ENCODING_ERROR; + } + + return ret; + +} + +/* encodes data and puts the result into result (locally allocated) + * The result_size is the return value + */ +static int +_gnutls_sbase64_encode(uint8_t * data, size_t data_size, char **result) +{ + unsigned i, j; + int ret, tmp; + uint8_t tmpres[4]; + unsigned mod = data_size % 3; + + ret = mod; + if (ret != 0) + ret = 4; + else + ret = 0; + + ret += (data_size * 4) / 3; + + (*result) = gnutls_calloc(1, ret + 1); + if ((*result) == NULL) + return GNUTLS_E_MEMORY_ERROR; + + i = j = 0; +/* encode the bytes that are not a multiple of 3 + */ + if (mod > 0) { + tmp = encode(tmpres, &data[0], mod); + if (tmp < 0) { + gnutls_free((*result)); + return tmp; + } + + memcpy(&(*result)[0], tmpres, tmp); + i = mod; + j = tmp; + + } +/* encode the rest + */ + for (; i < data_size; i += 3, j += 4) { + tmp = encode(tmpres, &data[i], data_size - i); + if (tmp < 0) { + gnutls_free((*result)); + return tmp; + } + memcpy(&(*result)[j], tmpres, tmp); + } + + return strlen(*result); +} + + +/* data must be 4 bytes + * result should be 3 bytes + */ +#define TOASCII(c) (c < 127 ? asciitable[c] : 0xff) +inline static int decode(uint8_t * result, const uint8_t * data) +{ + uint8_t a1, a2; + int ret = 3; + + memset(result, 0, 3); + + a1 = TOASCII(data[3]); + a2 = TOASCII(data[2]); + if (a1 != 0xff) + result[2] = a1 & 0xff; + else + return GNUTLS_E_BASE64_DECODING_ERROR; + if (a2 != 0xff) + result[2] |= ((a2 & 0x03) << 6) & 0xff; + + a1 = a2; + a2 = TOASCII(data[1]); + if (a1 != 0xff) + result[1] = ((a1 & 0x3c) >> 2); + if (a2 != 0xff) + result[1] |= ((a2 & 0x0f) << 4); + else if (a1 == 0xff || result[1] == 0) + ret--; + + a1 = a2; + a2 = TOASCII(data[0]); + if (a1 != 0xff) + result[0] = (((a1 & 0x30) >> 4) & 0xff); + if (a2 != 0xff) + result[0] |= ((a2 << 2) & 0xff); + else if (a1 == 0xff || result[0] == 0) + ret--; + + return ret; +} + +/* decodes data and puts the result into result (locally allocated) + * The result_size is the return value. + * That function does not ignore newlines tabs etc. You should remove them + * before calling it. + */ +int +_gnutls_sbase64_decode(char *data, size_t idata_size, uint8_t ** result) +{ + unsigned i, j; + int ret, left; + int data_size, tmp; + uint8_t datrev[4]; + uint8_t tmpres[3]; + + data_size = (idata_size / 4) * 4; + left = idata_size % 4; + + ret = (data_size / 4) * 3; + + if (left > 0) + ret += 3; + + (*result) = gnutls_malloc(ret + 1); + if ((*result) == NULL) + return GNUTLS_E_MEMORY_ERROR; + + /* the first "block" is treated with special care */ + tmp = 0; + if (left > 0) { + memset(datrev, 0, 4); + memcpy(&datrev[4 - left], data, left); + + tmp = decode(tmpres, datrev); + if (tmp < 0) { + gnutls_free((*result)); + return tmp; + } + + memcpy(*result, &tmpres[3 - tmp], tmp); + if (tmp < 3) + ret -= (3 - tmp); + } + + /* rest data */ + for (i = left, j = tmp; i < idata_size; i += 4) { + tmp = decode(tmpres, (uint8_t *) & data[i]); + if (tmp < 0) { + gnutls_free((*result)); + return tmp; + } + memcpy(&(*result)[j], tmpres, tmp); + if (tmp < 3) + ret -= (3 - tmp); + j += 3; + } + + return ret; +} + +/** + * gnutls_srp_base64_encode: + * @data: contain the raw data + * @result: the place where base64 data will be copied + * @result_size: holds the size of the result + * + * This function will convert the given data to printable data, using + * the base64 encoding, as used in the libsrp. This is the encoding + * used in SRP password files. If the provided buffer is not long + * enough GNUTLS_E_SHORT_MEMORY_BUFFER is returned. + * + * Warning! This base64 encoding is not the "standard" encoding, so + * do not use it for non-SRP purposes. + * + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not + * long enough, or 0 on success. + **/ +int +gnutls_srp_base64_encode(const gnutls_datum_t * data, char *result, + size_t * result_size) +{ + char *res; + int size; + + size = _gnutls_sbase64_encode(data->data, data->size, &res); + if (size < 0) + return size; + + if (result == NULL || *result_size < (size_t) size) { + gnutls_free(res); + *result_size = size; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } else { + memcpy(result, res, size); + gnutls_free(res); + *result_size = size; + } + + return 0; +} + +/** + * gnutls_srp_base64_encode2: + * @data: contains the raw data + * @result: will hold the newly allocated encoded data + * + * This function will convert the given data to printable data, using + * the base64 encoding. This is the encoding used in SRP password + * files. This function will allocate the required memory to hold + * the encoded data. + * + * You should use gnutls_free() to free the returned data. + * + * Warning! This base64 encoding is not the "standard" encoding, so + * do not use it for non-SRP purposes. + * + * Returns: 0 on success, or an error code. + **/ +int +gnutls_srp_base64_encode2(const gnutls_datum_t * data, + gnutls_datum_t * result) +{ + char *res; + int size; + + size = _gnutls_sbase64_encode(data->data, data->size, &res); + if (size < 0) + return size; + + if (result == NULL) { + gnutls_free(res); + return GNUTLS_E_INVALID_REQUEST; + } else { + result->data = (uint8_t *) res; + result->size = size; + } + + return 0; +} + +/** + * gnutls_srp_base64_decode: + * @b64_data: contain the encoded data + * @result: the place where decoded data will be copied + * @result_size: holds the size of the result + * + * This function will decode the given encoded data, using the base64 + * encoding found in libsrp. + * + * Note that @b64_data should be null terminated. + * + * Warning! This base64 encoding is not the "standard" encoding, so + * do not use it for non-SRP purposes. + * + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not + * long enough, or 0 on success. + **/ +int +gnutls_srp_base64_decode(const gnutls_datum_t * b64_data, char *result, + size_t * result_size) +{ + uint8_t *res; + int size; + + size = + _gnutls_sbase64_decode((char *) b64_data->data, b64_data->size, + &res); + if (size < 0) + return size; + + if (result == NULL || *result_size < (size_t) size) { + gnutls_free(res); + *result_size = size; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } else { + memcpy(result, res, size); + gnutls_free(res); + *result_size = size; + } + + return 0; +} + +/** + * gnutls_srp_base64_decode2: + * @b64_data: contains the encoded data + * @result: the place where decoded data lie + * + * This function will decode the given encoded data. The decoded data + * will be allocated, and stored into result. It will decode using + * the base64 algorithm as used in libsrp. + * + * You should use gnutls_free() to free the returned data. + * + * Warning! This base64 encoding is not the "standard" encoding, so + * do not use it for non-SRP purposes. + * + * Returns: 0 on success, or an error code. + **/ +int +gnutls_srp_base64_decode2(const gnutls_datum_t * b64_data, + gnutls_datum_t * result) +{ + uint8_t *ret; + int size; + + size = + _gnutls_sbase64_decode((char *) b64_data->data, b64_data->size, + &ret); + if (size < 0) + return size; + + if (result == NULL) { + gnutls_free(ret); + return GNUTLS_E_INVALID_REQUEST; + } else { + result->data = ret; + result->size = size; + } + + return 0; +} + +#endif /* ENABLE_SRP */ diff --git a/lib/auth/vko_gost.c b/lib/auth/vko_gost.c new file mode 100644 index 0000000..7654202 --- /dev/null +++ b/lib/auth/vko_gost.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2011-2012 Free Software Foundation, Inc. + * Copyright (C) 2016 Dmitry Eremin-Solenikov + * + * 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 <http://www.gnu.org/licenses/> + * + */ + +#include "gnutls_int.h" +#include "auth.h" +#include "errors.h" +#include "vko.h" +#include <state.h> +#include <datum.h> +#include <ext/signature.h> +#include <ext/supported_groups.h> +#include <auth/cert.h> +#include <pk.h> +#include <abstract_int.h> + +#if defined(ENABLE_GOST) +static int gen_vko_gost_client_kx(gnutls_session_t, gnutls_buffer_st *); +static int proc_vko_gost_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size); + +/* VKO GOST Key Exchange: + * see draft-smyshlyaev-tls12-gost-suites-06, Section 4.2.4 + * + * Client generates ephemeral key pair, uses server's public key (from + * certificate), ephemeral private key and additional nonce (UKM) to generate + * (VKO) shared point/shared secret. This secret is used to encrypt (key wrap) + * random PMS. Then encrypted PMS and client's ephemeral public key are wrappen + * in ASN.1 structure and sent in KX message. + * + * Server uses decodes ASN.1 structure and uses its own private key and + * client's ephemeral public key to unwrap PMS. + * + * Note, this KX is not PFS one, despite using ephemeral key pairs on client + * side. + */ +const mod_auth_st vko_gost_auth_struct = { + "VKO_GOST", + _gnutls_gen_cert_server_crt, + _gnutls_gen_cert_client_crt, + NULL, + gen_vko_gost_client_kx, + _gnutls_gen_cert_client_crt_vrfy, + _gnutls_gen_cert_server_cert_req, + + _gnutls_proc_crt, + _gnutls_proc_crt, + NULL, + proc_vko_gost_client_kx, + _gnutls_proc_cert_client_crt_vrfy, + _gnutls_proc_cert_cert_req +}; + +#define VKO_GOST_UKM_LEN 8 + +static int +calc_ukm(gnutls_session_t session, uint8_t *ukm) +{ + gnutls_digest_algorithm_t digalg = GNUTLS_DIG_STREEBOG_256; + gnutls_hash_hd_t dig; + int ret; + + ret = gnutls_hash_init(&dig, digalg); + if (ret < 0) + return gnutls_assert_val(ret); + + gnutls_hash(dig, session->security_parameters.client_random, + sizeof(session->security_parameters.client_random)); + + gnutls_hash(dig, session->security_parameters.server_random, + sizeof(session->security_parameters.server_random)); + + gnutls_hash_deinit(dig, ukm); + + return gnutls_hash_get_len(digalg); +} + +static int print_priv_key(gnutls_pk_params_st *params) +{ + int ret; + uint8_t priv_buf[512/8]; + char buf[512 / 4 + 1]; + size_t bytes = sizeof(priv_buf); + + /* Check if _gnutls_hard_log will print anything */ + if (likely(_gnutls_log_level < 9)) + return GNUTLS_E_SUCCESS; + + ret = _gnutls_mpi_print(params->params[GOST_K], + priv_buf, &bytes); + if (ret < 0) + return gnutls_assert_val(ret); + + _gnutls_hard_log("INT: VKO PRIVATE KEY[%zd]: %s\n", + bytes, _gnutls_bin2hex(priv_buf, + bytes, + buf, sizeof(buf), + NULL)); + return 0; +} + +static int +vko_prepare_client_keys(gnutls_session_t session, + gnutls_pk_params_st *pub, + gnutls_pk_params_st *priv) +{ + int ret; + gnutls_ecc_curve_t curve; + const gnutls_group_entry_st *group; + cert_auth_info_t info; + gnutls_pcert_st peer_cert; + + info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + if (info == NULL || info->ncerts == 0) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + + ret = _gnutls_get_auth_info_pcert(&peer_cert, + session->security_parameters. + server_ctype, info); + if (ret < 0) + return gnutls_assert_val(ret); + + /* Copy public key contents and free the rest */ + memcpy(pub, &peer_cert.pubkey->params, sizeof(gnutls_pk_params_st)); + gnutls_free(peer_cert.pubkey); + peer_cert.pubkey = NULL; + gnutls_pcert_deinit(&peer_cert); + + curve = pub->curve; + group = _gnutls_id_to_group(_gnutls_ecc_curve_get_group(curve)); + if (group == NULL) { + _gnutls_debug_log("received unknown curve %d\n", curve); + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + } else { + _gnutls_debug_log("received curve %s\n", group->name); + } + + ret = _gnutls_session_supports_group(session, group->id); + if (ret < 0) + return gnutls_assert_val(ret); + + if (pub->algo == GNUTLS_PK_GOST_12_512) { + gnutls_sign_algorithm_set_server(session, GNUTLS_SIGN_GOST_512); + } else { + gnutls_sign_algorithm_set_server(session, GNUTLS_SIGN_GOST_256); + } + + _gnutls_session_group_set(session, group); + + ret = _gnutls_pk_generate_keys(pub->algo, + curve, + priv, 1); + if (ret < 0) + return gnutls_assert_val(ret); + + priv->gost_params = pub->gost_params; + + print_priv_key(priv); + + session->key.key.size = 32; /* GOST key size */ + session->key.key.data = gnutls_malloc(session->key.key.size); + if (session->key.key.data == NULL) { + gnutls_assert(); + session->key.key.size = 0; + return GNUTLS_E_MEMORY_ERROR; + } + + /* Generate random */ + ret = gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data, + session->key.key.size); + if (ret < 0) { + gnutls_assert(); + gnutls_free(session->key.key.data); + session->key.key.size = 0; + return ret; + } + + return 0; +} + +/* KX message is: + TLSGostKeyTransportBlob ::= SEQUENCE { + keyBlob GostR3410-KeyTransport, + proxyKeyBlobs SEQUENCE OF TLSProxyKeyTransportBlob OPTIONAL + } + + draft-smyshlyaev-tls12-gost-suites does not define proxyKeyBlobs, but old + CSPs still send additional information after keyBlob. + + We only need keyBlob and we completely ignore the rest of the structure. + + _gnutls_gost_keytrans_decrypt will decrypt GostR3410-KeyTransport + */ + +static int +proc_vko_gost_client_kx(gnutls_session_t session, + uint8_t * data, size_t _data_size) +{ + int ret, i = 0; + ssize_t data_size = _data_size; + gnutls_privkey_t privkey = session->internals.selected_key; + uint8_t ukm_data[MAX_HASH_SIZE]; + gnutls_datum_t ukm = {ukm_data, VKO_GOST_UKM_LEN}; + gnutls_datum_t cek; + int len; + + if (!privkey || privkey->type != GNUTLS_PRIVKEY_X509) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + /* Skip TLSGostKeyTransportBlob tag and length */ + DECR_LEN(data_size, 1); + if (data[0] != (ASN1_TAG_SEQUENCE | ASN1_CLASS_STRUCTURED)) + return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + i += 1; + + ret = asn1_get_length_der(&data[i], data_size, &len); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_ASN1_DER_ERROR); + DECR_LEN(data_size, len); + i += len; + + /* Check that nothing is left after TLSGostKeyTransportBlob */ + DECR_LEN_FINAL(data_size, ret); + + /* Point data to GostR3410-KeyTransport */ + data_size = ret; + data += i; + + /* Now do the tricky part: determine length of GostR3410-KeyTransport */ + DECR_LEN(data_size, 1); /* tag */ + ret = asn1_get_length_der(&data[1], data_size, &len); + DECR_LEN_FINAL(data_size, len + ret); + + cek.data = data; + cek.size = ret + len + 1; + + ret = calc_ukm(session, ukm_data); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_gost_keytrans_decrypt(&privkey->key.x509->params, + &cek, &ukm, + &session->key.key); + if (ret < 0) + return gnutls_assert_val(ret); + + return 0; +} + +static int +gen_vko_gost_client_kx(gnutls_session_t session, + gnutls_buffer_st * data) +{ + int ret; + gnutls_datum_t out = {}; + uint8_t ukm_data[MAX_HASH_SIZE]; + gnutls_datum_t ukm = {ukm_data, VKO_GOST_UKM_LEN}; + gnutls_pk_params_st pub; + gnutls_pk_params_st priv; + uint8_t tl[1 + ASN1_MAX_LENGTH_SIZE]; + int len; + + ret = calc_ukm(session, ukm_data); + if (ret < 0) + return gnutls_assert_val(ret); + + gnutls_pk_params_init(&pub); + gnutls_pk_params_init(&priv); + ret = vko_prepare_client_keys(session, &pub, &priv); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_gost_keytrans_encrypt(&pub, + &priv, + &session->key.key, + &ukm, &out); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + tl[0] = ASN1_TAG_SEQUENCE | ASN1_CLASS_STRUCTURED; + asn1_length_der(out.size, tl + 1, &len); + ret = gnutls_buffer_append_data(data, tl, len + 1); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = gnutls_buffer_append_data(data, out.data, out.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = data->length; + cleanup: + /* no longer needed */ + gnutls_pk_params_release(&priv); + gnutls_pk_params_release(&pub); + + _gnutls_free_datum(&out); + + return ret; +} +#endif |