summaryrefslogtreecommitdiffstats
path: root/lib/auth
diff options
context:
space:
mode:
Diffstat (limited to 'lib/auth')
-rw-r--r--lib/auth/Makefile.am41
-rw-r--r--lib/auth/Makefile.in2447
-rw-r--r--lib/auth/anon.c131
-rw-r--r--lib/auth/anon.h52
-rw-r--r--lib/auth/anon_ecdh.c139
-rw-r--r--lib/auth/cert.c1914
-rw-r--r--lib/auth/cert.h189
-rw-r--r--lib/auth/dh_common.c379
-rw-r--r--lib/auth/dh_common.h50
-rw-r--r--lib/auth/dhe.c152
-rw-r--r--lib/auth/dhe_psk.c506
-rw-r--r--lib/auth/ecdhe.c522
-rw-r--r--lib/auth/ecdhe.h52
-rw-r--r--lib/auth/psk.c334
-rw-r--r--lib/auth/psk.h110
-rw-r--r--lib/auth/psk_passwd.c273
-rw-r--r--lib/auth/psk_passwd.h36
-rw-r--r--lib/auth/rsa.c316
-rw-r--r--lib/auth/rsa_common.h39
-rw-r--r--lib/auth/rsa_psk.c436
-rw-r--r--lib/auth/srp_kx.c1021
-rw-r--r--lib/auth/srp_kx.h74
-rw-r--r--lib/auth/srp_passwd.c470
-rw-r--r--lib/auth/srp_passwd.h46
-rw-r--r--lib/auth/srp_rsa.c265
-rw-r--r--lib/auth/srp_sb64.c453
-rw-r--r--lib/auth/vko_gost.c323
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, &params)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret =
+ _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key,
+ &params);
+
+ gnutls_pk_params_release(&params);
+
+ 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, &params)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ /* Encrypt premaster secret */
+ if ((ret =
+ _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &premaster_secret,
+ &params)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ gnutls_pk_params_release(&params);
+
+ 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