diff --git a/configure.ac b/configure.ac
index 4d4fb49a..57884162 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,3010 +1,3009 @@
# Configure.ac script for Libgcrypt
# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
# 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
# Copyright (C) 2012-2017 g10 Code GmbH
#
# This file is part of Libgcrypt.
#
# Libgcrypt 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.
#
# Libgcrypt 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 .
# (Process this file with autoconf to produce a configure script.)
AC_REVISION($Revision$)
AC_PREREQ(2.60)
min_automake_version="1.14"
# To build a release you need to create a tag with the version number
# (git tag -s libgcrypt-n.m.k) and run "./autogen.sh --force". Please
# bump the version number immediately after the release and do another
# commit and push so that the git magic is able to work. See below
# for the LT versions.
m4_define([mym4_package],[libgcrypt])
m4_define([mym4_major], [1])
m4_define([mym4_minor], [9])
m4_define([mym4_micro], [0])
# Below is m4 magic to extract and compute the git revision number,
# the decimalized short revision number, a beta version string and a
# flag indicating a development version (mym4_isbeta). Note that the
# m4 processing is done by autoconf and not during the configure run.
m4_define([mym4_verslist], m4_split(m4_esyscmd([./autogen.sh --find-version] \
mym4_package mym4_major mym4_minor mym4_micro),[:]))
m4_define([mym4_isbeta], m4_argn(2, mym4_verslist))
m4_define([mym4_version], m4_argn(4, mym4_verslist))
m4_define([mym4_revision], m4_argn(7, mym4_verslist))
m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist))
m4_esyscmd([echo ]mym4_version[>VERSION])
AC_INIT([mym4_package],[mym4_version], [https://bugs.gnupg.org])
# LT Version numbers, remember to change them just *before* a release.
# (Code changed: REVISION++)
# (Interfaces added/removed/changed: CURRENT++, REVISION=0)
# (Interfaces added: AGE++)
# (Interfaces removed: AGE=0)
#
# (Interfaces removed: CURRENT++, AGE=0, REVISION=0)
# (Interfaces added: CURRENT++, AGE++, REVISION=0)
# (No interfaces changed: REVISION++)
LIBGCRYPT_LT_CURRENT=23
LIBGCRYPT_LT_AGE=3
LIBGCRYPT_LT_REVISION=0
################################################
AC_SUBST(LIBGCRYPT_LT_CURRENT)
AC_SUBST(LIBGCRYPT_LT_AGE)
AC_SUBST(LIBGCRYPT_LT_REVISION)
# If the API is changed in an incompatible way: increment the next counter.
#
# 1.6: ABI and API change but the change is to most users irrelevant
# and thus the API version number has not been incremented.
LIBGCRYPT_CONFIG_API_VERSION=1
# If you change the required gpg-error version, please remove
# unnecessary error code defines in src/gcrypt-int.h.
NEED_GPG_ERROR_VERSION=1.27
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR([src/libgcrypt.vers])
AM_INIT_AUTOMAKE([serial-tests dist-bzip2])
AC_CONFIG_HEADER(config.h)
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_LIBOBJ_DIR([compat])
AC_CANONICAL_HOST
AM_MAINTAINER_MODE
AM_SILENT_RULES
AC_ARG_VAR(SYSROOT,[locate config scripts also below that directory])
AH_TOP([
#ifndef _GCRYPT_CONFIG_H_INCLUDED
#define _GCRYPT_CONFIG_H_INCLUDED
/* Enable gpg-error's strerror macro for W32CE. */
#define GPG_ERR_ENABLE_ERRNO_MACROS 1
])
AH_BOTTOM([
#define _GCRYPT_IN_LIBGCRYPT 1
/* If the configure check for endianness has been disabled, get it from
OS macros. This is intended for making fat binary builds on OS X. */
#ifdef DISABLED_ENDIAN_CHECK
# if defined(__BIG_ENDIAN__)
# define WORDS_BIGENDIAN 1
# elif defined(__LITTLE_ENDIAN__)
# undef WORDS_BIGENDIAN
# else
# error "No endianness found"
# endif
#endif /*DISABLED_ENDIAN_CHECK*/
/* We basically use the original Camellia source. Make sure the symbols
properly prefixed. */
#define CAMELLIA_EXT_SYM_PREFIX _gcry_
#endif /*_GCRYPT_CONFIG_H_INCLUDED*/
])
AH_VERBATIM([_REENTRANT],
[/* To allow the use of Libgcrypt in multithreaded programs we have to use
special features from the library. */
#ifndef _REENTRANT
# define _REENTRANT 1
#endif
])
######################
## Basic checks. ### (we need some results later on (e.g. $GCC)
######################
AC_PROG_MAKE_SET
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
# AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_PROG_CC
AC_PROG_CPP
AM_PROG_CC_C_O
AM_PROG_AS
AC_ISC_POSIX
AC_PROG_INSTALL
AC_PROG_AWK
AC_GNU_SOURCE
# Taken from mpfr-4.0.1, then modified for LDADD_FOR_TESTS_KLUDGE
dnl Under Linux, make sure that the old dtags are used if LD_LIBRARY_PATH
dnl is defined. The issue is that with the new dtags, LD_LIBRARY_PATH has
dnl the precedence over the run path, so that if a compatible MPFR library
dnl is installed in some directory from $LD_LIBRARY_PATH, then the tested
dnl MPFR library will be this library instead of the MPFR library from the
dnl build tree. Other OS with the same issue might be added later.
dnl
dnl References:
dnl https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859732
dnl http://lists.gnu.org/archive/html/libtool/2017-05/msg00000.html
dnl
dnl We need to check whether --disable-new-dtags is supported as alternate
dnl linkers may be used (e.g., with tcc: CC=tcc LD=tcc).
dnl
case $host in
*-*-linux*)
if test -n "$LD_LIBRARY_PATH"; then
saved_LDFLAGS="$LDFLAGS"
LDADD_FOR_TESTS_KLUDGE="-Wl,--disable-new-dtags"
LDFLAGS="$LDFLAGS $LDADD_FOR_TESTS_KLUDGE"
AC_MSG_CHECKING(whether --disable-new-dtags is supported by the linker)
AC_LINK_IFELSE([AC_LANG_SOURCE([[
int main (void) { return 0; }
]])],
[AC_MSG_RESULT(yes (use it since LD_LIBRARY_PATH is set))],
[AC_MSG_RESULT(no)
LDADD_FOR_TESTS_KLUDGE=""
])
LDFLAGS="$saved_LDFLAGS"
fi
;;
esac
AC_SUBST([LDADD_FOR_TESTS_KLUDGE])
VERSION_NUMBER=m4_esyscmd(printf "0x%02x%02x%02x" mym4_major \
mym4_minor mym4_micro)
AC_SUBST(VERSION_NUMBER)
# We need to compile and run a program on the build machine.
AX_CC_FOR_BUILD
LT_PREREQ([2.2.6])
LT_INIT([win32-dll disable-static])
LT_LANG([Windows Resource])
##########################
## General definitions. ##
##########################
# Used by libgcrypt-config
LIBGCRYPT_CONFIG_LIBS="-lgcrypt"
LIBGCRYPT_CONFIG_CFLAGS=""
LIBGCRYPT_CONFIG_HOST="$host"
# Definitions for symmetric ciphers.
available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268 seed"
available_ciphers="$available_ciphers camellia idea salsa20 gost28147 chacha20"
enabled_ciphers=""
# Definitions for public-key ciphers.
available_pubkey_ciphers="dsa elgamal rsa ecc"
enabled_pubkey_ciphers=""
# Definitions for message digests.
available_digests="crc gostr3411-94 md2 md4 md5 rmd160 sha1 sha256 sha512"
available_digests="$available_digests sha3 tiger whirlpool stribog blake2"
available_digests="$available_digests sm3"
enabled_digests=""
# Definitions for kdfs (optional ones)
available_kdfs="s2k pkdf2 scrypt"
enabled_kdfs=""
# Definitions for random modules.
available_random_modules="linux egd unix"
auto_random_modules="$available_random_modules"
# Supported thread backends.
LIBGCRYPT_THREAD_MODULES=""
# Other definitions.
have_w32_system=no
have_w32ce_system=no
have_pthread=no
# Setup some stuff depending on host.
case "${host}" in
*-*-mingw32*)
ac_cv_have_dev_random=no
have_w32_system=yes
case "${host}" in
*-mingw32ce*)
have_w32ce_system=yes
available_random_modules="w32ce"
;;
*)
available_random_modules="w32"
;;
esac
AC_DEFINE(USE_ONLY_8DOT3,1,
[set this to limit filenames to the 8.3 format])
AC_DEFINE(HAVE_DRIVE_LETTERS,1,
[defined if we must run on a stupid file system])
AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
[defined if we run on some of the PCDOS like systems
(DOS, Windoze. OS/2) with special properties like
no file modes])
;;
i?86-emx-os2 | i?86-*-os2*emx)
# OS/2 with the EMX environment
ac_cv_have_dev_random=no
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
;;
i?86-*-msdosdjgpp*)
# DOS with the DJGPP environment
ac_cv_have_dev_random=no
AC_DEFINE(HAVE_DRIVE_LETTERS)
AC_DEFINE(HAVE_DOSISH_SYSTEM)
;;
*-*-hpux*)
if test -z "$GCC" ; then
CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE"
fi
;;
*-dec-osf4*)
if test -z "$GCC" ; then
# Suppress all warnings
# to get rid of the unsigned/signed char mismatch warnings.
CFLAGS="$CFLAGS -w"
fi
;;
m68k-atari-mint)
;;
*-apple-darwin*)
AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
Expose all libc features (__DARWIN_C_FULL).)
;;
*)
;;
esac
if test "$have_w32_system" = yes; then
AC_DEFINE(HAVE_W32_SYSTEM,1, [Defined if we run on a W32 API based system])
if test "$have_w32ce_system" = yes; then
AC_DEFINE(HAVE_W32CE_SYSTEM,1,[Defined if we run on WindowsCE])
fi
fi
AM_CONDITIONAL(HAVE_W32_SYSTEM, test "$have_w32_system" = yes)
AM_CONDITIONAL(HAVE_W32CE_SYSTEM, test "$have_w32ce_system" = yes)
# A printable OS Name is sometimes useful.
case "${host}" in
*-*-mingw32ce*)
PRINTABLE_OS_NAME="W32CE"
;;
*-*-mingw32*)
PRINTABLE_OS_NAME="W32"
;;
i?86-emx-os2 | i?86-*-os2*emx )
PRINTABLE_OS_NAME="OS/2"
;;
i?86-*-msdosdjgpp*)
PRINTABLE_OS_NAME="MSDOS/DJGPP"
;;
*-linux*)
PRINTABLE_OS_NAME="GNU/Linux"
;;
*)
PRINTABLE_OS_NAME=`uname -s || echo "Unknown"`
;;
esac
NAME_OF_DEV_RANDOM="/dev/random"
NAME_OF_DEV_URANDOM="/dev/urandom"
AC_ARG_ENABLE(endian-check,
AC_HELP_STRING([--disable-endian-check],
[disable the endian check and trust the OS provided macros]),
endiancheck=$enableval,endiancheck=yes)
if test x"$endiancheck" = xyes ; then
AC_C_BIGENDIAN
else
AC_DEFINE(DISABLED_ENDIAN_CHECK,1,[configure did not test for endianness])
fi
AC_CHECK_SIZEOF(unsigned short, 2)
AC_CHECK_SIZEOF(unsigned int, 4)
AC_CHECK_SIZEOF(unsigned long, 4)
AC_CHECK_SIZEOF(unsigned long long, 0)
AC_CHECK_SIZEOF(void *, 0)
AC_TYPE_UINTPTR_T
if test "$ac_cv_sizeof_unsigned_short" = "0" \
|| test "$ac_cv_sizeof_unsigned_int" = "0" \
|| test "$ac_cv_sizeof_unsigned_long" = "0"; then
AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]);
fi
# Ensure that we have UINT64_C before we bother to check for uint64_t
AC_CACHE_CHECK([for UINT64_C],[gnupg_cv_uint64_c_works],
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]],
[[uint64_t foo=UINT64_C(42);]])],
gnupg_cv_uint64_c_works=yes,gnupg_cv_uint64_c_works=no))
if test "$gnupg_cv_uint64_c_works" = "yes" ; then
AC_CHECK_SIZEOF(uint64_t)
fi
# Do we have any 64-bit data types?
if test "$ac_cv_sizeof_unsigned_int" != "8" \
&& test "$ac_cv_sizeof_unsigned_long" != "8" \
&& test "$ac_cv_sizeof_unsigned_long_long" != "8" \
&& test "$ac_cv_sizeof_uint64_t" != "8"; then
AC_MSG_ERROR([[
***
*** No 64-bit integer type available.
*** It is not possible to build Libgcrypt on this platform.
***]])
fi
# If not specified otherwise, all available algorithms will be
# included.
default_ciphers="$available_ciphers"
default_pubkey_ciphers="$available_pubkey_ciphers"
default_digests="$available_digests"
default_kdfs="$available_kdfs"
# Blacklist MD2 by default
default_digests=`echo $default_digests | sed -e 's/md2//g'`
# Substitutions to set generated files in a Emacs buffer to read-only.
AC_SUBST(emacs_local_vars_begin, ['Local Variables:'])
AC_SUBST(emacs_local_vars_read_only, ['buffer-read-only: t'])
AC_SUBST(emacs_local_vars_end, ['End:'])
############################
## Command line switches. ##
############################
# Implementation of the --enable-ciphers switch.
AC_ARG_ENABLE(ciphers,
AC_HELP_STRING([--enable-ciphers=ciphers],
[select the symmetric ciphers to include]),
[enabled_ciphers=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_ciphers=""])
if test "x$enabled_ciphers" = "x" \
-o "$enabled_ciphers" = "yes" \
-o "$enabled_ciphers" = "no"; then
enabled_ciphers=$default_ciphers
fi
AC_MSG_CHECKING([which symmetric ciphers to include])
for cipher in $enabled_ciphers; do
LIST_MEMBER($cipher, $available_ciphers)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported cipher "$cipher" specified])
fi
done
AC_MSG_RESULT([$enabled_ciphers])
# Implementation of the --enable-pubkey-ciphers switch.
AC_ARG_ENABLE(pubkey-ciphers,
AC_HELP_STRING([--enable-pubkey-ciphers=ciphers],
[select the public-key ciphers to include]),
[enabled_pubkey_ciphers=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_pubkey_ciphers=""])
if test "x$enabled_pubkey_ciphers" = "x" \
-o "$enabled_pubkey_ciphers" = "yes" \
-o "$enabled_pubkey_ciphers" = "no"; then
enabled_pubkey_ciphers=$default_pubkey_ciphers
fi
AC_MSG_CHECKING([which public-key ciphers to include])
for cipher in $enabled_pubkey_ciphers; do
LIST_MEMBER($cipher, $available_pubkey_ciphers)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported public-key cipher specified])
fi
done
AC_MSG_RESULT([$enabled_pubkey_ciphers])
# Implementation of the --enable-digests switch.
AC_ARG_ENABLE(digests,
AC_HELP_STRING([--enable-digests=digests],
[select the message digests to include]),
[enabled_digests=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_digests=""])
if test "x$enabled_digests" = "x" \
-o "$enabled_digests" = "yes" \
-o "$enabled_digests" = "no"; then
enabled_digests=$default_digests
fi
AC_MSG_CHECKING([which message digests to include])
for digest in $enabled_digests; do
LIST_MEMBER($digest, $available_digests)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported message digest specified])
fi
done
AC_MSG_RESULT([$enabled_digests])
# Implementation of the --enable-kdfs switch.
AC_ARG_ENABLE(kdfs,
AC_HELP_STRING([--enable-kfds=kdfs],
[select the KDFs to include]),
[enabled_kdfs=`echo $enableval | tr ',:' ' ' | tr '[A-Z]' '[a-z]'`],
[enabled_kdfs=""])
if test "x$enabled_kdfs" = "x" \
-o "$enabled_kdfs" = "yes" \
-o "$enabled_kdfs" = "no"; then
enabled_kdfs=$default_kdfs
fi
AC_MSG_CHECKING([which key derivation functions to include])
for kdf in $enabled_kdfs; do
LIST_MEMBER($kdf, $available_kdfs)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported key derivation function specified])
fi
done
AC_MSG_RESULT([$enabled_kdfs])
# Implementation of the --enable-random switch.
AC_ARG_ENABLE(random,
AC_HELP_STRING([--enable-random=name],
[select which random number generator to use]),
[random=`echo $enableval | tr '[A-Z]' '[a-z]'`],
[])
if test "x$random" = "x" -o "$random" = "yes" -o "$random" = "no"; then
random=default
fi
AC_MSG_CHECKING([which random module to use])
if test "$random" != "default" -a "$random" != "auto"; then
LIST_MEMBER($random, $available_random_modules)
if test "$found" = "0"; then
AC_MSG_ERROR([unsupported random module specified])
fi
fi
AC_MSG_RESULT($random)
# Implementation of the --disable-dev-random switch.
AC_MSG_CHECKING([whether use of /dev/random is requested])
AC_ARG_ENABLE(dev-random,
[ --disable-dev-random disable the use of dev random],
try_dev_random=$enableval, try_dev_random=yes)
AC_MSG_RESULT($try_dev_random)
# Implementation of the --with-egd-socket switch.
AC_ARG_WITH(egd-socket,
[ --with-egd-socket=NAME Use NAME for the EGD socket)],
egd_socket_name="$withval", egd_socket_name="" )
AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name",
[Define if you don't want the default EGD socket name.
For details see cipher/rndegd.c])
# Implementation of the --enable-random-daemon
AC_MSG_CHECKING([whether the experimental random daemon is requested])
AC_ARG_ENABLE([random-daemon],
AC_HELP_STRING([--enable-random-daemon],
[Build and support the experimental gcryptrnd]),
[use_random_daemon=$enableval],
[use_random_daemon=no])
AC_MSG_RESULT($use_random_daemon)
if test x$use_random_daemon = xyes ; then
AC_DEFINE(USE_RANDOM_DAEMON,1,
[Define to support the experimental random daemon])
fi
AM_CONDITIONAL(USE_RANDOM_DAEMON, test x$use_random_daemon = xyes)
# Implementation of --disable-asm.
AC_MSG_CHECKING([whether MPI assembler modules are requested])
AC_ARG_ENABLE([asm],
AC_HELP_STRING([--disable-asm],
[Disable MPI assembler modules]),
[try_asm_modules=$enableval],
[try_asm_modules=yes])
AC_MSG_RESULT($try_asm_modules)
# Implementation of the --enable-m-guard switch.
AC_MSG_CHECKING([whether memory guard is requested])
AC_ARG_ENABLE(m-guard,
AC_HELP_STRING([--enable-m-guard],
[Enable memory guard facility]),
[use_m_guard=$enableval], [use_m_guard=no])
AC_MSG_RESULT($use_m_guard)
if test "$use_m_guard" = yes ; then
AC_DEFINE(M_GUARD,1,[Define to use the (obsolete) malloc guarding feature])
fi
# Implementation of the --enable-large-data-tests switch.
AC_MSG_CHECKING([whether to run large data tests])
AC_ARG_ENABLE(large-data-tests,
AC_HELP_STRING([--enable-large-data-tests],
[Enable the real long ruinning large data tests]),
large_data_tests=$enableval,large_data_tests=no)
AC_MSG_RESULT($large_data_tests)
AC_SUBST(RUN_LARGE_DATA_TESTS, $large_data_tests)
# Implementation of the --with-capabilities switch.
# Check whether we want to use Linux capabilities
AC_MSG_CHECKING([whether use of capabilities is requested])
AC_ARG_WITH(capabilities,
AC_HELP_STRING([--with-capabilities],
[Use linux capabilities [default=no]]),
[use_capabilities="$withval"],[use_capabilities=no])
AC_MSG_RESULT($use_capabilities)
# Implementation of the --enable-hmac-binary-check.
AC_MSG_CHECKING([whether a HMAC binary check is requested])
AC_ARG_ENABLE(hmac-binary-check,
AC_HELP_STRING([--enable-hmac-binary-check],
[Enable library integrity check]),
[use_hmac_binary_check=$enableval],
[use_hmac_binary_check=no])
AC_MSG_RESULT($use_hmac_binary_check)
if test "$use_hmac_binary_check" = yes ; then
AC_DEFINE(ENABLE_HMAC_BINARY_CHECK,1,
[Define to support an HMAC based integrity check])
fi
# Implementation of the --disable-jent-support switch.
AC_MSG_CHECKING([whether jitter entropy support is requested])
AC_ARG_ENABLE(jent-support,
AC_HELP_STRING([--disable-jent-support],
[Disable support for the Jitter entropy collector]),
jentsupport=$enableval,jentsupport=yes)
AC_MSG_RESULT($jentsupport)
# Implementation of the --disable-padlock-support switch.
AC_MSG_CHECKING([whether padlock support is requested])
AC_ARG_ENABLE(padlock-support,
AC_HELP_STRING([--disable-padlock-support],
[Disable support for the PadLock Engine of VIA processors]),
padlocksupport=$enableval,padlocksupport=yes)
AC_MSG_RESULT($padlocksupport)
# Implementation of the --disable-aesni-support switch.
AC_MSG_CHECKING([whether AESNI support is requested])
AC_ARG_ENABLE(aesni-support,
AC_HELP_STRING([--disable-aesni-support],
[Disable support for the Intel AES-NI instructions]),
aesnisupport=$enableval,aesnisupport=yes)
AC_MSG_RESULT($aesnisupport)
# Implementation of the --disable-shaext-support switch.
AC_MSG_CHECKING([whether SHAEXT support is requested])
AC_ARG_ENABLE(shaext-support,
AC_HELP_STRING([--disable-shaext-support],
[Disable support for the Intel SHAEXT instructions]),
shaextsupport=$enableval,shaextsupport=yes)
AC_MSG_RESULT($shaextsupport)
# Implementation of the --disable-pclmul-support switch.
AC_MSG_CHECKING([whether PCLMUL support is requested])
AC_ARG_ENABLE(pclmul-support,
AC_HELP_STRING([--disable-pclmul-support],
[Disable support for the Intel PCLMUL instructions]),
pclmulsupport=$enableval,pclmulsupport=yes)
AC_MSG_RESULT($pclmulsupport)
# Implementation of the --disable-sse41-support switch.
AC_MSG_CHECKING([whether SSE4.1 support is requested])
AC_ARG_ENABLE(sse41-support,
AC_HELP_STRING([--disable-sse41-support],
[Disable support for the Intel SSE4.1 instructions]),
sse41support=$enableval,sse41support=yes)
AC_MSG_RESULT($sse41support)
# Implementation of the --disable-drng-support switch.
AC_MSG_CHECKING([whether DRNG support is requested])
AC_ARG_ENABLE(drng-support,
AC_HELP_STRING([--disable-drng-support],
[Disable support for the Intel DRNG (RDRAND instruction)]),
drngsupport=$enableval,drngsupport=yes)
AC_MSG_RESULT($drngsupport)
# Implementation of the --disable-avx-support switch.
AC_MSG_CHECKING([whether AVX support is requested])
AC_ARG_ENABLE(avx-support,
AC_HELP_STRING([--disable-avx-support],
[Disable support for the Intel AVX instructions]),
avxsupport=$enableval,avxsupport=yes)
AC_MSG_RESULT($avxsupport)
# Implementation of the --disable-avx2-support switch.
AC_MSG_CHECKING([whether AVX2 support is requested])
AC_ARG_ENABLE(avx2-support,
AC_HELP_STRING([--disable-avx2-support],
[Disable support for the Intel AVX2 instructions]),
avx2support=$enableval,avx2support=yes)
AC_MSG_RESULT($avx2support)
# Implementation of the --disable-neon-support switch.
AC_MSG_CHECKING([whether NEON support is requested])
AC_ARG_ENABLE(neon-support,
AC_HELP_STRING([--disable-neon-support],
[Disable support for the ARM NEON instructions]),
neonsupport=$enableval,neonsupport=yes)
AC_MSG_RESULT($neonsupport)
# Implementation of the --disable-arm-crypto-support switch.
AC_MSG_CHECKING([whether ARMv8 Crypto Extension support is requested])
AC_ARG_ENABLE(arm-crypto-support,
AC_HELP_STRING([--disable-arm-crypto-support],
[Disable support for the ARMv8 Crypto Extension instructions]),
armcryptosupport=$enableval,armcryptosupport=yes)
AC_MSG_RESULT($armcryptosupport)
# Implementation of the --disable-ppc-crypto-support switch.
AC_MSG_CHECKING([whether PPC crypto support is requested])
AC_ARG_ENABLE(ppc-crypto-support,
AC_HELP_STRING([--disable-ppc-crypto-support],
[Disable support for the PPC crypto instructions introduced in POWER 8 (PowerISA 2.07)]),
ppccryptosupport=$enableval,ppccryptosupport=yes)
AC_MSG_RESULT($ppccryptosupport)
# Implementation of the --disable-O-flag-munging switch.
AC_MSG_CHECKING([whether a -O flag munging is requested])
AC_ARG_ENABLE([O-flag-munging],
AC_HELP_STRING([--disable-O-flag-munging],
[Disable modification of the cc -O flag]),
[enable_o_flag_munging=$enableval],
[enable_o_flag_munging=yes])
AC_MSG_RESULT($enable_o_flag_munging)
AM_CONDITIONAL(ENABLE_O_FLAG_MUNGING, test "$enable_o_flag_munging" = "yes")
# Implementation of the --disable-instrumentation-munging switch.
AC_MSG_CHECKING([whether a instrumentation (-fprofile, -fsanitize) munging is requested])
AC_ARG_ENABLE([instrumentation-munging],
AC_HELP_STRING([--disable-instrumentation-munging],
[Disable modification of the cc instrumentation options]),
[enable_instrumentation_munging=$enableval],
[enable_instrumentation_munging=yes])
AC_MSG_RESULT($enable_instrumentation_munging)
AM_CONDITIONAL(ENABLE_INSTRUMENTATION_MUNGING,
test "$enable_instrumentation_munging" = "yes")
# Implementation of the --disable-amd64-as-feature-detection switch.
AC_MSG_CHECKING([whether to enable AMD64 as(1) feature detection])
AC_ARG_ENABLE(amd64-as-feature-detection,
AC_HELP_STRING([--disable-amd64-as-feature-detection],
[Disable the auto-detection of AMD64 as(1) features]),
amd64_as_feature_detection=$enableval,
amd64_as_feature_detection=yes)
AC_MSG_RESULT($amd64_as_feature_detection)
AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME",
[A human readable text with the name of the OS])
# For some systems we know that we have ld_version scripts.
# Use it then as default.
have_ld_version_script=no
case "${host}" in
*-*-linux*)
have_ld_version_script=yes
;;
*-*-gnu*)
have_ld_version_script=yes
;;
esac
AC_ARG_ENABLE([ld-version-script],
AC_HELP_STRING([--enable-ld-version-script],
[enable/disable use of linker version script.
(default is system dependent)]),
[have_ld_version_script=$enableval],
[ : ] )
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM",
[defined to the name of the strong random device])
AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM",
[defined to the name of the weaker random device])
###############################
#### Checks for libraries. ####
###############################
#
# gpg-error is required.
#
AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION")
if test "x$GPG_ERROR_LIBS" = "x"; then
AC_MSG_ERROR([libgpg-error is needed.
See ftp://ftp.gnupg.org/gcrypt/libgpg-error/ .])
fi
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GCRYPT,
[The default error source for libgcrypt.])
#
# Check whether the GNU Pth library is available. We require this
# to build the optional gcryptrnd program.
#
AC_ARG_WITH(pth-prefix,
AC_HELP_STRING([--with-pth-prefix=PFX],
[prefix where GNU Pth is installed (optional)]),
pth_config_prefix="$withval", pth_config_prefix="")
if test x$pth_config_prefix != x ; then
PTH_CONFIG="$pth_config_prefix/bin/pth-config"
fi
if test "$use_random_daemon" = "yes"; then
AC_PATH_PROG(PTH_CONFIG, pth-config, no)
if test "$PTH_CONFIG" = "no"; then
AC_MSG_WARN([[
***
*** To build the Libgcrypt's random number daemon
*** we need the support of the GNU Portable Threads Library.
*** Download it from ftp://ftp.gnu.org/gnu/pth/
*** On a Debian GNU/Linux system you might want to try
*** apt-get install libpth-dev
***]])
else
GNUPG_PTH_VERSION_CHECK([1.3.7])
if test $have_pth = yes; then
PTH_CFLAGS=`$PTH_CONFIG --cflags`
PTH_LIBS=`$PTH_CONFIG --ldflags`
PTH_LIBS="$PTH_LIBS `$PTH_CONFIG --libs --all`"
AC_DEFINE(USE_GNU_PTH, 1,
[Defined if the GNU Portable Thread Library should be used])
AC_DEFINE(HAVE_PTH, 1,
[Defined if the GNU Pth is available])
fi
fi
fi
AC_SUBST(PTH_CFLAGS)
AC_SUBST(PTH_LIBS)
#
# Check whether pthreads is available
#
if test "$have_w32_system" != yes; then
AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes)
if test "$have_pthread" = yes; then
AC_DEFINE(HAVE_PTHREAD, 1 ,[Define if we have pthread.])
fi
fi
# Solaris needs -lsocket and -lnsl. Unisys system includes
# gethostbyname in libsocket but needs libnsl for socket.
AC_SEARCH_LIBS(setsockopt, [socket], ,
[AC_SEARCH_LIBS(setsockopt, [socket], , , [-lnsl])])
AC_SEARCH_LIBS(setsockopt, [nsl])
##################################
#### Checks for header files. ####
##################################
AC_HEADER_STDC
AC_CHECK_HEADERS(unistd.h sys/select.h sys/msg.h sys/auxv.h)
INSERT_SYS_SELECT_H=
if test x"$ac_cv_header_sys_select_h" = xyes; then
INSERT_SYS_SELECT_H=" include "
fi
AC_SUBST(INSERT_SYS_SELECT_H)
##########################################
#### Checks for typedefs, structures, ####
#### and compiler characteristics. ####
##########################################
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
AC_DECL_SYS_SIGLIST
AC_TYPE_PID_T
GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF)
GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF)
-GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF)
GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF)
GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF)
gl_TYPE_SOCKLEN_T
case "${host}" in
*-*-mingw32*)
# socklen_t may or may not be defined depending on what headers
# are included. To be safe we use int as this is the actual type.
FALLBACK_SOCKLEN_T="typedef int gcry_socklen_t;"
;;
*)
if test ".$gl_cv_socklen_t_equiv" = "."; then
FALLBACK_SOCKLEN_T="typedef socklen_t gcry_socklen_t;"
else
FALLBACK_SOCKLEN_T="typedef ${gl_cv_socklen_t_equiv} gcry_socklen_t;"
fi
esac
AC_SUBST(FALLBACK_SOCKLEN_T)
#
# Check for __builtin_bswap32 intrinsic.
#
AC_CACHE_CHECK(for __builtin_bswap32,
[gcry_cv_have_builtin_bswap32],
[gcry_cv_have_builtin_bswap32=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[int x = 0; int y = __builtin_bswap32(x); return y;])],
[gcry_cv_have_builtin_bswap32=yes])])
if test "$gcry_cv_have_builtin_bswap32" = "yes" ; then
AC_DEFINE(HAVE_BUILTIN_BSWAP32,1,
[Defined if compiler has '__builtin_bswap32' intrinsic])
fi
#
# Check for __builtin_bswap64 intrinsic.
#
AC_CACHE_CHECK(for __builtin_bswap64,
[gcry_cv_have_builtin_bswap64],
[gcry_cv_have_builtin_bswap64=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[long long x = 0; long long y = __builtin_bswap64(x); return y;])],
[gcry_cv_have_builtin_bswap64=yes])])
if test "$gcry_cv_have_builtin_bswap64" = "yes" ; then
AC_DEFINE(HAVE_BUILTIN_BSWAP64,1,
[Defined if compiler has '__builtin_bswap64' intrinsic])
fi
#
# Check for __builtin_ctz intrinsic.
#
AC_CACHE_CHECK(for __builtin_ctz,
[gcry_cv_have_builtin_ctz],
[gcry_cv_have_builtin_ctz=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[unsigned int x = 0; int y = __builtin_ctz(x); return y;])],
[gcry_cv_have_builtin_ctz=yes])])
if test "$gcry_cv_have_builtin_ctz" = "yes" ; then
AC_DEFINE(HAVE_BUILTIN_CTZ, 1,
[Defined if compiler has '__builtin_ctz' intrinsic])
fi
#
# Check for __sync_synchronize intrinsic.
#
AC_CACHE_CHECK(for __sync_synchronize,
[gcry_cv_have_sync_synchronize],
[gcry_cv_have_sync_synchronize=no
AC_LINK_IFELSE([AC_LANG_PROGRAM([],
[__sync_synchronize(); return 0;])],
[gcry_cv_have_sync_synchronize=yes])])
if test "$gcry_cv_have_sync_synchronize" = "yes" ; then
AC_DEFINE(HAVE_SYNC_SYNCHRONIZE, 1,
[Defined if compiler has '__sync_synchronize' intrinsic])
fi
#
# Check for VLA support (variable length arrays).
#
AC_CACHE_CHECK(whether the variable length arrays are supported,
[gcry_cv_have_vla],
[gcry_cv_have_vla=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void f1(char *, int);
char foo(int i) {
char b[(i < 0 ? 0 : i) + 1];
f1(b, sizeof b); return b[0];}]])],
[gcry_cv_have_vla=yes])])
if test "$gcry_cv_have_vla" = "yes" ; then
AC_DEFINE(HAVE_VLA,1, [Defined if variable length arrays are supported])
fi
#
# Check for ELF visibility support.
#
AC_CACHE_CHECK(whether the visibility attribute is supported,
gcry_cv_visibility_attribute,
[gcry_cv_visibility_attribute=no
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[int foo __attribute__ ((visibility ("hidden"))) = 1;
int bar __attribute__ ((visibility ("protected"))) = 1;
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep '\.hidden.*foo' conftest.s >/dev/null 2>&1 ; then
if grep '\.protected.*bar' conftest.s >/dev/null 2>&1; then
gcry_cv_visibility_attribute=yes
fi
fi
fi
])
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(for broken visibility attribute,
gcry_cv_broken_visibility_attribute,
[gcry_cv_broken_visibility_attribute=yes
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[int foo (int x);
int bar (int x) __asm__ ("foo")
__attribute__ ((visibility ("hidden")));
int bar (int x) { return x; }
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep '\.hidden@<:@ _@:>@foo' conftest.s >/dev/null 2>&1;
then
gcry_cv_broken_visibility_attribute=no
fi
fi
])
fi
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(for broken alias attribute,
gcry_cv_broken_alias_attribute,
[gcry_cv_broken_alias_attribute=yes
AC_LANG_CONFTEST([AC_LANG_SOURCE(
[[extern int foo (int x) __asm ("xyzzy");
int bar (int x) { return x; }
extern __typeof (bar) foo __attribute ((weak, alias ("bar")));
extern int dfoo;
extern __typeof (dfoo) dfoo __asm ("abccb");
int dfoo = 1;
]])])
if ${CC-cc} -Werror -S conftest.c -o conftest.s \
1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ; then
if grep 'xyzzy' conftest.s >/dev/null 2>&1 && \
grep 'abccb' conftest.s >/dev/null 2>&1; then
gcry_cv_broken_alias_attribute=no
fi
fi
])
fi
if test "$gcry_cv_visibility_attribute" = "yes"; then
AC_CACHE_CHECK(if gcc supports -fvisibility=hidden,
gcry_cv_gcc_has_f_visibility,
[gcry_cv_gcc_has_f_visibility=no
_gcc_cflags_save=$CFLAGS
CFLAGS="-fvisibility=hidden"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],
gcry_cv_gcc_has_f_visibility=yes)
CFLAGS=$_gcc_cflags_save;
])
fi
if test "$gcry_cv_visibility_attribute" = "yes" \
&& test "$gcry_cv_broken_visibility_attribute" != "yes" \
&& test "$gcry_cv_broken_alias_attribute" != "yes" \
&& test "$gcry_cv_gcc_has_f_visibility" = "yes"
then
AC_DEFINE(GCRY_USE_VISIBILITY, 1,
[Define to use the GNU C visibility attribute.])
CFLAGS="$CFLAGS -fvisibility=hidden"
fi
# Following attribute tests depend on warnings to cause compile to fail,
# so set -Werror temporarily.
_gcc_cflags_save=$CFLAGS
CFLAGS="$CFLAGS -Werror"
#
# Check whether the compiler supports the GCC style aligned attribute
#
AC_CACHE_CHECK([whether the GCC style aligned attribute is supported],
[gcry_cv_gcc_attribute_aligned],
[gcry_cv_gcc_attribute_aligned=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[struct { int a; } foo __attribute__ ((aligned (16)));]])],
[gcry_cv_gcc_attribute_aligned=yes])])
if test "$gcry_cv_gcc_attribute_aligned" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_ALIGNED,1,
[Defined if a GCC style "__attribute__ ((aligned (n))" is supported])
fi
#
# Check whether the compiler supports the GCC style packed attribute
#
AC_CACHE_CHECK([whether the GCC style packed attribute is supported],
[gcry_cv_gcc_attribute_packed],
[gcry_cv_gcc_attribute_packed=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[struct foolong_s { long b; } __attribute__ ((packed));
struct foo_s { char a; struct foolong_s b; }
__attribute__ ((packed));
enum bar {
FOO = 1 / (sizeof(struct foo_s) == (sizeof(char) + sizeof(long))),
};]])],
[gcry_cv_gcc_attribute_packed=yes])])
if test "$gcry_cv_gcc_attribute_packed" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_PACKED,1,
[Defined if a GCC style "__attribute__ ((packed))" is supported])
fi
#
# Check whether the compiler supports the GCC style may_alias attribute
#
AC_CACHE_CHECK([whether the GCC style may_alias attribute is supported],
[gcry_cv_gcc_attribute_may_alias],
[gcry_cv_gcc_attribute_may_alias=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[typedef struct foo_s { int a; }
__attribute__ ((may_alias)) foo_t;]])],
[gcry_cv_gcc_attribute_may_alias=yes])])
if test "$gcry_cv_gcc_attribute_may_alias" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_MAY_ALIAS,1,
[Defined if a GCC style "__attribute__ ((may_alias))" is supported])
fi
# Restore flags.
CFLAGS=$_gcc_cflags_save;
#
# Check whether the compiler supports 'asm' or '__asm__' keyword for
# assembler blocks.
#
AC_CACHE_CHECK([whether 'asm' assembler keyword is supported],
[gcry_cv_have_asm],
[gcry_cv_have_asm=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) { asm("":::"memory"); }]])],
[gcry_cv_have_asm=yes])])
AC_CACHE_CHECK([whether '__asm__' assembler keyword is supported],
[gcry_cv_have___asm__],
[gcry_cv_have___asm__=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) { __asm__("":::"memory"); }]])],
[gcry_cv_have___asm__=yes])])
if test "$gcry_cv_have_asm" = "no" ; then
if test "$gcry_cv_have___asm__" = "yes" ; then
AC_DEFINE(asm,__asm__,
[Define to supported assembler block keyword, if plain 'asm' was not
supported])
fi
fi
#
# Check whether the compiler supports inline assembly memory barrier.
#
if test "$gcry_cv_have_asm" = "no" ; then
if test "$gcry_cv_have___asm__" = "yes" ; then
AC_CACHE_CHECK([whether inline assembly memory barrier is supported],
[gcry_cv_have_asm_volatile_memory],
[gcry_cv_have_asm_volatile_memory=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) { __asm__ volatile("":::"memory"); }]])],
[gcry_cv_have_asm_volatile_memory=yes])])
fi
else
AC_CACHE_CHECK([whether inline assembly memory barrier is supported],
[gcry_cv_have_asm_volatile_memory],
[gcry_cv_have_asm_volatile_memory=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) { asm volatile("":::"memory"); }]])],
[gcry_cv_have_asm_volatile_memory=yes])])
fi
if test "$gcry_cv_have_asm_volatile_memory" = "yes" ; then
AC_DEFINE(HAVE_GCC_ASM_VOLATILE_MEMORY,1,
[Define if inline asm memory barrier is supported])
fi
#
# Check whether GCC assembler supports features needed for our ARM
# implementations. This needs to be done before setting up the
# assembler stuff.
#
AC_CACHE_CHECK([whether GCC assembler is compatible for ARM assembly implementations],
[gcry_cv_gcc_arm_platform_as_ok],
[gcry_cv_gcc_arm_platform_as_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
/* Test if assembler supports UAL syntax. */
".syntax unified\n\t"
".arm\n\t" /* our assembly code is in ARM mode */
/* Following causes error if assembler ignored '.syntax unified'. */
"asmfunc:\n\t"
"add %r0, %r0, %r4, ror #12;\n\t"
/* Test if '.type' and '.size' are supported. */
".size asmfunc,.-asmfunc;\n\t"
".type asmfunc,%function;\n\t"
);]])],
[gcry_cv_gcc_arm_platform_as_ok=yes])])
if test "$gcry_cv_gcc_arm_platform_as_ok" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with ARM assembly implementations])
fi
#
# Check whether GCC assembler supports features needed for our ARMv8/Aarch64
# implementations. This needs to be done before setting up the
# assembler stuff.
#
AC_CACHE_CHECK([whether GCC assembler is compatible for ARMv8/Aarch64 assembly implementations],
[gcry_cv_gcc_aarch64_platform_as_ok],
[gcry_cv_gcc_aarch64_platform_as_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
"asmfunc:\n\t"
"eor x0, x0, x30, ror #12;\n\t"
"add x0, x0, x30, asr #12;\n\t"
"eor v0.16b, v0.16b, v31.16b;\n\t"
);]])],
[gcry_cv_gcc_aarch64_platform_as_ok=yes])])
if test "$gcry_cv_gcc_aarch64_platform_as_ok" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_GCC_AARCH64_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with ARMv8/Aarch64 assembly implementations])
fi
#
# Check whether GCC assembler supports for CFI directives.
#
AC_CACHE_CHECK([whether GCC assembler supports for CFI directives],
[gcry_cv_gcc_asm_cfi_directives],
[gcry_cv_gcc_asm_cfi_directives=no
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[__asm__(
".text\n\t"
"ac_test:\n\t"
".cfi_startproc\n\t"
".cfi_remember_state\n\t"
".cfi_adjust_cfa_offset 8\n\t"
".cfi_rel_offset 0, 8\n\t"
".cfi_def_cfa_register 1\n\t"
".cfi_register 2, 3\n\t"
".cfi_restore 2\n\t"
".cfi_escape 0x0f, 0x02, 0x11, 0x00\n\t"
".cfi_restore_state\n\t"
".long 0\n\t"
".cfi_endproc\n\t"
);]])],
[gcry_cv_gcc_asm_cfi_directives=yes])])
if test "$gcry_cv_gcc_asm_cfi_directives" = "yes" ; then
AC_DEFINE(HAVE_GCC_ASM_CFI_DIRECTIVES,1,
[Defined if underlying assembler supports for CFI directives])
fi
#
# Check whether underscores in symbols are required. This needs to be
# done before setting up the assembler stuff.
#
GNUPG_SYS_SYMBOL_UNDERSCORE()
#################################
#### ####
#### Setup assembler stuff. ####
#### Define mpi_cpu_arch. ####
#### ####
#################################
AC_ARG_ENABLE(mpi-path,
AC_HELP_STRING([--enable-mpi-path=EXTRA_PATH],
[prepend EXTRA_PATH to list of CPU specific optimizations]),
mpi_extra_path="$enableval",mpi_extra_path="")
AC_MSG_CHECKING(architecture and mpi assembler functions)
if test -f $srcdir/mpi/config.links ; then
. $srcdir/mpi/config.links
AC_CONFIG_LINKS("$mpi_ln_list")
ac_cv_mpi_sflags="$mpi_sflags"
AC_MSG_RESULT($mpi_cpu_arch)
else
AC_MSG_RESULT(failed)
AC_MSG_ERROR([mpi/config.links missing!])
fi
MPI_SFLAGS="$ac_cv_mpi_sflags"
AC_SUBST(MPI_SFLAGS)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_ADD1, test "$mpi_mod_asm_mpih_add1" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_SUB1, test "$mpi_mod_asm_mpih_sub1" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL1, test "$mpi_mod_asm_mpih_mul1" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL2, test "$mpi_mod_asm_mpih_mul2" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_MUL3, test "$mpi_mod_asm_mpih_mul3" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_LSHIFT, test "$mpi_mod_asm_mpih_lshift" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_MPIH_RSHIFT, test "$mpi_mod_asm_mpih_rshift" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_UDIV, test "$mpi_mod_asm_udiv" = yes)
AM_CONDITIONAL(MPI_MOD_ASM_UDIV_QRNND, test "$mpi_mod_asm_udiv_qrnnd" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_ADD1, test "$mpi_mod_c_mpih_add1" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_SUB1, test "$mpi_mod_c_mpih_sub1" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL1, test "$mpi_mod_c_mpih_mul1" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL2, test "$mpi_mod_c_mpih_mul2" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_MUL3, test "$mpi_mod_c_mpih_mul3" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_LSHIFT, test "$mpi_mod_c_mpih_lshift" = yes)
AM_CONDITIONAL(MPI_MOD_C_MPIH_RSHIFT, test "$mpi_mod_c_mpih_rshift" = yes)
AM_CONDITIONAL(MPI_MOD_C_UDIV, test "$mpi_mod_c_udiv" = yes)
AM_CONDITIONAL(MPI_MOD_C_UDIV_QRNND, test "$mpi_mod_c_udiv_qrnnd" = yes)
# Reset non applicable feature flags.
if test "$mpi_cpu_arch" != "x86" ; then
aesnisupport="n/a"
shaextsupport="n/a"
pclmulsupport="n/a"
sse41support="n/a"
avxsupport="n/a"
avx2support="n/a"
padlocksupport="n/a"
jentsupport="n/a"
drngsupport="n/a"
fi
if test "$mpi_cpu_arch" != "arm" ; then
if test "$mpi_cpu_arch" != "aarch64" ; then
neonsupport="n/a"
armcryptosupport="n/a"
fi
fi
if test "$mpi_cpu_arch" != "ppc"; then
ppccryptosupport="n/a"
fi
#############################################
#### ####
#### Platform specific compiler checks. ####
#### ####
#############################################
# Following tests depend on warnings to cause compile to fail, so set -Werror
# temporarily.
_gcc_cflags_save=$CFLAGS
CFLAGS="$CFLAGS -Werror"
#
# Check whether compiler supports 'ms_abi' function attribute.
#
AC_CACHE_CHECK([whether compiler supports 'ms_abi' function attribute],
[gcry_cv_gcc_attribute_ms_abi],
[gcry_cv_gcc_attribute_ms_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[int __attribute__ ((ms_abi)) proto(int);]])],
[gcry_cv_gcc_attribute_ms_abi=yes])])
if test "$gcry_cv_gcc_attribute_ms_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_MS_ABI,1,
[Defined if compiler supports "__attribute__ ((ms_abi))" function attribute])
fi
#
# Check whether compiler supports 'sysv_abi' function attribute.
#
AC_CACHE_CHECK([whether compiler supports 'sysv_abi' function attribute],
[gcry_cv_gcc_attribute_sysv_abi],
[gcry_cv_gcc_attribute_sysv_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[int __attribute__ ((sysv_abi)) proto(int);]])],
[gcry_cv_gcc_attribute_sysv_abi=yes])])
if test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_ATTRIBUTE_SYSV_ABI,1,
[Defined if compiler supports "__attribute__ ((sysv_abi))" function attribute])
fi
#
# Check whether default calling convention is 'ms_abi'.
#
if test "$gcry_cv_gcc_attribute_ms_abi" = "yes" ; then
AC_CACHE_CHECK([whether default calling convention is 'ms_abi'],
[gcry_cv_gcc_default_abi_is_ms_abi],
[gcry_cv_gcc_default_abi_is_ms_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void *test(void) {
void *(*def_func)(void) = test;
void *__attribute__((ms_abi))(*msabi_func)(void);
/* warning on SysV abi targets, passes on Windows based targets */
msabi_func = def_func;
return msabi_func;
}]])],
[gcry_cv_gcc_default_abi_is_ms_abi=yes])])
if test "$gcry_cv_gcc_default_abi_is_ms_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_DEFAULT_ABI_IS_MS_ABI,1,
[Defined if default calling convention is 'ms_abi'])
fi
fi
#
# Check whether default calling convention is 'sysv_abi'.
#
if test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" ; then
AC_CACHE_CHECK([whether default calling convention is 'sysv_abi'],
[gcry_cv_gcc_default_abi_is_sysv_abi],
[gcry_cv_gcc_default_abi_is_sysv_abi=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void *test(void) {
void *(*def_func)(void) = test;
void *__attribute__((sysv_abi))(*sysvabi_func)(void);
/* warning on MS ABI targets, passes on SysV ABI targets */
sysvabi_func = def_func;
return sysvabi_func;
}]])],
[gcry_cv_gcc_default_abi_is_sysv_abi=yes])])
if test "$gcry_cv_gcc_default_abi_is_sysv_abi" = "yes" ; then
AC_DEFINE(HAVE_GCC_DEFAULT_ABI_IS_SYSV_ABI,1,
[Defined if default calling convention is 'sysv_abi'])
fi
fi
# Restore flags.
CFLAGS=$_gcc_cflags_save;
#
# Check whether GCC inline assembler supports SSSE3 instructions
# This is required for the AES-NI instructions.
#
AC_CACHE_CHECK([whether GCC inline assembler supports SSSE3 instructions],
[gcry_cv_gcc_inline_asm_ssse3],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_ssse3="n/a"
else
gcry_cv_gcc_inline_asm_ssse3=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[static unsigned char be_mask[16] __attribute__ ((aligned (16))) =
{ 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
void a(void) {
__asm__("pshufb %[mask], %%xmm2\n\t"::[mask]"m"(*be_mask):);
}]])],
[gcry_cv_gcc_inline_asm_ssse3=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_ssse3" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_SSSE3,1,
[Defined if inline assembler supports SSSE3 instructions])
fi
#
# Check whether GCC inline assembler supports PCLMUL instructions.
#
AC_CACHE_CHECK([whether GCC inline assembler supports PCLMUL instructions],
[gcry_cv_gcc_inline_asm_pclmul],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_pclmul="n/a"
else
gcry_cv_gcc_inline_asm_pclmul=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("pclmulqdq \$0, %%xmm1, %%xmm3\n\t":::"cc");
}]])],
[gcry_cv_gcc_inline_asm_pclmul=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_pclmul" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_PCLMUL,1,
[Defined if inline assembler supports PCLMUL instructions])
fi
#
# Check whether GCC inline assembler supports SHA Extensions instructions.
#
AC_CACHE_CHECK([whether GCC inline assembler supports SHA Extensions instructions],
[gcry_cv_gcc_inline_asm_shaext],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_shaext="n/a"
else
gcry_cv_gcc_inline_asm_shaext=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("sha1rnds4 \$0, %%xmm1, %%xmm3\n\t":::"cc");
__asm__("sha1nexte %%xmm1, %%xmm3\n\t":::"cc");
__asm__("sha1msg1 %%xmm1, %%xmm3\n\t":::"cc");
__asm__("sha1msg2 %%xmm1, %%xmm3\n\t":::"cc");
__asm__("sha256rnds2 %%xmm0, %%xmm1, %%xmm3\n\t":::"cc");
__asm__("sha256msg1 %%xmm1, %%xmm3\n\t":::"cc");
__asm__("sha256msg2 %%xmm1, %%xmm3\n\t":::"cc");
}]])],
[gcry_cv_gcc_inline_asm_shaext=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_shaext" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_SHAEXT,1,
[Defined if inline assembler supports SHA Extensions instructions])
fi
#
# Check whether GCC inline assembler supports SSE4.1 instructions.
#
AC_CACHE_CHECK([whether GCC inline assembler supports SSE4.1 instructions],
[gcry_cv_gcc_inline_asm_sse41],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_sse41="n/a"
else
gcry_cv_gcc_inline_asm_sse41=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
int i;
__asm__("pextrd \$2, %%xmm0, %[out]\n\t" : [out] "=m" (i));
}]])],
[gcry_cv_gcc_inline_asm_sse41=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_sse41" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_SSE41,1,
[Defined if inline assembler supports SSE4.1 instructions])
fi
#
# Check whether GCC inline assembler supports AVX instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions],
[gcry_cv_gcc_inline_asm_avx],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_avx="n/a"
else
gcry_cv_gcc_inline_asm_avx=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("xgetbv; vaesdeclast (%[mem]),%%xmm0,%%xmm7\n\t"::[mem]"r"(0):);
}]])],
[gcry_cv_gcc_inline_asm_avx=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_avx" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX,1,
[Defined if inline assembler supports AVX instructions])
fi
#
# Check whether GCC inline assembler supports AVX2 instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AVX2 instructions],
[gcry_cv_gcc_inline_asm_avx2],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_avx2="n/a"
else
gcry_cv_gcc_inline_asm_avx2=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[void a(void) {
__asm__("xgetbv; vpbroadcastb %%xmm7,%%ymm1\n\t":::"cc");
}]])],
[gcry_cv_gcc_inline_asm_avx2=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_avx2" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AVX2,1,
[Defined if inline assembler supports AVX2 instructions])
fi
#
# Check whether GCC inline assembler supports BMI2 instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports BMI2 instructions],
[gcry_cv_gcc_inline_asm_bmi2],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_inline_asm_bmi2="n/a"
else
gcry_cv_gcc_inline_asm_bmi2=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[unsigned int a(unsigned int x, unsigned int y) {
unsigned int tmp1, tmp2;
asm ("rorxl %2, %1, %0"
: "=r" (tmp1)
: "rm0" (x), "J" (32 - ((23) & 31)));
asm ("andnl %2, %1, %0"
: "=r" (tmp2)
: "r0" (x), "rm" (y));
return tmp1 + tmp2;
}]])],
[gcry_cv_gcc_inline_asm_bmi2=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_bmi2" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_BMI2,1,
[Defined if inline assembler supports BMI2 instructions])
fi
#
# Check whether GCC assembler needs "-Wa,--divide" to correctly handle
# constant division
#
if test $amd64_as_feature_detection = yes; then
AC_CACHE_CHECK([whether GCC assembler handles division correctly],
[gcry_cv_gcc_as_const_division_ok],
[gcry_cv_gcc_as_const_division_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__("xorl \$(123456789/12345678), %ebp;\n\t");]])],
[gcry_cv_gcc_as_const_division_ok=yes])])
if test "$gcry_cv_gcc_as_const_division_ok" = "no" ; then
#
# Add '-Wa,--divide' to CPPFLAGS and try check again.
#
_gcc_cppflags_save="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -Wa,--divide"
AC_CACHE_CHECK([whether GCC assembler handles division correctly with "-Wa,--divide"],
[gcry_cv_gcc_as_const_division_with_wadivide_ok],
[gcry_cv_gcc_as_const_division_with_wadivide_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__("xorl \$(123456789/12345678), %ebp;\n\t");]])],
[gcry_cv_gcc_as_const_division_with_wadivide_ok=yes])])
if test "$gcry_cv_gcc_as_const_division_with_wadivide_ok" = "no" ; then
# '-Wa,--divide' did not work, restore old flags.
CPPFLAGS="$_gcc_cppflags_save"
fi
fi
fi
#
# Check whether GCC assembler supports features needed for our amd64
# implementations
#
if test $amd64_as_feature_detection = yes; then
AC_CACHE_CHECK([whether GCC assembler is compatible for amd64 assembly implementations],
[gcry_cv_gcc_amd64_platform_as_ok],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_amd64_platform_as_ok="n/a"
else
gcry_cv_gcc_amd64_platform_as_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
/* Test if '.type' and '.size' are supported. */
/* These work only on ELF targets. */
"asmfunc:\n\t"
".size asmfunc,.-asmfunc;\n\t"
".type asmfunc,@function;\n\t"
/* Test if assembler allows use of '/' for constant division
* (Solaris/x86 issue). If previous constant division check
* and "-Wa,--divide" workaround failed, this causes assembly
* to be disable on this machine. */
"xorl \$(123456789/12345678), %ebp;\n\t"
);]])],
[gcry_cv_gcc_amd64_platform_as_ok=yes])
fi])
if test "$gcry_cv_gcc_amd64_platform_as_ok" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with amd64 assembly implementations])
fi
if test "$gcry_cv_gcc_amd64_platform_as_ok" = "no" &&
test "$gcry_cv_gcc_attribute_sysv_abi" = "yes" &&
test "$gcry_cv_gcc_default_abi_is_ms_abi" = "yes"; then
AC_CACHE_CHECK([whether GCC assembler is compatible for WIN64 assembly implementations],
[gcry_cv_gcc_win64_platform_as_ok],
[gcry_cv_gcc_win64_platform_as_ok=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
".globl asmfunc\n\t"
"asmfunc:\n\t"
"xorq \$(1234), %rbp;\n\t"
);]])],
[gcry_cv_gcc_win64_platform_as_ok=yes])])
if test "$gcry_cv_gcc_win64_platform_as_ok" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with WIN64 assembly implementations])
fi
fi
fi
#
# Check whether GCC assembler supports features needed for assembly
# implementations that use Intel syntax
#
AC_CACHE_CHECK([whether GCC assembler is compatible for Intel syntax assembly implementations],
[gcry_cv_gcc_platform_as_ok_for_intel_syntax],
[if test "$mpi_cpu_arch" != "x86" ; then
gcry_cv_gcc_platform_as_ok_for_intel_syntax="n/a"
else
gcry_cv_gcc_platform_as_ok_for_intel_syntax=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
".intel_syntax noprefix\n\t"
"pxor xmm1, xmm7;\n\t"
/* Intel syntax implementation also use GAS macros, so check
* for them here. */
"VAL_A = xmm4\n\t"
"VAL_B = xmm2\n\t"
".macro SET_VAL_A p1\n\t"
" VAL_A = \\\\p1 \n\t"
".endm\n\t"
".macro SET_VAL_B p1\n\t"
" VAL_B = \\\\p1 \n\t"
".endm\n\t"
"vmovdqa VAL_A, VAL_B;\n\t"
"SET_VAL_A eax\n\t"
"SET_VAL_B ebp\n\t"
"add VAL_A, VAL_B;\n\t"
"add VAL_B, 0b10101;\n\t"
);]])],
[gcry_cv_gcc_platform_as_ok_for_intel_syntax=yes])
fi])
if test "$gcry_cv_gcc_platform_as_ok_for_intel_syntax" = "yes" ; then
AC_DEFINE(HAVE_INTEL_SYNTAX_PLATFORM_AS,1,
[Defined if underlying assembler is compatible with Intel syntax assembly implementations])
fi
#
# Check whether compiler is configured for ARMv6 or newer architecture
#
AC_CACHE_CHECK([whether compiler is configured for ARMv6 or newer architecture],
[gcry_cv_cc_arm_arch_is_v6],
[if test "$mpi_cpu_arch" != "arm" ; then
gcry_cv_cc_arm_arch_is_v6="n/a"
else
gcry_cv_cc_arm_arch_is_v6=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[
#if defined(__arm__) && \
((defined(__ARM_ARCH) && __ARM_ARCH >= 6) \
|| defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|| defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) \
|| defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__))
/* empty */
#else
/* fail compile if not ARMv6. */
not_armv6 not_armv6 = (not_armv6)not_armv6;
#endif
]])],
[gcry_cv_cc_arm_arch_is_v6=yes])
fi])
if test "$gcry_cv_cc_arm_arch_is_v6" = "yes" ; then
AC_DEFINE(HAVE_ARM_ARCH_V6,1,
[Defined if ARM architecture is v6 or newer])
fi
#
# Check whether GCC inline assembler supports NEON instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports NEON instructions],
[gcry_cv_gcc_inline_asm_neon],
[if test "$mpi_cpu_arch" != "arm" ; then
gcry_cv_gcc_inline_asm_neon="n/a"
else
gcry_cv_gcc_inline_asm_neon=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
".syntax unified\n\t"
".arm\n\t"
".fpu neon\n\t"
"vld1.64 {%q0-%q1}, [%r0]!;\n\t"
"vrev64.8 %q0, %q3;\n\t"
"vadd.u64 %q0, %q1;\n\t"
"vadd.s64 %d3, %d2, %d3;\n\t"
);
]])],
[gcry_cv_gcc_inline_asm_neon=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_neon" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_NEON,1,
[Defined if inline assembler supports NEON instructions])
fi
#
# Check whether GCC inline assembler supports AArch32 Crypto Extension instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AArch32 Crypto Extension instructions],
[gcry_cv_gcc_inline_asm_aarch32_crypto],
[if test "$mpi_cpu_arch" != "arm" ; then
gcry_cv_gcc_inline_asm_aarch32_crypto="n/a"
else
gcry_cv_gcc_inline_asm_aarch32_crypto=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
".syntax unified\n\t"
".arch armv8-a\n\t"
".arm\n\t"
".fpu crypto-neon-fp-armv8\n\t"
"sha1h.32 q0, q0;\n\t"
"sha1c.32 q0, q0, q0;\n\t"
"sha1p.32 q0, q0, q0;\n\t"
"sha1su0.32 q0, q0, q0;\n\t"
"sha1su1.32 q0, q0;\n\t"
"sha256h.32 q0, q0, q0;\n\t"
"sha256h2.32 q0, q0, q0;\n\t"
"sha1p.32 q0, q0, q0;\n\t"
"sha256su0.32 q0, q0;\n\t"
"sha256su1.32 q0, q0, q15;\n\t"
"aese.8 q0, q0;\n\t"
"aesd.8 q0, q0;\n\t"
"aesmc.8 q0, q0;\n\t"
"aesimc.8 q0, q0;\n\t"
"vmull.p64 q0, d0, d0;\n\t"
);
]])],
[gcry_cv_gcc_inline_asm_aarch32_crypto=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH32_CRYPTO,1,
[Defined if inline assembler supports AArch32 Crypto Extension instructions])
fi
#
# Check whether GCC inline assembler supports AArch64 NEON instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AArch64 NEON instructions],
[gcry_cv_gcc_inline_asm_aarch64_neon],
[if test "$mpi_cpu_arch" != "aarch64" ; then
gcry_cv_gcc_inline_asm_aarch64_neon="n/a"
else
gcry_cv_gcc_inline_asm_aarch64_neon=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
".cpu generic+simd\n\t"
"mov w0, \#42;\n\t"
"dup v0.8b, w0;\n\t"
"ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
);
]])],
[gcry_cv_gcc_inline_asm_aarch64_neon=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_aarch64_neon" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH64_NEON,1,
[Defined if inline assembler supports AArch64 NEON instructions])
fi
#
# Check whether GCC inline assembler supports AArch64 Crypto Extension instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports AArch64 Crypto Extension instructions],
[gcry_cv_gcc_inline_asm_aarch64_crypto],
[if test "$mpi_cpu_arch" != "aarch64" ; then
gcry_cv_gcc_inline_asm_aarch64_crypto="n/a"
else
gcry_cv_gcc_inline_asm_aarch64_crypto=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(
".cpu generic+simd+crypto\n\t"
"mov w0, \#42;\n\t"
"dup v0.8b, w0;\n\t"
"ld4 {v0.8b,v1.8b,v2.8b,v3.8b},[x0],\#32;\n\t"
"sha1h s0, s0;\n\t"
"sha1c q0, s0, v0.4s;\n\t"
"sha1p q0, s0, v0.4s;\n\t"
"sha1su0 v0.4s, v0.4s, v0.4s;\n\t"
"sha1su1 v0.4s, v0.4s;\n\t"
"sha256h q0, q0, v0.4s;\n\t"
"sha256h2 q0, q0, v0.4s;\n\t"
"sha1p q0, s0, v0.4s;\n\t"
"sha256su0 v0.4s, v0.4s;\n\t"
"sha256su1 v0.4s, v0.4s, v31.4s;\n\t"
"aese v0.16b, v0.16b;\n\t"
"aesd v0.16b, v0.16b;\n\t"
"aesmc v0.16b, v0.16b;\n\t"
"aesimc v0.16b, v0.16b;\n\t"
"pmull v0.1q, v0.1d, v31.1d;\n\t"
"pmull2 v0.1q, v0.2d, v31.2d;\n\t"
);
]])],
[gcry_cv_gcc_inline_asm_aarch64_crypto=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_AARCH64_CRYPTO,1,
[Defined if inline assembler supports AArch64 Crypto Extension instructions])
fi
#
# Check whether PowerPC AltiVec/VSX intrinsics
#
AC_CACHE_CHECK([whether compiler supports PowerPC AltiVec/VSX intrinsics],
[gcry_cv_cc_ppc_altivec],
[if test "$mpi_cpu_arch" != "ppc" ; then
gcry_cv_cc_ppc_altivec="n/a"
else
gcry_cv_cc_ppc_altivec=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[#include
typedef vector unsigned char block;
block fn(block in)
{
block t = vec_perm (in, in, vec_vsx_ld (0, (unsigned char*)0));
return vec_cipher_be (t, in);
}
]])],
[gcry_cv_cc_ppc_altivec=yes])
fi])
if test "$gcry_cv_cc_ppc_altivec" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_CC_PPC_ALTIVEC,1,
[Defined if underlying compiler supports PowerPC AltiVec/VSX/crypto intrinsics])
fi
_gcc_cflags_save=$CFLAGS
CFLAGS="$CFLAGS -maltivec -mvsx -mcrypto"
if test "$gcry_cv_cc_ppc_altivec" = "no" &&
test "$mpi_cpu_arch" = "ppc" ; then
AC_CACHE_CHECK([whether compiler supports PowerPC AltiVec/VSX/crypto intrinsics with extra GCC flags],
[gcry_cv_cc_ppc_altivec_cflags],
[gcry_cv_cc_ppc_altivec_cflags=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[#include
typedef vector unsigned char block;
block fn(block in)
{
block t = vec_perm (in, in, vec_vsx_ld (0, (unsigned char*)0));
return vec_cipher_be (t, in);
}]])],
[gcry_cv_cc_ppc_altivec_cflags=yes])])
if test "$gcry_cv_cc_ppc_altivec_cflags" = "yes" ; then
AC_DEFINE(HAVE_COMPATIBLE_CC_PPC_ALTIVEC,1,
[Defined if underlying compiler supports PowerPC AltiVec/VSX/crypto intrinsics])
AC_DEFINE(HAVE_COMPATIBLE_CC_PPC_ALTIVEC_WITH_CFLAGS,1,
[Defined if underlying compiler supports PowerPC AltiVec/VSX/crypto intrinsics with extra GCC flags])
fi
fi
AM_CONDITIONAL(ENABLE_PPC_VCRYPTO_EXTRA_CFLAGS,
test "$gcry_cv_cc_ppc_altivec_cflags" = "yes")
# Restore flags.
CFLAGS=$_gcc_cflags_save;
#
# Check whether GCC inline assembler supports PowerPC AltiVec/VSX/crypto instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports PowerPC AltiVec/VSX/crypto instructions],
[gcry_cv_gcc_inline_asm_ppc_altivec],
[if test "$mpi_cpu_arch" != "ppc" ; then
gcry_cv_gcc_inline_asm_ppc_altivec="n/a"
else
gcry_cv_gcc_inline_asm_ppc_altivec=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(".globl testfn;\n"
"testfn:\n"
"stvx %v31,%r12,%r0;\n"
"lvx %v20,%r12,%r0;\n"
"vcipher %v0, %v1, %v22;\n"
"lxvw4x %vs32, %r0, %r1;\n"
"vadduwm %v0, %v1, %v22;\n"
"vshasigmaw %v0, %v1, 0, 15;\n"
"vshasigmad %v0, %v1, 0, 15;\n"
"vpmsumd %v11, %v11, %v11;\n"
);
]])],
[gcry_cv_gcc_inline_asm_ppc_altivec=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_ppc_altivec" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_PPC_ALTIVEC,1,
[Defined if inline assembler supports PowerPC AltiVec/VSX/crypto instructions])
fi
#
# Check whether GCC inline assembler supports PowerISA 3.00 instructions
#
AC_CACHE_CHECK([whether GCC inline assembler supports PowerISA 3.00 instructions],
[gcry_cv_gcc_inline_asm_ppc_arch_3_00],
[if test "$mpi_cpu_arch" != "ppc" ; then
gcry_cv_gcc_inline_asm_ppc_arch_3_00="n/a"
else
gcry_cv_gcc_inline_asm_ppc_arch_3_00=no
AC_COMPILE_IFELSE([AC_LANG_SOURCE(
[[__asm__(".globl testfn;\n"
"testfn:\n"
"stxvb16x %r1,%v12,%v30;\n"
);
]])],
[gcry_cv_gcc_inline_asm_ppc_arch_3_00=yes])
fi])
if test "$gcry_cv_gcc_inline_asm_ppc_arch_3_00" = "yes" ; then
AC_DEFINE(HAVE_GCC_INLINE_ASM_PPC_ARCH_3_00,1,
[Defined if inline assembler supports PowerISA 3.00 instructions])
fi
#######################################
#### Checks for library functions. ####
#######################################
AC_FUNC_VPRINTF
# We have replacements for these in src/missing-string.c
AC_CHECK_FUNCS(stpcpy strcasecmp)
# We have replacements for these in src/g10lib.h
AC_CHECK_FUNCS(strtoul memmove stricmp atexit raise)
# Other checks
AC_CHECK_FUNCS(strerror rand mmap getpagesize sysconf waitpid wait4)
AC_CHECK_FUNCS(gettimeofday getrusage gethrtime clock_gettime syslog)
AC_CHECK_FUNCS(syscall fcntl ftruncate flockfile getauxval elf_aux_info)
AC_CHECK_FUNCS(explicit_bzero explicit_memset getentropy)
GNUPG_CHECK_MLOCK
#
# Replacement functions.
#
AC_REPLACE_FUNCS([getpid clock])
#
# Check whether it is necessary to link against libdl.
#
DL_LIBS=""
if test "$use_hmac_binary_check" = yes ; then
_gcry_save_libs="$LIBS"
LIBS=""
AC_SEARCH_LIBS(dlopen, c dl,,,)
DL_LIBS=$LIBS
LIBS="$_gcry_save_libs"
LIBGCRYPT_CONFIG_LIBS="${LIBGCRYPT_CONFIG_LIBS} ${DL_LIBS}"
fi
AC_SUBST(DL_LIBS)
#
# Check whether we can use Linux capabilities as requested.
#
if test "$use_capabilities" = "yes" ; then
use_capabilities=no
AC_CHECK_HEADERS(sys/capability.h)
if test "$ac_cv_header_sys_capability_h" = "yes" ; then
AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1)
if test "$ac_cv_lib_cap_cap_init" = "yes"; then
AC_DEFINE(USE_CAPABILITIES,1,
[define if capabilities should be used])
LIBS="$LIBS -lcap"
use_capabilities=yes
fi
fi
if test "$use_capabilities" = "no" ; then
AC_MSG_WARN([[
***
*** The use of capabilities on this system is not possible.
*** You need a recent Linux kernel and some patches:
*** fcaps-2.2.9-990610.patch (kernel patch for 2.2.9)
*** fcap-module-990613.tar.gz (kernel module)
*** libcap-1.92.tar.gz (user mode library and utilities)
*** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN
*** set (filesystems menu). Be warned: This code is *really* ALPHA.
***]])
fi
fi
# Check whether a random device is available.
if test "$try_dev_random" = yes ; then
AC_CACHE_CHECK(for random device, ac_cv_have_dev_random,
[if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then
ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi])
if test "$ac_cv_have_dev_random" = yes; then
AC_DEFINE(HAVE_DEV_RANDOM,1,
[defined if the system supports a random device] )
fi
else
AC_MSG_CHECKING(for random device)
ac_cv_have_dev_random=no
AC_MSG_RESULT(has been disabled)
fi
# Figure out the random modules for this configuration.
if test "$random" = "default"; then
# Select default value.
if test "$ac_cv_have_dev_random" = yes; then
# Try Linuxish random device.
random_modules="linux"
else
case "${host}" in
*-*-mingw32ce*)
# WindowsCE random device.
random_modules="w32ce"
;;
*-*-mingw32*|*-*-cygwin*)
# Windows random device.
random_modules="w32"
;;
*)
# Build everything, allow to select at runtime.
random_modules="$auto_random_modules"
;;
esac
fi
else
if test "$random" = "auto"; then
# Build everything, allow to select at runtime.
random_modules="$auto_random_modules"
else
random_modules="$random"
fi
fi
#
# Other defines
#
if test mym4_isgit = "yes"; then
AC_DEFINE(IS_DEVELOPMENT_VERSION,1,
[Defined if this is not a regular release])
fi
AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes)
# This is handy for debugging so the compiler doesn't rearrange
# things and eliminate variables.
AC_ARG_ENABLE(optimization,
AC_HELP_STRING([--disable-optimization],
[disable compiler optimization]),
[if test $enableval = no ; then
CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'`
fi])
AC_MSG_NOTICE([checking for cc features])
# CFLAGS mangling when using gcc.
if test "$GCC" = yes; then
AC_MSG_CHECKING([if gcc supports -fno-delete-null-pointer-checks])
_gcc_cflags_save=$CFLAGS
CFLAGS="-fno-delete-null-pointer-checks"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
CFLAGS=$_gcc_cflags_save;
if test x"$_gcc_wopt" = xyes ; then
CFLAGS="$CFLAGS -fno-delete-null-pointer-checks"
fi
CFLAGS="$CFLAGS -Wall"
if test "$USE_MAINTAINER_MODE" = "yes"; then
CFLAGS="$CFLAGS -Wcast-align -Wshadow -Wstrict-prototypes"
CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
# If -Wno-missing-field-initializers is supported we can enable a
# a bunch of really useful warnings.
AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wno-missing-field-initializers"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
CFLAGS=$_gcc_cflags_save;
if test x"$_gcc_wopt" = xyes ; then
CFLAGS="$CFLAGS -W -Wextra -Wbad-function-cast"
CFLAGS="$CFLAGS -Wwrite-strings"
CFLAGS="$CFLAGS -Wdeclaration-after-statement"
CFLAGS="$CFLAGS -Wno-missing-field-initializers"
CFLAGS="$CFLAGS -Wno-sign-compare"
fi
AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
_gcc_cflags_save=$CFLAGS
CFLAGS="-Wpointer-arith"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
AC_MSG_RESULT($_gcc_wopt)
CFLAGS=$_gcc_cflags_save;
if test x"$_gcc_wopt" = xyes ; then
CFLAGS="$CFLAGS -Wpointer-arith"
fi
fi
fi
# Check whether as(1) supports a noeexecstack feature. This test
# includes an override option.
CL_AS_NOEXECSTACK
AC_SUBST(LIBGCRYPT_CONFIG_API_VERSION)
AC_SUBST(LIBGCRYPT_CONFIG_LIBS)
AC_SUBST(LIBGCRYPT_CONFIG_CFLAGS)
AC_SUBST(LIBGCRYPT_CONFIG_HOST)
AC_SUBST(LIBGCRYPT_THREAD_MODULES)
AC_CONFIG_COMMANDS([gcrypt-conf],[[
chmod +x src/libgcrypt-config
]],[[
prefix=$prefix
exec_prefix=$exec_prefix
libdir=$libdir
datadir=$datadir
DATADIRNAME=$DATADIRNAME
]])
#####################
#### Conclusion. ####
#####################
# Check that requested feature can actually be used and define
# ENABLE_foo_SUPPORT macros.
if test x"$aesnisupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_ssse3" != "yes" ; then
aesnisupport="no (unsupported by compiler)"
fi
fi
if test x"$shaextsupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_shaext" != "yes" ; then
shaextsupport="no (unsupported by compiler)"
fi
fi
if test x"$pclmulsupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_pclmul" != "yes" ; then
pclmulsupport="no (unsupported by compiler)"
fi
fi
if test x"$sse41support" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_sse41" != "yes" ; then
sse41support="no (unsupported by compiler)"
fi
fi
if test x"$avxsupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_avx" != "yes" ; then
avxsupport="no (unsupported by compiler)"
fi
fi
if test x"$avx2support" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_avx2" != "yes" ; then
avx2support="no (unsupported by compiler)"
fi
fi
if test x"$neonsupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_neon" != "yes" ; then
if test "$gcry_cv_gcc_inline_asm_aarch64_neon" != "yes" ; then
neonsupport="no (unsupported by compiler)"
fi
fi
fi
if test x"$armcryptosupport" = xyes ; then
if test "$gcry_cv_gcc_inline_asm_aarch32_crypto" != "yes" ; then
if test "$gcry_cv_gcc_inline_asm_aarch64_crypto" != "yes" ; then
neonsupport="no (unsupported by compiler)"
fi
fi
fi
if test x"$aesnisupport" = xyes ; then
AC_DEFINE(ENABLE_AESNI_SUPPORT, 1,
[Enable support for Intel AES-NI instructions.])
fi
if test x"$shaextsupport" = xyes ; then
AC_DEFINE(ENABLE_SHAEXT_SUPPORT, 1,
[Enable support for Intel SHAEXT instructions.])
fi
if test x"$pclmulsupport" = xyes ; then
AC_DEFINE(ENABLE_PCLMUL_SUPPORT, 1,
[Enable support for Intel PCLMUL instructions.])
fi
if test x"$sse41support" = xyes ; then
AC_DEFINE(ENABLE_SSE41_SUPPORT, 1,
[Enable support for Intel SSE4.1 instructions.])
fi
if test x"$avxsupport" = xyes ; then
AC_DEFINE(ENABLE_AVX_SUPPORT,1,
[Enable support for Intel AVX instructions.])
fi
if test x"$avx2support" = xyes ; then
AC_DEFINE(ENABLE_AVX2_SUPPORT,1,
[Enable support for Intel AVX2 instructions.])
fi
if test x"$neonsupport" = xyes ; then
AC_DEFINE(ENABLE_NEON_SUPPORT,1,
[Enable support for ARM NEON instructions.])
fi
if test x"$armcryptosupport" = xyes ; then
AC_DEFINE(ENABLE_ARM_CRYPTO_SUPPORT,1,
[Enable support for ARMv8 Crypto Extension instructions.])
fi
if test x"$ppccryptosupport" = xyes ; then
AC_DEFINE(ENABLE_PPC_CRYPTO_SUPPORT,1,
[Enable support for POWER 8 (PowerISA 2.07) crypto extension.])
fi
if test x"$jentsupport" = xyes ; then
AC_DEFINE(ENABLE_JENT_SUPPORT, 1,
[Enable support for the jitter entropy collector.])
fi
if test x"$padlocksupport" = xyes ; then
AC_DEFINE(ENABLE_PADLOCK_SUPPORT, 1,
[Enable support for the PadLock engine.])
fi
if test x"$drngsupport" = xyes ; then
AC_DEFINE(ENABLE_DRNG_SUPPORT, 1,
[Enable support for Intel DRNG (RDRAND instruction).])
fi
# Define conditional sources and config.h symbols depending on the
# selected ciphers, pubkey-ciphers, digests, kdfs, and random modules.
LIST_MEMBER(arcfour, $enabled_ciphers)
if test "$found" = "1"; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour.lo"
AC_DEFINE(USE_ARCFOUR, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS arcfour-amd64.lo"
;;
esac
fi
LIST_MEMBER(blowfish, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish.lo"
AC_DEFINE(USE_BLOWFISH, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-amd64.lo"
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS blowfish-arm.lo"
;;
esac
fi
LIST_MEMBER(cast5, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5.lo"
AC_DEFINE(USE_CAST5, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-amd64.lo"
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS cast5-arm.lo"
;;
esac
fi
LIST_MEMBER(des, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS des.lo"
AC_DEFINE(USE_DES, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS des-amd64.lo"
;;
esac
fi
LIST_MEMBER(aes, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael.lo"
AC_DEFINE(USE_AES, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-amd64.lo"
# Build with the SSSE3 implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ssse3-amd64.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ssse3-amd64-asm.lo"
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-arm.lo"
# Build with the ARMv8/AArch32 CE implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-ce.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-aarch32-ce.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aarch64.lo"
# Build with the ARMv8/AArch64 CE implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-ce.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-armv8-aarch64-ce.lo"
;;
powerpc64le-*-*)
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ppc.lo"
;;
powerpc64-*-*)
# Big-Endian.
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ppc.lo"
;;
powerpc-*-*)
# Big-Endian.
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-ppc.lo"
;;
esac
case "$mpi_cpu_arch" in
x86)
# Build with the AES-NI implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-aesni.lo"
# Build with the Padlock implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rijndael-padlock.lo"
;;
esac
fi
LIST_MEMBER(twofish, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish.lo"
AC_DEFINE(USE_TWOFISH, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-amd64.lo"
if test x"$avx2support" = xyes ; then
# Build with the AVX2 implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-avx2-amd64.lo"
fi
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-arm.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS twofish-aarch64.lo"
;;
esac
fi
LIST_MEMBER(serpent, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent.lo"
AC_DEFINE(USE_SERPENT, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the SSE2 implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-sse2-amd64.lo"
;;
esac
if test x"$avx2support" = xyes ; then
# Build with the AVX2 implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-avx2-amd64.lo"
fi
if test x"$neonsupport" = xyes ; then
# Build with the NEON implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS serpent-armv7-neon.lo"
fi
fi
LIST_MEMBER(rfc2268, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS rfc2268.lo"
AC_DEFINE(USE_RFC2268, 1, [Defined if this module should be included])
fi
LIST_MEMBER(seed, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS seed.lo"
AC_DEFINE(USE_SEED, 1, [Defined if this module should be included])
fi
LIST_MEMBER(camellia, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia.lo camellia-glue.lo"
AC_DEFINE(USE_CAMELLIA, 1, [Defined if this module should be included])
case "${host}" in
arm*-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-arm.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aarch64.lo"
;;
esac
if test x"$avxsupport" = xyes ; then
if test x"$aesnisupport" = xyes ; then
# Build with the AES-NI/AVX implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx-amd64.lo"
fi
fi
if test x"$avx2support" = xyes ; then
if test x"$aesnisupport" = xyes ; then
# Build with the AES-NI/AVX2 implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS camellia-aesni-avx2-amd64.lo"
fi
fi
fi
LIST_MEMBER(idea, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS idea.lo"
AC_DEFINE(USE_IDEA, 1, [Defined if this module should be included])
fi
LIST_MEMBER(salsa20, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20.lo"
AC_DEFINE(USE_SALSA20, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20-amd64.lo"
;;
esac
if test x"$neonsupport" = xyes ; then
# Build with the NEON implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS salsa20-armv7-neon.lo"
fi
fi
LIST_MEMBER(gost28147, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS gost28147.lo"
AC_DEFINE(USE_GOST28147, 1, [Defined if this module should be included])
fi
LIST_MEMBER(chacha20, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20.lo"
AC_DEFINE(USE_CHACHA20, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-amd64-ssse3.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-amd64-avx2.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-aarch64.lo"
;;
powerpc64le-*-*)
# Build with the ppc8 vector implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ppc.lo"
;;
powerpc64-*-*)
# Build with the ppc8 vector implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ppc.lo"
;;
powerpc-*-*)
# Build with the ppc8 vector implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ppc.lo"
;;
esac
if test x"$neonsupport" = xyes ; then
# Build with the NEON implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-armv7-neon.lo"
fi
fi
LIST_MEMBER(dsa, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo"
AC_DEFINE(USE_DSA, 1, [Defined if this module should be included])
fi
LIST_MEMBER(rsa, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS rsa.lo"
AC_DEFINE(USE_RSA, 1, [Defined if this module should be included])
fi
LIST_MEMBER(elgamal, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS elgamal.lo"
AC_DEFINE(USE_ELGAMAL, 1, [Defined if this module should be included])
fi
LIST_MEMBER(ecc, $enabled_pubkey_ciphers)
if test "$found" = "1" ; then
GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS \
ecc.lo ecc-curves.lo ecc-misc.lo \
ecc-ecdh.lo ecc-ecdsa.lo ecc-eddsa.lo ecc-gost.lo"
AC_DEFINE(USE_ECC, 1, [Defined if this module should be included])
fi
LIST_MEMBER(crc, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc.lo"
AC_DEFINE(USE_CRC, 1, [Defined if this module should be included])
case "${host}" in
i?86-*-* | x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS crc-intel-pclmul.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-armv8-ce.lo"
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-armv8-aarch64-ce.lo"
;;
powerpc64le-*-*)
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-ppc.lo"
;;
powerpc64-*-*)
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-ppc.lo"
;;
powerpc-*-*)
GCRYPT_CIPHERS="$GCRYPT_CIPHERS crc-ppc.lo"
;;
esac
fi
LIST_MEMBER(gostr3411-94, $enabled_digests)
if test "$found" = "1" ; then
# GOST R 34.11-94 internally uses GOST 28147-89
LIST_MEMBER(gost28147, $enabled_ciphers)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS gostr3411-94.lo"
AC_DEFINE(USE_GOST_R_3411_94, 1, [Defined if this module should be included])
fi
fi
LIST_MEMBER(stribog, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS stribog.lo"
AC_DEFINE(USE_GOST_R_3411_12, 1, [Defined if this module should be included])
fi
LIST_MEMBER(md2, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS md2.lo"
AC_DEFINE(USE_MD2, 1, [Defined if this module should be included])
fi
LIST_MEMBER(md4, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS md4.lo"
AC_DEFINE(USE_MD4, 1, [Defined if this module should be included])
fi
LIST_MEMBER(md5, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS md5.lo"
AC_DEFINE(USE_MD5, 1, [Defined if this module should be included])
fi
LIST_MEMBER(rmd160, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS rmd160.lo"
AC_DEFINE(USE_RMD160, 1, [Defined if this module should be included])
fi
LIST_MEMBER(sha256, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256.lo"
AC_DEFINE(USE_SHA256, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-ssse3-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-avx-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-avx2-bmi2-amd64.lo"
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-armv8-aarch32-ce.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-armv8-aarch64-ce.lo"
;;
powerpc64le-*-*)
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS sha256-ppc.lo"
;;
powerpc64-*-*)
# Big-Endian.
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS sha256-ppc.lo"
;;
powerpc-*-*)
# Big-Endian.
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS sha256-ppc.lo"
esac
case "$mpi_cpu_arch" in
x86)
# Build with the SHAEXT implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha256-intel-shaext.lo"
;;
esac
fi
LIST_MEMBER(sha512, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512.lo"
AC_DEFINE(USE_SHA512, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-ssse3-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-avx2-bmi2-amd64.lo"
;;
i?86-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-ssse3-i386.lo"
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-arm.lo"
;;
powerpc64le-*-*)
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS sha512-ppc.lo"
;;
powerpc64-*-*)
# Big-Endian.
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS sha512-ppc.lo"
;;
powerpc-*-*)
# Big-Endian.
# Build with the crypto extension implementation
GCRYPT_CIPHERS="$GCRYPT_CIPHERS sha512-ppc.lo"
esac
if test x"$neonsupport" = xyes ; then
# Build with the NEON implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha512-armv7-neon.lo"
fi
fi
LIST_MEMBER(sha3, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak.lo"
AC_DEFINE(USE_SHA3, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
:
;;
esac
if test x"$neonsupport" = xyes ; then
# Build with the NEON implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak-armv7-neon.lo"
fi
fi
LIST_MEMBER(tiger, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS tiger.lo"
AC_DEFINE(USE_TIGER, 1, [Defined if this module should be included])
fi
LIST_MEMBER(whirlpool, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool.lo"
AC_DEFINE(USE_WHIRLPOOL, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS whirlpool-sse2-amd64.lo"
;;
esac
fi
LIST_MEMBER(blake2, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS blake2.lo"
AC_DEFINE(USE_BLAKE2, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS blake2b-amd64-avx2.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS blake2s-amd64-avx.lo"
;;
esac
fi
# SHA-1 needs to be included always for example because it is used by
# random-csprng.c.
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1.lo"
AC_DEFINE(USE_SHA1, 1, [Defined if this module should be included])
case "${host}" in
x86_64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-ssse3-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx-bmi2-amd64.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-avx2-bmi2-amd64.lo"
;;
arm*-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv7-neon.lo"
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch32-ce.lo"
;;
aarch64-*-*)
# Build with the assembly implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-armv8-aarch64-ce.lo"
;;
esac
case "$mpi_cpu_arch" in
x86)
# Build with the SHAEXT implementation
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sha1-intel-shaext.lo"
;;
esac
LIST_MEMBER(sm3, $enabled_digests)
if test "$found" = "1" ; then
GCRYPT_DIGESTS="$GCRYPT_DIGESTS sm3.lo"
AC_DEFINE(USE_SM3, 1, [Defined if this module should be included])
fi
LIST_MEMBER(scrypt, $enabled_kdfs)
if test "$found" = "1" ; then
GCRYPT_KDFS="$GCRYPT_KDFS scrypt.lo"
AC_DEFINE(USE_SCRYPT, 1, [Defined if this module should be included])
fi
LIST_MEMBER(linux, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndlinux.lo"
AC_DEFINE(USE_RNDLINUX, 1, [Defined if the /dev/random RNG should be used.])
fi
LIST_MEMBER(unix, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndunix.lo"
AC_DEFINE(USE_RNDUNIX, 1, [Defined if the default Unix RNG should be used.])
fi
LIST_MEMBER(egd, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndegd.lo"
AC_DEFINE(USE_RNDEGD, 1, [Defined if the EGD based RNG should be used.])
fi
LIST_MEMBER(w32, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32.lo"
AC_DEFINE(USE_RNDW32, 1,
[Defined if the Windows specific RNG should be used.])
fi
LIST_MEMBER(w32ce, $random_modules)
if test "$found" = "1" ; then
GCRYPT_RANDOM="$GCRYPT_RANDOM rndw32ce.lo"
AC_DEFINE(USE_RNDW32CE, 1,
[Defined if the WindowsCE specific RNG should be used.])
fi
AC_SUBST([GCRYPT_CIPHERS])
AC_SUBST([GCRYPT_PUBKEY_CIPHERS])
AC_SUBST([GCRYPT_DIGESTS])
AC_SUBST([GCRYPT_KDFS])
AC_SUBST([GCRYPT_RANDOM])
AC_SUBST(LIBGCRYPT_CIPHERS, $enabled_ciphers)
AC_SUBST(LIBGCRYPT_PUBKEY_CIPHERS, $enabled_pubkey_ciphers)
AC_SUBST(LIBGCRYPT_DIGESTS, $enabled_digests)
# For printing the configuration we need a colon separated list of
# algorithm names.
tmp=`echo "$enabled_ciphers" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_CIPHERS, "$tmp",
[List of available cipher algorithms])
tmp=`echo "$enabled_pubkey_ciphers" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_PUBKEY_CIPHERS, "$tmp",
[List of available public key cipher algorithms])
tmp=`echo "$enabled_digests" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_DIGESTS, "$tmp",
[List of available digest algorithms])
tmp=`echo "$enabled_kdfs" | tr ' ' : `
AC_DEFINE_UNQUOTED(LIBGCRYPT_KDFS, "$tmp",
[List of available KDF algorithms])
#
# Define conditional sources depending on the used hardware platform.
# Note that all possible modules must also be listed in
# src/Makefile.am (EXTRA_libgcrypt_la_SOURCES).
#
GCRYPT_HWF_MODULES=
case "$mpi_cpu_arch" in
x86)
AC_DEFINE(HAVE_CPU_ARCH_X86, 1, [Defined for the x86 platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-x86.lo"
;;
alpha)
AC_DEFINE(HAVE_CPU_ARCH_ALPHA, 1, [Defined for Alpha platforms])
;;
sparc)
AC_DEFINE(HAVE_CPU_ARCH_SPARC, 1, [Defined for SPARC platforms])
;;
mips)
AC_DEFINE(HAVE_CPU_ARCH_MIPS, 1, [Defined for MIPS platforms])
;;
m68k)
AC_DEFINE(HAVE_CPU_ARCH_M68K, 1, [Defined for M68k platforms])
;;
ppc)
AC_DEFINE(HAVE_CPU_ARCH_PPC, 1, [Defined for PPC platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-ppc.lo"
;;
arm)
AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-arm.lo"
;;
aarch64)
AC_DEFINE(HAVE_CPU_ARCH_ARM, 1, [Defined for ARM AArch64 platforms])
GCRYPT_HWF_MODULES="libgcrypt_la-hwf-arm.lo"
;;
esac
AC_SUBST([GCRYPT_HWF_MODULES])
#
# Option to disable building of doc file
#
build_doc=yes
AC_ARG_ENABLE([doc], AC_HELP_STRING([--disable-doc],
[do not build the documentation]),
build_doc=$enableval, build_doc=yes)
AM_CONDITIONAL([BUILD_DOC], [test "x$build_doc" != xno])
#
# Provide information about the build.
#
BUILD_REVISION="mym4_revision"
AC_SUBST(BUILD_REVISION)
AC_DEFINE_UNQUOTED(BUILD_REVISION, "$BUILD_REVISION",
[GIT commit id revision used to build this package])
changequote(,)dnl
BUILD_VERSION=`echo "$PACKAGE_VERSION" | sed 's/\([0-9.]*\).*/\1./'`
changequote([,])dnl
BUILD_VERSION="${BUILD_VERSION}mym4_revision_dec"
BUILD_FILEVERSION=`echo "${BUILD_VERSION}" | tr . ,`
AC_SUBST(BUILD_VERSION)
AC_SUBST(BUILD_FILEVERSION)
AC_ARG_ENABLE([build-timestamp],
AC_HELP_STRING([--enable-build-timestamp],
[set an explicit build timestamp for reproducibility.
(default is the current time in ISO-8601 format)]),
[if test "$enableval" = "yes"; then
BUILD_TIMESTAMP=`date -u +%Y-%m-%dT%H:%M+0000 2>/dev/null || date`
else
BUILD_TIMESTAMP="$enableval"
fi],
[BUILD_TIMESTAMP=""])
AC_SUBST(BUILD_TIMESTAMP)
AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
[The time this package was configured for a build])
# And create the files.
AC_CONFIG_FILES([
Makefile
m4/Makefile
compat/Makefile
mpi/Makefile
cipher/Makefile
random/Makefile
doc/Makefile
src/Makefile
src/gcrypt.h
src/libgcrypt-config
src/libgcrypt.pc
src/versioninfo.rc
tests/Makefile
])
AC_CONFIG_FILES([tests/hashtest-256g], [chmod +x tests/hashtest-256g])
AC_CONFIG_FILES([tests/basic-disable-all-hwf], [chmod +x tests/basic-disable-all-hwf])
AC_OUTPUT
detection_module="${GCRYPT_HWF_MODULES%.lo}"
test -n "$detection_module" || detection_module="none"
# Give some feedback
GCRY_MSG_SHOW([],[])
GCRY_MSG_SHOW([Libgcrypt],[v${VERSION} has been configured as follows:])
GCRY_MSG_SHOW([],[])
GCRY_MSG_SHOW([Platform: ],[$PRINTABLE_OS_NAME ($host)])
GCRY_MSG_SHOW([Hardware detection module:],[$detection_module])
GCRY_MSG_WRAP([Enabled cipher algorithms:],[$enabled_ciphers])
GCRY_MSG_WRAP([Enabled digest algorithms:],[$enabled_digests])
GCRY_MSG_WRAP([Enabled kdf algorithms: ],[$enabled_kdfs])
GCRY_MSG_WRAP([Enabled pubkey algorithms:],[$enabled_pubkey_ciphers])
GCRY_MSG_SHOW([Random number generator: ],[$random])
GCRY_MSG_SHOW([Try using jitter entropy: ],[$jentsupport])
GCRY_MSG_SHOW([Using linux capabilities: ],[$use_capabilities])
GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport])
GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport])
GCRY_MSG_SHOW([Try using Intel SHAEXT: ],[$shaextsupport])
GCRY_MSG_SHOW([Try using Intel PCLMUL: ],[$pclmulsupport])
GCRY_MSG_SHOW([Try using Intel SSE4.1: ],[$sse41support])
GCRY_MSG_SHOW([Try using DRNG (RDRAND): ],[$drngsupport])
GCRY_MSG_SHOW([Try using Intel AVX: ],[$avxsupport])
GCRY_MSG_SHOW([Try using Intel AVX2: ],[$avx2support])
GCRY_MSG_SHOW([Try using ARM NEON: ],[$neonsupport])
GCRY_MSG_SHOW([Try using ARMv8 crypto: ],[$armcryptosupport])
GCRY_MSG_SHOW([Try using PPC crypto: ],[$ppccryptosupport])
GCRY_MSG_SHOW([],[])
if test "x${gpg_config_script_warn}" != x; then
cat <
#include
#include
#include "mpi-internal.h"
#include "longlong.h"
#include "g10lib.h"
void
_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
{
int divisor_sign = divisor->sign;
gcry_mpi_t temp_divisor = NULL;
/* We need the original value of the divisor after the remainder has been
* preliminary calculated. We have to copy it to temporary space if it's
* the same variable as REM. */
if( rem == divisor ) {
temp_divisor = mpi_copy( divisor );
divisor = temp_divisor;
}
_gcry_mpi_tdiv_r( rem, dividend, divisor );
if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
mpi_add (rem, rem, divisor);
if( temp_divisor )
mpi_free(temp_divisor);
}
/****************
* Division rounding the quotient towards -infinity.
* The remainder gets the same sign as the denominator.
* rem is optional
*/
-ulong
-_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor )
+unsigned long
+_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend,
+ unsigned long divisor )
{
mpi_limb_t rlimb;
rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
if( rlimb && dividend->sign )
rlimb = divisor - rlimb;
if( rem ) {
rem->d[0] = rlimb;
rem->nlimbs = rlimb? 1:0;
}
return rlimb;
}
void
_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor )
{
gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) );
_gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor);
mpi_free(tmp);
}
void
_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
{
int divisor_sign = divisor->sign;
gcry_mpi_t temp_divisor = NULL;
if( quot == divisor || rem == divisor ) {
temp_divisor = mpi_copy( divisor );
divisor = temp_divisor;
}
_gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );
if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
mpi_sub_ui( quot, quot, 1 );
mpi_add( rem, rem, divisor);
}
if( temp_divisor )
mpi_free(temp_divisor);
}
/* If den == quot, den needs temporary storage.
* If den == rem, den needs temporary storage.
* If num == quot, num needs temporary storage.
* If den has temporary storage, it can be normalized while being copied,
* i.e no extra storage should be allocated.
*/
void
_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
{
_gcry_mpi_tdiv_qr(NULL, rem, num, den );
}
void
_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
{
mpi_ptr_t np, dp;
mpi_ptr_t qp, rp;
mpi_size_t nsize = num->nlimbs;
mpi_size_t dsize = den->nlimbs;
mpi_size_t qsize, rsize;
mpi_size_t sign_remainder = num->sign;
mpi_size_t sign_quotient = num->sign ^ den->sign;
unsigned normalization_steps;
mpi_limb_t q_limb;
mpi_ptr_t marker[5];
unsigned int marker_nlimbs[5];
int markidx=0;
/* Ensure space is enough for quotient and remainder.
* We need space for an extra limb in the remainder, because it's
* up-shifted (normalized) below. */
rsize = nsize + 1;
mpi_resize( rem, rsize);
qsize = rsize - dsize; /* qsize cannot be bigger than this. */
if( qsize <= 0 ) {
if( num != rem ) {
rem->nlimbs = num->nlimbs;
rem->sign = num->sign;
MPN_COPY(rem->d, num->d, nsize);
}
if( quot ) {
/* This needs to follow the assignment to rem, in case the
* numerator and quotient are the same. */
quot->nlimbs = 0;
quot->sign = 0;
}
return;
}
if( quot )
mpi_resize( quot, qsize);
/* Read pointers here, when reallocation is finished. */
np = num->d;
dp = den->d;
rp = rem->d;
/* Optimize division by a single-limb divisor. */
if( dsize == 1 ) {
mpi_limb_t rlimb;
if( quot ) {
qp = quot->d;
rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] );
qsize -= qp[qsize - 1] == 0;
quot->nlimbs = qsize;
quot->sign = sign_quotient;
}
else
rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] );
rp[0] = rlimb;
rsize = rlimb != 0?1:0;
rem->nlimbs = rsize;
rem->sign = sign_remainder;
return;
}
if( quot ) {
qp = quot->d;
/* Make sure QP and NP point to different objects. Otherwise the
* numerator would be gradually overwritten by the quotient limbs. */
if(qp == np) { /* Copy NP object to temporary space. */
marker_nlimbs[markidx] = nsize;
np = marker[markidx++] = mpi_alloc_limb_space(nsize,
mpi_is_secure(quot));
MPN_COPY(np, qp, nsize);
}
}
else /* Put quotient at top of remainder. */
qp = rp + dsize;
count_leading_zeros( normalization_steps, dp[dsize - 1] );
/* Normalize the denominator, i.e. make its most significant bit set by
* shifting it NORMALIZATION_STEPS bits to the left. Also shift the
* numerator the same number of steps (to keep the quotient the same!).
*/
if( normalization_steps ) {
mpi_ptr_t tp;
mpi_limb_t nlimb;
/* Shift up the denominator setting the most significant bit of
* the most significant word. Use temporary storage not to clobber
* the original contents of the denominator. */
marker_nlimbs[markidx] = dsize;
tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
_gcry_mpih_lshift( tp, dp, dsize, normalization_steps );
dp = tp;
/* Shift up the numerator, possibly introducing a new most
* significant word. Move the shifted numerator in the remainder
* meanwhile. */
nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps);
if( nlimb ) {
rp[nsize] = nlimb;
rsize = nsize + 1;
}
else
rsize = nsize;
}
else {
/* The denominator is already normalized, as required. Copy it to
* temporary space if it overlaps with the quotient or remainder. */
if( dp == rp || (quot && (dp == qp))) {
mpi_ptr_t tp;
marker_nlimbs[markidx] = dsize;
tp = marker[markidx++] = mpi_alloc_limb_space(dsize,
mpi_is_secure(den));
MPN_COPY( tp, dp, dsize );
dp = tp;
}
/* Move the numerator to the remainder. */
if( rp != np )
MPN_COPY(rp, np, nsize);
rsize = nsize;
}
q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize );
if( quot ) {
qsize = rsize - dsize;
if(q_limb) {
qp[qsize] = q_limb;
qsize += 1;
}
quot->nlimbs = qsize;
quot->sign = sign_quotient;
}
rsize = dsize;
MPN_NORMALIZE (rp, rsize);
if( normalization_steps && rsize ) {
_gcry_mpih_rshift(rp, rp, rsize, normalization_steps);
rsize -= rp[rsize - 1] == 0?1:0;
}
rem->nlimbs = rsize;
rem->sign = sign_remainder;
while( markidx )
{
markidx--;
_gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]);
}
}
void
_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count )
{
mpi_size_t usize, wsize;
mpi_size_t limb_cnt;
usize = u->nlimbs;
limb_cnt = count / BITS_PER_MPI_LIMB;
wsize = usize - limb_cnt;
if( limb_cnt >= usize )
w->nlimbs = 0;
else {
mpi_ptr_t wp;
mpi_ptr_t up;
RESIZE_IF_NEEDED( w, wsize );
wp = w->d;
up = u->d;
count %= BITS_PER_MPI_LIMB;
if( count ) {
_gcry_mpih_rshift( wp, up + limb_cnt, wsize, count );
wsize -= !wp[wsize - 1];
}
else {
MPN_COPY_INCR( wp, up + limb_cnt, wsize);
}
w->nlimbs = wsize;
}
}
/****************
* Check whether dividend is divisible by divisor
* (note: divisor must fit into a limb)
*/
int
-_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
+_gcry_mpi_divisible_ui(gcry_mpi_t dividend, unsigned long divisor )
{
return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
}
void
_gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend,
gcry_mpi_t divisor, int round)
{
if (!round)
{
if (!rem)
{
gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot));
_gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor);
mpi_free (tmp);
}
else
_gcry_mpi_tdiv_qr (quot, rem, dividend, divisor);
}
else if (round < 0)
{
if (!rem)
_gcry_mpi_fdiv_q (quot, dividend, divisor);
else if (!quot)
_gcry_mpi_fdiv_r (rem, dividend, divisor);
else
_gcry_mpi_fdiv_qr (quot, rem, dividend, divisor);
}
else
log_bug ("mpi rounding to ceiling not yet implemented\n");
}
diff --git a/random/rndunix.c b/random/rndunix.c
index fcb45b78..aff2f85d 100644
--- a/random/rndunix.c
+++ b/random/rndunix.c
@@ -1,937 +1,937 @@
/****************************************************************************
* *
* *
* Unix Randomness-Gathering Code *
* *
* Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. *
* Heavily modified for GnuPG by Werner Koch *
* *
* *
****************************************************************************/
/* This module is part of the cryptlib continuously seeded pseudorandom
number generator. For usage conditions, see lib_rand.c
[Here is the notice from lib_rand.c:]
This module and the misc/rnd*.c modules represent the cryptlib
continuously seeded pseudorandom number generator (CSPRNG) as described in
my 1998 Usenix Security Symposium paper "The generation of random numbers
for cryptographic purposes".
The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
modules and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice
and this permission notice in its entirety.
2. Redistributions in binary form must reproduce the copyright notice in
the documentation and/or other materials provided with the distribution.
3. A copy of any bugfixes or enhancements made must be provided to the
author, to allow them to be added to the
baseline version of the code.
ALTERNATIVELY, the code may be distributed under the terms of the
GNU Lesser General Public License, version 2.1 or any later version
published by the Free Software Foundation, in which case the
provisions of the GNU LGPL are required INSTEAD OF the above
restrictions.
Although not required under the terms of the LGPL, it would still be
nice if you could make any changes available to the author to allow
a consistent code base to be maintained. */
/*************************************************************************
The above alternative was changed from GPL to LGPL on 2007-08-22 with
permission from Peter Gutmann:
==========
From: pgut001
Subject: Re: LGPL for the windows entropy gatherer
To: wk@gnupg.org
Date: Wed, 22 Aug 2007 03:05:42 +1200
Hi,
>As of now libgcrypt is GPL under Windows due to that module and some people
>would really like to see it under LGPL too. Can you do such a license change
>to LGPL version 2? Note that LGPL give the user the option to relicense it
>under GPL, so the change would be pretty easy and backwar compatible.
Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy
code as well, but Ian asked for LGPL as an option so as of the next release
I'll have LGPL in there. You can consider it to be retroactive, so your
current version will be LGPLd as well.
Peter.
==========
From: pgut001
Subject: Re: LGPL for the windows entropy gatherer
To: wk@gnupg.org
Date: Wed, 22 Aug 2007 20:50:08 +1200
>Would you mind to extend this also to the Unix entropy gatherer which is
>still used on systems without /dev/random and when EGD is not installed? That
>would be the last GPLed piece in Libgcrypt.
Sure, it covers the entire entropy-gathering subsystem.
Peter.
=========
*/
/* General includes */
#include
#include
#include
#ifdef HAVE_STDINT_H
# include
#endif
#include
/* OS-specific includes */
#ifdef __osf__
/* Somewhere in the morass of system-specific cruft which OSF/1 pulls in
* via the following includes are various endianness defines, so we
* undefine the cryptlib ones, which aren't really needed for this module
* anyway */
#undef BIG_ENDIAN
#undef LITTLE_ENDIAN
#endif /* __osf__ */
#include
#include
#include
#ifndef __QNX__
#include
#include
#endif /* __QNX__ */
#include /* SCO and SunOS need this before resource.h */
#ifndef __QNX__
#include
#endif /* __QNX__ */
#if defined( _AIX ) || defined( __QNX__ )
#include
#endif /* _AIX */
#ifndef __QNX__
#include
#include
#include
#endif /* __QNX__ */
#include
#include /* Verschiedene komische Typen */
#if defined( __hpux ) && ( OS_VERSION == 9 )
#include
#endif /* __hpux 9.x, after that it's in unistd.h */
#include
/* #include */
#ifdef __QNX__
#include
#include
#endif /* __QNX__ */
#include
#include "types.h" /* for byte and u32 typedefs */
#include "g10lib.h"
#include "rand-internal.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
#define GATHER_BUFSIZE 49152 /* Usually about 25K are filled */
/* The structure containing information on random-data sources. Each
* record contains the source and a relative estimate of its usefulness
* (weighting) which is used to scale the number of kB of output from the
* source (total = data_bytes / usefulness). Usually the weighting is in the
* range 1-3 (or 0 for especially useless sources), resulting in a usefulness
* rating of 1...3 for each kB of source output (or 0 for the useless
* sources).
*
* If the source is constantly changing (certain types of network statistics
* have this characteristic) but the amount of output is small, the weighting
* is given as a negative value to indicate that the output should be treated
* as if a minimum of 1K of output had been obtained. If the source produces
* a lot of output then the scale factor is fractional, resulting in a
* usefulness rating of < 1 for each kB of source output.
*
* In order to provide enough randomness to satisfy the requirements for a
* slow poll, we need to accumulate at least 20 points of usefulness (a
* typical system should get about 30 points).
*
* Some potential options are missed out because of special considerations.
* pstat -i and pstat -f can produce amazing amounts of output (the record
* is 600K on an Oracle server) which floods the buffer and doesn't yield
* anything useful (apart from perhaps increasing the entropy of the vmstat
* output a bit), so we don't bother with this. pstat in general produces
* quite a bit of output, but it doesn't change much over time, so it gets
* very low weightings. netstat -s produces constantly-changing output but
* also produces quite a bit of it, so it only gets a weighting of 2 rather
* than 3. The same holds for netstat -in, which gets 1 rather than 2.
*
* Some binaries are stored in different locations on different systems so
* alternative paths are given for them. The code sorts out which one to
* run by itself, once it finds an exectable somewhere it moves on to the
* next source. The sources are arranged roughly in their order of
* usefulness, occasionally sources which provide a tiny amount of
* relatively useless data are placed ahead of ones which provide a large
* amount of possibly useful data because another 100 bytes can't hurt, and
* it means the buffer won't be swamped by one or two high-output sources.
* All the high-output sources are clustered towards the end of the list
* for this reason. Some binaries are checked for in a certain order, for
* example under Slowaris /usr/ucb/ps understands aux as an arg, but the
* others don't. Some systems have conditional defines enabling alternatives
* to commands which don't understand the usual options but will provide
* enough output (in the form of error messages) to look like they're the
* real thing, causing alternative options to be skipped (we can't check the
* return either because some commands return peculiar, non-zero status even
* when they're working correctly).
*
* In order to maximise use of the buffer, the code performs a form of run-
* length compression on its input where a repeated sequence of bytes is
* replaced by the occurrence count mod 256. Some commands output an awful
* lot of whitespace, this measure greatly increases the amount of data we
* can fit in the buffer.
*
* When we scale the weighting using the SC() macro, some preprocessors may
* give a division by zero warning for the most obvious expression
* 'weight ? 1024 / weight : 0' (and gcc 2.7.2.2 dies with a division by zero
* trap), so we define a value SC_0 which evaluates to zero when fed to
* '1024 / SC_0' */
#define SC( weight ) ( 1024 / weight ) /* Scale factor */
#define SC_0 16384 /* SC( SC_0 ) evaluates to 0 */
static struct RI {
const char *path; /* Path to check for existence of source */
const char *arg; /* Args for source */
const int usefulness; /* Usefulness of source */
FILE *pipe; /* Pipe to source as FILE * */
int pipeFD; /* Pipe to source as FD */
pid_t pid; /* pid of child for waitpid() */
int length; /* Quantity of output produced */
const int hasAlternative; /* Whether source has alt.location */
} dataSources[] = {
{ "/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 1 },
{ "/usr/bin/vmstat", "-s", SC(-3), NULL, 0, 0, 0, 0},
{ "/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 1 },
{ "/usr/bin/vmstat", "-c", SC(-3), NULL, 0, 0, 0, 0},
{ "/usr/bin/pfstat", NULL, SC(-2), NULL, 0, 0, 0, 0},
{ "/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 1 },
{ "/usr/bin/vmstat", "-i", SC(-2), NULL, 0, 0, 0, 0},
{ "/usr/ucb/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
{ "/usr/bin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1 },
{ "/usr/sbin/netstat", "-s", SC(2), NULL, 0, 0, 0, 1},
{ "/usr/etc/netstat", "-s", SC(2), NULL, 0, 0, 0, 0},
{ "/usr/bin/nfsstat", NULL, SC(2), NULL, 0, 0, 0, 0},
{ "/usr/ucb/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
{ "/usr/bin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
{ "/usr/sbin/netstat", "-m", SC(-1), NULL, 0, 0, 0, 1 },
{ "/usr/etc/netstat", "-m", SC(-1), NULL, 0, 0, 0, 0 },
{ "/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
{ "/usr/ucb/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
{ "/usr/bin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1 },
{ "/usr/sbin/netstat", "-in", SC(-1), NULL, 0, 0, 0, 1},
{ "/usr/etc/netstat", "-in", SC(-1), NULL, 0, 0, 0, 0},
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.1.0",
SC(-1), NULL, 0, 0, 0, 0 }, /* UDP in */
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.7.4.0",
SC(-1), NULL, 0, 0, 0, 0 }, /* UDP out */
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.4.3.0",
SC(-1), NULL, 0, 0, 0, 0 }, /* IP ? */
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.10.0",
SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.11.0",
SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.6.13.0",
SC(-1), NULL, 0, 0, 0, 0 }, /* TCP ? */
{ "/usr/bin/mpstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
{ "/usr/bin/w", NULL, SC(1), NULL, 0, 0, 0, 1 },
{ "/usr/bsd/w", NULL, SC(1), NULL, 0, 0, 0, 0 },
{ "/usr/bin/df", NULL, SC(1), NULL, 0, 0, 0, 1 },
{ "/bin/df", NULL, SC(1), NULL, 0, 0, 0, 0 },
{ "/usr/sbin/portstat", NULL, SC(1), NULL, 0, 0, 0, 0 },
{ "/usr/bin/iostat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
{ "/usr/bin/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
{ "/usr/bsd/uptime", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
{ "/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 1 },
{ "/usr/bin/vmstat", "-f", SC(SC_0), NULL, 0, 0, 0, 0 },
{ "/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 1 },
{ "/usr/bin/vmstat", NULL, SC(SC_0), NULL, 0, 0, 0, 0 },
{ "/usr/ucb/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
{ "/usr/bin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
{ "/usr/sbin/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 1 },
{ "/usr/etc/netstat", "-n", SC(0.5), NULL, 0, 0, 0, 0 },
#if defined( __sgi ) || defined( __hpux )
{ "/bin/ps", "-el", SC(0.3), NULL, 0, 0, 0, 1 },
#endif /* __sgi || __hpux */
{ "/usr/ucb/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
{ "/usr/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 1 },
{ "/bin/ps", "aux", SC(0.3), NULL, 0, 0, 0, 0 },
{ "/bin/ps", "-A", SC(0.3), NULL, 0, 0, 0, 0 }, /*QNX*/
{ "/usr/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 1 },
{ "/bin/ipcs", "-a", SC(0.5), NULL, 0, 0, 0, 0 },
/* Unreliable source, depends on system usage */
{ "/etc/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 1 },
{ "/bin/pstat", "-p", SC(0.5), NULL, 0, 0, 0, 0 },
{ "/etc/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 1 },
{ "/bin/pstat", "-S", SC(0.2), NULL, 0, 0, 0, 0 },
{ "/etc/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 1 },
{ "/bin/pstat", "-v", SC(0.2), NULL, 0, 0, 0, 0 },
{ "/etc/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 1 },
{ "/bin/pstat", "-x", SC(0.2), NULL, 0, 0, 0, 0 },
{ "/etc/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
{ "/bin/pstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
/* pstat is your friend */
{ "/usr/bin/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 1 },
#ifdef __sgi
{ "/usr/bsd/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
#endif /* __sgi */
#ifdef __hpux
{ "/etc/last", "-50", SC(0.3), NULL, 0, 0, 0, 0 },
#endif /* __hpux */
{ "/usr/bsd/last", "-n 50", SC(0.3), NULL, 0, 0, 0, 0 },
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.1.0",
SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
{ "/usr/sbin/snmp_request", "localhost public get 1.3.6.1.2.1.5.3.0",
SC(0.1), NULL, 0, 0, 0, 0 }, /* ICMP ? */
{ "/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
{ "/usr/etc/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
{ "/usr/bin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 1 },
{ "/usr/sbin/arp", "-a", SC(0.1), NULL, 0, 0, 0, 0 },
{ "/usr/sbin/ripquery", "-nw 1 127.0.0.1",
SC(0.1), NULL, 0, 0, 0, 0 },
{ "/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
{ "/usr/bin/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 1 },
{ "/usr/ucb/lpstat", "-t", SC(0.1), NULL, 0, 0, 0, 0 },
{ "/usr/bin/tcpdump", "-c 5 -efvvx", SC(1), NULL, 0, 0, 0, 0 },
/* This is very environment-dependent. If network traffic is low, it'll
* probably time out before delivering 5 packets, which is OK because
* it'll probably be fixed stuff like ARP anyway */
{ "/usr/sbin/advfsstat", "-b usr_domain",
SC(SC_0), NULL, 0, 0, 0, 0},
{ "/usr/sbin/advfsstat", "-l 2 usr_domain",
SC(0.5), NULL, 0, 0, 0, 0},
{ "/usr/sbin/advfsstat", "-p usr_domain",
SC(SC_0), NULL, 0, 0, 0, 0},
/* This is a complex and screwball program. Some systems have things
* like rX_dmn, x = integer, for RAID systems, but the statistics are
* pretty dodgy */
#ifdef __QNXNTO__
{ "/bin/pidin", "-F%A%B%c%d%E%I%J%K%m%M%n%N%p%P%S%s%T", SC(0.3),
NULL, 0, 0, 0, 0 },
#endif
#if 0
/* The following aren't enabled since they're somewhat slow and not very
* unpredictable, however they give an indication of the sort of sources
* you can use (for example the finger might be more useful on a
* firewalled internal network) */
{ "/usr/bin/finger", "@ml.media.mit.edu", SC(0.9), NULL, 0, 0, 0, 0 },
{ "/usr/local/bin/wget", "-O - http://lavarand.sgi.com/block.html",
SC(0.9), NULL, 0, 0, 0, 0 },
{ "/bin/cat", "/usr/spool/mqueue/syslog", SC(0.9), NULL, 0, 0, 0, 0 },
#endif /* 0 */
{ NULL, NULL, 0, NULL, 0, 0, 0, 0 }
};
static byte *gather_buffer; /* buffer for gathering random noise */
static int gather_buffer_size; /* size of the memory buffer */
static uid_t gatherer_uid;
/* The message structure used to communicate with the parent */
typedef struct {
int usefulness; /* usefulness of data */
int ndata; /* valid bytes in data */
char data[500]; /* gathered data */
} GATHER_MSG;
#ifndef HAVE_WAITPID
static pid_t
waitpid(pid_t pid, int *statptr, int options)
{
#ifdef HAVE_WAIT4
return wait4(pid, statptr, options, NULL);
#else
/* If wait4 is also not available, try wait3 for SVR3 variants */
/* Less ideal because can't actually request a specific pid */
/* For that reason, first check to see if pid is for an */
/* existing process. */
int tmp_pid, dummystat;;
if (kill(pid, 0) == -1) {
errno = ECHILD;
return -1;
}
if (statptr == NULL)
statptr = &dummystat;
while (((tmp_pid = wait3(statptr, options, 0)) != pid) &&
(tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
;
return tmp_pid;
#endif
}
#endif
/* Under SunOS popen() doesn't record the pid of the child process. When
* pclose() is called, instead of calling waitpid() for the correct child, it
* calls wait() repeatedly until the right child is reaped. The problem is
* that this reaps any other children that happen to have died at that
* moment, and when their pclose() comes along, the process hangs forever.
* The fix is to use a wrapper for popen()/pclose() which saves the pid in
* the dataSources structure (code adapted from GNU-libc's popen() call).
*
* Aut viam inveniam aut faciam */
static FILE *
my_popen(struct RI *entry)
{
int pipedes[2];
FILE *stream;
/* Create the pipe */
if (pipe(pipedes) < 0)
return (NULL);
/* Fork off the child ("vfork() is like an OS orgasm. All OS's want to
* do it, but most just end up faking it" - Chris Wedgwood). If your OS
* supports it, you should try to use vfork() here because it's somewhat
* more efficient */
#if defined( sun ) || defined( __ultrix__ ) || defined( __osf__ ) || \
defined(__hpux)
entry->pid = vfork();
#else /* */
entry->pid = fork();
#endif /* Unixen which have vfork() */
if (entry->pid == (pid_t) - 1) {
/* The fork failed */
close(pipedes[0]);
close(pipedes[1]);
return (NULL);
}
if (entry->pid == (pid_t) 0) {
struct passwd *passwd;
/* We are the child. Make the read side of the pipe be stdout */
if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
exit(127);
/* Now that everything is set up, give up our permissions to make
* sure we don't read anything sensitive. If the getpwnam() fails,
* we default to -1, which is usually nobody */
if (gatherer_uid == (uid_t)-1 && \
(passwd = getpwnam("nobody")) != NULL)
gatherer_uid = passwd->pw_uid;
setuid(gatherer_uid);
/* Close the pipe descriptors */
close(pipedes[STDIN_FILENO]);
close(pipedes[STDOUT_FILENO]);
/* Try and exec the program */
execl(entry->path, entry->path, entry->arg, NULL);
/* Die if the exec failed */
exit(127);
}
/* We are the parent. Close the irrelevant side of the pipe and open
* the relevant side as a new stream. Mark our side of the pipe to
* close on exec, so new children won't see it */
close(pipedes[STDOUT_FILENO]);
#ifdef FD_CLOEXEC
fcntl(pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
#endif
stream = fdopen(pipedes[STDIN_FILENO], "r");
if (stream == NULL) {
int savedErrno = errno;
/* The stream couldn't be opened or the child structure couldn't be
* allocated. Kill the child and close the other side of the pipe */
kill(entry->pid, SIGKILL);
if (stream == NULL)
close(pipedes[STDOUT_FILENO]);
else
fclose(stream);
waitpid(entry->pid, NULL, 0);
entry->pid = 0;
errno = savedErrno;
return (NULL);
}
return (stream);
}
static int
my_pclose(struct RI *entry)
{
int status = 0;
if (fclose(entry->pipe))
return (-1);
/* We ignore the return value from the process because some
programs return funny values which would result in the input
being discarded even if they executed successfully. This isn't
a problem because the result data size threshold will filter
out any programs which exit with a usage message without
producing useful output. */
if (waitpid(entry->pid, NULL, 0) != entry->pid)
status = -1;
entry->pipe = NULL;
entry->pid = 0;
return (status);
}
/* Unix slow poll (without special support for Linux)
*
* If a few of the randomness sources create a large amount of output then
* the slowPoll() stops once the buffer has been filled (but before all the
* randomness sources have been sucked dry) so that the 'usefulness' factor
* remains below the threshold. For this reason the gatherer buffer has to
* be fairly sizeable on moderately loaded systems. This is something of a
* bug since the usefulness should be influenced by the amount of output as
* well as the source type */
static int
slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
{
int moreSources;
struct timeval tv;
fd_set fds;
#if defined( __hpux )
size_t maxFD = 0;
#else
int maxFD = 0;
#endif /* OS-specific brokenness */
int bufPos, i, usefulness = 0;
int last_so_far = 0;
int any_need_entropy = 0;
int delay;
int rc;
/* Fire up each randomness source */
FD_ZERO(&fds);
for (i = 0; dataSources[i].path != NULL; i++) {
/* Since popen() is a fairly heavy function, we check to see whether
* the executable exists before we try to run it */
if (access(dataSources[i].path, X_OK)) {
if( dbgfp && dbgall )
fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
dataSources[i].hasAlternative ?
", has alternatives" : "");
dataSources[i].pipe = NULL;
}
else
dataSources[i].pipe = my_popen(&dataSources[i]);
if (dataSources[i].pipe != NULL) {
dataSources[i].pipeFD = fileno(dataSources[i].pipe);
if (dataSources[i].pipeFD > maxFD)
maxFD = dataSources[i].pipeFD;
#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
#else
#error O_NONBLOCK is missing
#endif
/* FIXME: We need to make sure that the fd is less than
FD_SETSIZE. */
FD_SET(dataSources[i].pipeFD, &fds);
dataSources[i].length = 0;
/* If there are alternatives for this command, don't try and
* execute them */
while (dataSources[i].hasAlternative) {
if( dbgfp && dbgall )
fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
i++;
}
}
}
/* Suck all the data we can get from each of the sources */
bufPos = 0;
moreSources = 1;
delay = 0; /* Return immediately (well, after 100ms) the first time. */
while (moreSources && bufPos <= gather_buffer_size) {
/* Wait for data to become available from any of the sources, with a
* timeout of 10 seconds. This adds even more randomness since data
* becomes available in a nondeterministic fashion. Kudos to HP's QA
* department for managing to ship a select() which breaks its own
* prototype */
tv.tv_sec = delay;
tv.tv_usec = delay? 0 : 100000;
#if defined( __hpux ) && ( OS_VERSION == 9 )
rc = select(maxFD + 1, (int *)&fds, NULL, NULL, &tv);
#else /* */
rc = select(maxFD + 1, &fds, NULL, NULL, &tv);
#endif /* __hpux */
if (rc == -1)
break; /* Ooops; select failed. */
if (!rc)
{
/* FIXME: Because we run several tools at once it is
unlikely that we will see a block in select at all. */
if (!any_need_entropy
|| last_so_far != (gather_buffer_size - bufPos) )
{
last_so_far = gather_buffer_size - bufPos;
_gcry_random_progress ("need_entropy", 'X',
last_so_far,
gather_buffer_size);
any_need_entropy = 1;
}
delay = 10; /* Use 10 seconds henceforth. */
/* Note that the fd_set is setup again at the end of this loop. */
}
/* One of the sources has data available, read it into the buffer */
for (i = 0; dataSources[i].path != NULL; i++) {
if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
size_t noBytes;
if ((noBytes = fread(gather_buffer + bufPos, 1,
gather_buffer_size - bufPos,
dataSources[i].pipe)) == 0) {
if (my_pclose(&dataSources[i]) == 0) {
int total = 0;
/* Try and estimate how much entropy we're getting
* from a data source */
if (dataSources[i].usefulness) {
if (dataSources[i].usefulness < 0)
total = (dataSources[i].length + 999)
/ -dataSources[i].usefulness;
else
total = dataSources[i].length
/ dataSources[i].usefulness;
}
if( dbgfp )
fprintf(dbgfp,
"%s %s contributed %d bytes, "
"usefulness = %d\n", dataSources[i].path,
(dataSources[i].arg != NULL) ?
dataSources[i].arg : "",
dataSources[i].length, total);
if( dataSources[i].length )
usefulness += total;
}
dataSources[i].pipe = NULL;
}
else {
int currPos = bufPos;
int endPos = bufPos + noBytes;
/* Run-length compress the input byte sequence */
while (currPos < endPos) {
int ch = gather_buffer[currPos];
/* If it's a single byte, just copy it over */
if (ch != gather_buffer[currPos + 1]) {
gather_buffer[bufPos++] = ch;
currPos++;
}
else {
int count = 0;
/* It's a run of repeated bytes, replace them
* with the byte count mod 256 */
while ((ch == gather_buffer[currPos])
&& currPos < endPos) {
count++;
currPos++;
}
gather_buffer[bufPos++] = count;
noBytes -= count - 1;
}
}
/* Remember the number of (compressed) bytes of input we
* obtained */
dataSources[i].length += noBytes;
}
}
}
/* Check if there is more input available on any of the sources */
moreSources = 0;
FD_ZERO(&fds);
for (i = 0; dataSources[i].path != NULL; i++) {
if (dataSources[i].pipe != NULL) {
FD_SET(dataSources[i].pipeFD, &fds);
moreSources = 1;
}
}
}
if (any_need_entropy)
_gcry_random_progress ("need_entropy", 'X',
gather_buffer_size,
gather_buffer_size);
if( dbgfp ) {
fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
fflush(dbgfp);
}
*nbytes = bufPos;
return usefulness;
}
/****************
* Start the gatherer process which writes messages of
* type GATHERER_MSG to pipedes
*/
static void
start_gatherer( int pipefd )
{
FILE *dbgfp = NULL;
int dbgall;
{
const char *s = getenv("GCRYPT_RNDUNIX_DBG");
if( s ) {
dbgfp = (*s=='-' && !s[1])? stdout : fopen(s, "a");
if( !dbgfp )
log_info("can't open debug file `%s': %s\n",
s, strerror(errno) );
else
fprintf(dbgfp,"\nSTART RNDUNIX DEBUG pid=%d\n", (int)getpid());
}
dbgall = !!getenv("GCRYPT_RNDUNIX_DBGALL");
}
/* close all files but the ones we need */
{ int nmax, n1, n2, i;
#ifdef _SC_OPEN_MAX
if( (nmax=sysconf( _SC_OPEN_MAX )) < 0 ) {
# ifdef _POSIX_OPEN_MAX
nmax = _POSIX_OPEN_MAX;
# else
nmax = 20; /* assume a reasonable value */
# endif
}
/* AIX returns INT32_MAX instead of a proper value. We assume that
* this is always an error and use a reasonable value. */
# ifdef INT32_MAX
if (nmax == INT32_MAX)
nmax = 20;
# endif
#else /*!_SC_OPEN_MAX*/
nmax = 20; /* assume a reasonable value */
#endif /*!_SC_OPEN_MAX*/
n1 = fileno( stderr );
n2 = dbgfp? fileno( dbgfp ) : -1;
for(i=0; i < nmax; i++ ) {
if( i != n1 && i != n2 && i != pipefd )
close(i);
}
errno = 0;
}
/* Set up the buffer. Not ethat we use a plain standard malloc here. */
gather_buffer_size = GATHER_BUFSIZE;
gather_buffer = malloc( gather_buffer_size );
if( !gather_buffer ) {
log_error("out of core while allocating the gatherer buffer\n");
exit(2);
}
/* Reset the SIGC(H)LD handler to the system default. This is necessary
* because if the program which cryptlib is a part of installs its own
* SIGC(H)LD handler, it will end up reaping the cryptlib children before
* cryptlib can. As a result, my_pclose() will call waitpid() on a
* process which has already been reaped by the installed handler and
* return an error, so the read data won't be added to the randomness
* pool. There are two types of SIGC(H)LD naming, the SysV SIGCLD and
* the BSD/Posix SIGCHLD, so we need to handle either possibility */
#ifdef SIGCLD
signal(SIGCLD, SIG_DFL);
#else
signal(SIGCHLD, SIG_DFL);
#endif
fclose(stderr); /* Arrghh!! It's Stuart code!! */
/* Mary goes to Berkeley: NetBSD emits warnings if the standard
descriptors are not open when running setuid program. Thus we
connect them to the bitbucket if they are not already open. */
{
struct stat statbuf;
if (fstat (STDIN_FILENO, &statbuf) == -1 && errno == EBADF)
open ("/dev/null",O_RDONLY);
if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
open ("/dev/null",O_WRONLY);
if (fstat (STDERR_FILENO, &statbuf) == -1 && errno == EBADF)
open ("/dev/null",O_WRONLY);
}
for(;;) {
GATHER_MSG msg;
size_t nbytes;
const char *p;
msg.usefulness = slow_poll( dbgfp, dbgall, &nbytes );
p = (const char*)gather_buffer;
while( nbytes ) {
msg.ndata = nbytes > sizeof(msg.data)? sizeof(msg.data) : nbytes;
memcpy( msg.data, p, msg.ndata );
nbytes -= msg.ndata;
p += msg.ndata;
while( write( pipefd, &msg, sizeof(msg) ) != sizeof(msg) ) {
if( errno == EINTR )
continue;
if( errno == EAGAIN ) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 50000;
select(0, NULL, NULL, NULL, &tv);
continue;
}
if( errno == EPIPE ) /* parent has exited, so give up */
exit(0);
/* we can't do very much here because stderr is closed */
if( dbgfp )
fprintf(dbgfp, "gatherer can't write to pipe: %s\n",
strerror(errno) );
/* we start a new poll to give the system some time */
nbytes = 0;
break;
}
}
}
/* we are killed when the parent dies */
}
static int
read_a_msg( int fd, GATHER_MSG *msg )
{
char *buffer = (char*)msg;
size_t length = sizeof( *msg );
int n;
do {
do {
n = read(fd, buffer, length );
} while( n == -1 && errno == EINTR );
if( n == -1 )
return -1;
buffer += n;
length -= n;
} while( length );
return 0;
}
/****************
* Using a level of 0 should never block and better add nothing
* to the pool. So this is just a dummy for this gatherer.
*/
int
_gcry_rndunix_gather_random (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level )
{
static pid_t gatherer_pid = 0;
static int pipedes[2];
GATHER_MSG msg;
size_t n;
if( !level )
return 0;
if( !gatherer_pid ) {
/* Make sure we are not setuid. */
if ( getuid() != geteuid() )
BUG();
/* time to start the gatherer process */
if( pipe( pipedes ) ) {
log_error("pipe() failed: %s\n", strerror(errno));
return -1;
}
gatherer_pid = fork();
if( gatherer_pid == -1 ) {
log_error("can't for gatherer process: %s\n", strerror(errno));
return -1;
}
if( !gatherer_pid ) {
start_gatherer( pipedes[1] );
/* oops, can't happen */
return -1;
}
}
/* now read from the gatherer */
while( length ) {
int goodness;
- ulong subtract;
+ unsigned long subtract;
if( read_a_msg( pipedes[0], &msg ) ) {
log_error("reading from gatherer pipe failed: %s\n",
strerror(errno));
return -1;
}
if( level > 1 ) {
if( msg.usefulness > 30 )
goodness = 100;
else if ( msg.usefulness )
goodness = msg.usefulness * 100 / 30;
else
goodness = 0;
}
else if( level ) {
if( msg.usefulness > 15 )
goodness = 100;
else if ( msg.usefulness )
goodness = msg.usefulness * 100 / 15;
else
goodness = 0;
}
else
goodness = 100; /* goodness of level 0 is always 100 % */
n = msg.ndata;
if( n > length )
n = length;
(*add)( msg.data, n, origin );
/* this is the trick how we cope with the goodness */
- subtract = (ulong)n * goodness / 100;
+ subtract = (unsigned long)n * goodness / 100;
/* subtract at least 1 byte to avoid infinite loops */
length -= subtract ? subtract : 1;
}
return 0;
}
diff --git a/random/rndw32.c b/random/rndw32.c
index 08a8867d..b3f63d20 100644
--- a/random/rndw32.c
+++ b/random/rndw32.c
@@ -1,1030 +1,1030 @@
/* rndw32.c - W32 entropy gatherer
* Copyright (C) 1999, 2000, 2002, 2003, 2007,
* 2010 Free Software Foundation, Inc.
* Copyright Peter Gutmann, Matt Thomlinson and Blake Coverett 1996-2006
*
* This file is part of Libgcrypt.
*
*************************************************************************
* The code here is based on code from Cryptlib 3.0 beta by Peter Gutmann.
* Source file misc/rndwin32.c "Win32 Randomness-Gathering Code" with this
* copyright notice:
*
* This module is part of the cryptlib continuously seeded pseudorandom
* number generator. For usage conditions, see lib_rand.c
*
* [Here is the notice from lib_rand.c, which is now called dev_sys.c]
*
* This module and the misc/rnd*.c modules represent the cryptlib
* continuously seeded pseudorandom number generator (CSPRNG) as described in
* my 1998 Usenix Security Symposium paper "The generation of random numbers
* for cryptographic purposes".
*
* The CSPRNG code is copyright Peter Gutmann (and various others) 1996,
* 1997, 1998, 1999, all rights reserved. Redistribution of the CSPRNG
* modules and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and this permission notice in its entirety.
*
* 2. Redistributions in binary form must reproduce the copyright notice in
* the documentation and/or other materials provided with the distribution.
*
* 3. A copy of any bugfixes or enhancements made must be provided to the
* author, to allow them to be added to the
* baseline version of the code.
*
* ALTERNATIVELY, the code may be distributed under the terms of the
* GNU Lesser General Public License, version 2.1 or any later version
* published by the Free Software Foundation, in which case the
* provisions of the GNU LGPL are required INSTEAD OF the above
* restrictions.
*
* Although not required under the terms of the LGPL, it would still
* be nice if you could make any changes available to the author to
* allow a consistent code base to be maintained.
*************************************************************************
* The above alternative was changed from GPL to LGPL on 2007-08-22 with
* permission from Peter Gutmann:
*==========
From: pgut001
Subject: Re: LGPL for the windows entropy gatherer
To: wk@gnupg.org
Date: Wed, 22 Aug 2007 03:05:42 +1200
Hi,
>As of now libgcrypt is GPL under Windows due to that module and some people
>would really like to see it under LGPL too. Can you do such a license change
>to LGPL version 2? Note that LGPL give the user the option to relicense it
>under GPL, so the change would be pretty easy and backwar compatible.
Sure. I assumed that since GPG was GPLd, you'd prefer the GPL for the entropy
code as well, but Ian asked for LGPL as an option so as of the next release
I'll have LGPL in there. You can consider it to be retroactive, so your
current version will be LGPLd as well.
Peter.
*==========
*/
#include
#include
#include
#include
#include
#ifdef __GNUC__
#include
#endif
#include
#include
#include "types.h"
#include "g10lib.h"
#include "rand-internal.h"
/* Definitions which are missing from the current GNU Windows32Api. */
#ifndef IOCTL_DISK_PERFORMANCE
#define IOCTL_DISK_PERFORMANCE 0x00070020
#endif
/* This used to be (6*8+5*4+8*2), but Peter Gutmann figured a larger
value in a newer release. So we use a far larger value. */
#define SIZEOF_DISK_PERFORMANCE_STRUCT 256
/* We don't include wincrypt.h so define it here. */
#define HCRYPTPROV HANDLE
/* When we query the performance counters, we allocate an initial buffer and
* then reallocate it as required until RegQueryValueEx() stops returning
* ERROR_MORE_DATA. The following values define the initial buffer size and
* step size by which the buffer is increased
*/
#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */
#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */
/* The number of bytes to read from the system RNG on each slow poll. */
#define SYSTEMRNG_BYTES 64
/* Intel Chipset CSP type and name */
#define PROV_INTEL_SEC 22
#define INTEL_DEF_PROV "Intel Hardware Cryptographic Service Provider"
/* Type definitions for function pointers to call NetAPI32 functions. */
typedef DWORD (WINAPI *NETSTATISTICSGET)(LPWSTR szServer, LPWSTR szService,
DWORD dwLevel, DWORD dwOptions,
LPBYTE *lpBuffer);
typedef DWORD (WINAPI *NETAPIBUFFERSIZE)(LPVOID lpBuffer, LPDWORD cbBuffer);
typedef DWORD (WINAPI *NETAPIBUFFERFREE)(LPVOID lpBuffer);
/* Type definitions for function pointers to call native NT functions. */
typedef DWORD (WINAPI *NTQUERYSYSTEMINFORMATION)(DWORD systemInformationClass,
PVOID systemInformation,
ULONG systemInformationLength,
PULONG returnLength);
typedef DWORD (WINAPI *NTQUERYINFORMATIONPROCESS)
(HANDLE processHandle, DWORD processInformationClass,
PVOID processInformation, ULONG processInformationLength,
PULONG returnLength);
typedef DWORD (WINAPI *NTPOWERINFORMATION)
(DWORD powerInformationClass, PVOID inputBuffer,
ULONG inputBufferLength, PVOID outputBuffer, ULONG outputBufferLength );
/* Type definitions for function pointers to call CryptoAPI functions. */
typedef BOOL (WINAPI *CRYPTACQUIRECONTEXT)(HCRYPTPROV *phProv,
LPCTSTR pszContainer,
LPCTSTR pszProvider,
DWORD dwProvType,
DWORD dwFlags);
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,
BYTE *pbBuffer);
typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
/* Somewhat alternative functionality available as a direct call, for
Windows XP and newer. This is the CryptoAPI RNG, which isn't anywhere
near as good as the HW RNG, but we use it if it's present on the basis
that at least it can't make things any worse. This direct access version
is only available under Windows XP, we don't go out of our way to access
the more general CryptoAPI one since the main purpose of using it is to
take advantage of any possible future hardware RNGs that may be added,
for example via TCPA devices. */
typedef BOOL (WINAPI *RTLGENRANDOM)(PVOID RandomBuffer,
ULONG RandomBufferLength);
/* MBM data structures, originally by Alexander van Kaam, converted to C by
Anders@Majland.org, finally updated by Chris Zahrt */
#define BusType char
#define SMBType char
#define SensorType char
typedef struct
{
SensorType iType; /* Type of sensor. */
int Count; /* Number of sensor for that type. */
} SharedIndex;
typedef struct
{
SensorType ssType; /* Type of sensor */
unsigned char ssName[12]; /* Name of sensor */
char sspadding1[3]; /* Padding of 3 bytes */
double ssCurrent; /* Current value */
double ssLow; /* Lowest readout */
double ssHigh; /* Highest readout */
long ssCount; /* Total number of readout */
char sspadding2[4]; /* Padding of 4 bytes */
long double ssTotal; /* Total amount of all readouts */
char sspadding3[6]; /* Padding of 6 bytes */
double ssAlarm1; /* Temp & fan: high alarm; voltage: % off */
double ssAlarm2; /* Temp: low alarm */
} SharedSensor;
typedef struct
{
short siSMB_Base; /* SMBus base address */
BusType siSMB_Type; /* SMBus/Isa bus used to access chip */
SMBType siSMB_Code; /* SMBus sub type, Intel, AMD or ALi */
char siSMB_Addr; /* Address of sensor chip on SMBus */
unsigned char siSMB_Name[41]; /* Nice name for SMBus */
short siISA_Base; /* ISA base address of sensor chip on ISA */
int siChipType; /* Chip nr, connects with Chipinfo.ini */
char siVoltageSubType; /* Subvoltage option selected */
} SharedInfo;
typedef struct
{
double sdVersion; /* Version number (example: 51090) */
SharedIndex sdIndex[10]; /* Sensor index */
SharedSensor sdSensor[100]; /* Sensor info */
SharedInfo sdInfo; /* Misc.info */
unsigned char sdStart[41]; /* Start time */
/* We don't use the next two fields both because they're not random
and because it provides a nice safety margin in case of data size
mis- estimates (we always under-estimate the buffer size). */
#if 0
unsigned char sdCurrent[41]; /* Current time */
unsigned char sdPath[256]; /* MBM path */
#endif /*0*/
} SharedData;
/* One time initialized handles and function pointers. We use dynamic
loading of the DLLs to do without them in case libgcrypt does not
need any random. */
static HANDLE hNetAPI32;
static NETSTATISTICSGET pNetStatisticsGet;
static NETAPIBUFFERSIZE pNetApiBufferSize;
static NETAPIBUFFERFREE pNetApiBufferFree;
static HANDLE hNTAPI;
static NTQUERYSYSTEMINFORMATION pNtQuerySystemInformation;
static NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess;
static NTPOWERINFORMATION pNtPowerInformation;
static HANDLE hAdvAPI32;
static CRYPTACQUIRECONTEXT pCryptAcquireContext;
static CRYPTGENRANDOM pCryptGenRandom;
static CRYPTRELEASECONTEXT pCryptReleaseContext;
static RTLGENRANDOM pRtlGenRandom;
/* Other module global variables. */
static int system_rng_available; /* Whether a system RNG is available. */
static HCRYPTPROV hRNGProv; /* Handle to Intel RNG CSP. */
/* The debug flag. Debugging is enabled if the value of the envvar
* GCRY_RNDW32_DBG is a positive number.*/
static int debug_me;
static int system_is_w2000; /* True if running on W2000. */
/* Try and connect to the system RNG if there's one present. */
static void
init_system_rng (void)
{
system_rng_available = 0;
hRNGProv = NULL;
hAdvAPI32 = GetModuleHandle ("AdvAPI32.dll");
if (!hAdvAPI32)
return;
pCryptAcquireContext = (CRYPTACQUIRECONTEXT)
GetProcAddress (hAdvAPI32, "CryptAcquireContextA");
pCryptGenRandom = (CRYPTGENRANDOM)
GetProcAddress (hAdvAPI32, "CryptGenRandom");
pCryptReleaseContext = (CRYPTRELEASECONTEXT)
GetProcAddress (hAdvAPI32, "CryptReleaseContext");
/* Get a pointer to the native randomness function if it's available.
This isn't exported by name, so we have to get it by ordinal. */
pRtlGenRandom = (RTLGENRANDOM)
GetProcAddress (hAdvAPI32, "SystemFunction036");
/* Try and connect to the PIII RNG CSP. The AMD 768 southbridge (from
the 760 MP chipset) also has a hardware RNG, but there doesn't appear
to be any driver support for this as there is for the Intel RNG so we
can't do much with it. OTOH the Intel RNG is also effectively dead
as well, mostly due to virtually nonexistent support/marketing by
Intel, it's included here mostly for form's sake. */
if ( (!pCryptAcquireContext || !pCryptGenRandom || !pCryptReleaseContext
|| !pCryptAcquireContext (&hRNGProv, NULL, INTEL_DEF_PROV,
PROV_INTEL_SEC, 0) )
&& !pRtlGenRandom)
{
hAdvAPI32 = NULL;
}
else
system_rng_available = 1;
}
/* Read data from the system RNG if availavle. */
static void
read_system_rng (void (*add)(const void*, size_t, enum random_origins),
enum random_origins requester)
{
BYTE buffer[ SYSTEMRNG_BYTES + 8 ];
int quality = 0;
if (!system_rng_available)
return;
/* Read SYSTEMRNG_BYTES bytes from the system RNG. We don't rely on
this for all our randomness requirements (particularly the
software RNG) in case it's broken in some way. */
if (hRNGProv)
{
if (pCryptGenRandom (hRNGProv, SYSTEMRNG_BYTES, buffer))
quality = 80;
}
else if (pRtlGenRandom)
{
if ( pRtlGenRandom (buffer, SYSTEMRNG_BYTES))
quality = 50;
}
if (quality > 0)
{
if (debug_me)
log_debug ("rndw32#read_system_rng: got %d bytes of quality %d\n",
SYSTEMRNG_BYTES, quality);
(*add) (buffer, SYSTEMRNG_BYTES, requester);
wipememory (buffer, SYSTEMRNG_BYTES);
}
}
/* Read data from MBM. This communicates via shared memory, so all we
need to do is map a file and read the data out. */
static void
read_mbm_data (void (*add)(const void*, size_t, enum random_origins),
enum random_origins requester)
{
HANDLE hMBMData;
SharedData *mbmDataPtr;
hMBMData = OpenFileMapping (FILE_MAP_READ, FALSE, "$M$B$M$5$S$D$" );
if (hMBMData)
{
mbmDataPtr = (SharedData*)MapViewOfFile (hMBMData, FILE_MAP_READ,0,0,0);
if (mbmDataPtr)
{
if (debug_me)
log_debug ("rndw32#read_mbm_data: got %d bytes\n",
(int)sizeof (SharedData));
(*add) (mbmDataPtr, sizeof (SharedData), requester);
UnmapViewOfFile (mbmDataPtr);
}
CloseHandle (hMBMData);
}
}
/* Fallback method using the registry to poll the statistics. */
static void
registry_poll (void (*add)(const void*, size_t, enum random_origins),
enum random_origins requester)
{
static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
int iterations;
DWORD dwSize, status;
PERF_DATA_BLOCK *pPerfData;
/* Get information from the system performance counters. This can take a
few seconds to do. In some environments the call to RegQueryValueEx()
can produce an access violation at some random time in the future, in
some cases adding a short delay after the following code block makes
the problem go away. This problem is extremely difficult to
reproduce, I haven't been able to get it to occur despite running it
on a number of machines. MS knowledge base article Q178887 covers
this type of problem, it's typically caused by an external driver or
other program that adds its own values under the
HKEY_PERFORMANCE_DATA key. The NT kernel, via Advapi32.dll, calls the
required external module to map in the data inside an SEH try/except
block, so problems in the module's collect function don't pop up until
after it has finished, so the fault appears to occur in Advapi32.dll.
There may be problems in the NT kernel as well though, a low-level
memory checker indicated that ExpandEnvironmentStrings() in
Kernel32.dll, called an interminable number of calls down inside
RegQueryValueEx(), was overwriting memory (it wrote twice the
allocated size of a buffer to a buffer allocated by the NT kernel).
OTOH this could be coming from the external module calling back into
the kernel, which eventually causes the problem described above.
Possibly as an extension of the problem that the krnlWaitSemaphore()
call above works around, running two instances of cryptlib (e.g. two
applications that use it) under NT4 can result in one of them hanging
in the RegQueryValueEx() call. This happens only under NT4 and is
hard to reproduce in any consistent manner.
One workaround that helps a bit is to read the registry as a remote
(rather than local) registry, it's possible that the use of a network
RPC call isolates the calling app from the problem in that whatever
service handles the RPC is taking the hit and not affecting the
calling app. Since this would require another round of extensive
testing to verify and the NT native API call is working fine, we'll
stick with the native API call for now.
Some versions of NT4 had a problem where the amount of data returned
was mis-reported and would never settle down, because of this the code
below includes a safety-catch that bails out after 10 attempts have
been made, this results in no data being returned but at does ensure
that the thread will terminate.
In addition to these problems the code in RegQueryValueEx() that
estimates the amount of memory required to return the performance
counter information isn't very accurate (it's much worse than the
"slightly-inaccurate" level that the MS docs warn about, it's usually
wildly off) since it always returns a worst-case estimate which is
usually nowhere near the actual amount required. For example it may
report that 128K of memory is required, but only return 64K of data.
Even worse than the registry-based performance counters is the
performance data helper (PDH) shim that tries to make the counters
look like the old Win16 API (which is also used by Win95). Under NT
this can consume tens of MB of memory and huge amounts of CPU time
while it gathers its data, and even running once can still consume
about 1/2MB of memory */
if (getenv ("GCRYPT_RNDW32_NOPERF"))
{
static int shown;
if (!shown)
{
shown = 1;
log_info ("note: get performance data has been disabled\n");
}
}
else
{
pPerfData = xmalloc (cbPerfData);
for (iterations=0; iterations < 10; iterations++)
{
dwSize = cbPerfData;
if ( debug_me )
log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
NULL, (LPBYTE) pPerfData, &dwSize);
if (status == ERROR_SUCCESS)
{
if (!memcmp (pPerfData->Signature, L"PERF", 8))
(*add) ( pPerfData, dwSize, requester );
else
log_debug ("rndw32: no PERF signature\n");
break;
}
else if (status == ERROR_MORE_DATA)
{
cbPerfData += PERFORMANCE_BUFFER_STEP;
pPerfData = xrealloc (pPerfData, cbPerfData);
}
else
{
static int been_here;
/* Silence the error message. In particular under Wine (as
of 2008) we would get swamped with such diagnotiscs. One
such diagnotiscs should be enough. */
if (been_here != status)
{
been_here = status;
log_debug ("rndw32: get performance data problem: ec=%ld\n",
status);
}
break;
}
}
xfree (pPerfData);
}
/* Although this isn't documented in the Win32 API docs, it's necessary
to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
implicitly opened on the first call to RegQueryValueEx()). If this
isn't done then any system components which provide performance data
can't be removed or changed while the handle remains active. */
RegCloseKey (HKEY_PERFORMANCE_DATA);
}
static void
slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
enum random_origins requester )
{
static int is_initialized = 0;
static int is_workstation = 1;
HANDLE hDevice;
DWORD dwType, dwSize, dwResult;
ULONG ulSize;
int drive_no, status;
int no_results = 0;
void *buffer;
if ( !is_initialized )
{
HKEY hKey;
if ( debug_me )
log_debug ("rndw32#slow_gatherer: init toolkit\n" );
/* Find out whether this is an NT server or workstation if necessary */
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
BYTE szValue[32 + 8];
dwSize = 32;
if ( debug_me )
log_debug ("rndw32#slow_gatherer: check product options\n" );
status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
szValue, &dwSize);
if (status == ERROR_SUCCESS && stricmp ((char*)szValue, "WinNT"))
{
/* Note: There are (at least) three cases for ProductType:
WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
NT Server acting as a Domain Controller. */
is_workstation = 0;
if ( debug_me )
log_debug ("rndw32: this is a NT server\n");
}
RegCloseKey (hKey);
}
/* The following are fixed for the lifetime of the process so we
only add them once */
/* readPnPData (); - we have not implemented that. */
/* Initialize the NetAPI32 function pointers if necessary */
hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
if (hNetAPI32)
{
if (debug_me)
log_debug ("rndw32#slow_gatherer: netapi32 loaded\n" );
pNetStatisticsGet = (NETSTATISTICSGET)
GetProcAddress (hNetAPI32, "NetStatisticsGet");
pNetApiBufferSize = (NETAPIBUFFERSIZE)
GetProcAddress (hNetAPI32, "NetApiBufferSize");
pNetApiBufferFree = (NETAPIBUFFERFREE)
GetProcAddress (hNetAPI32, "NetApiBufferFree");
if (!pNetStatisticsGet || !pNetApiBufferSize || !pNetApiBufferFree)
{
FreeLibrary (hNetAPI32);
hNetAPI32 = NULL;
log_debug ("rndw32: No NETAPI found\n" );
}
}
/* Initialize the NT kernel native API function pointers if necessary */
hNTAPI = GetModuleHandle ("NTDll.dll");
if (hNTAPI)
{
/* Get a pointer to the NT native information query functions */
pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)
GetProcAddress (hNTAPI, "NtQuerySystemInformation");
pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
GetProcAddress (hNTAPI, "NtQueryInformationProcess");
pNtPowerInformation = (NTPOWERINFORMATION)
GetProcAddress(hNTAPI, "NtPowerInformation");
if (!pNtQuerySystemInformation || !pNtQueryInformationProcess)
hNTAPI = NULL;
}
is_initialized = 1;
}
read_system_rng ( add, requester );
read_mbm_data ( add, requester );
/* Get network statistics. Note: Both NT Workstation and NT Server by
default will be running both the workstation and server services. The
heuristic below is probably useful though on the assumption that the
majority of the network traffic will be via the appropriate service.
In any case the network statistics return almost no randomness. */
{
LPBYTE lpBuffer;
if (hNetAPI32
&& !pNetStatisticsGet (NULL,
(LPWSTR)(is_workstation ? L"LanmanWorkstation" :
L"LanmanServer"), 0, 0, &lpBuffer))
{
if ( debug_me )
log_debug ("rndw32#slow_gatherer: get netstats\n" );
pNetApiBufferSize (lpBuffer, &dwSize);
(*add) ( lpBuffer, dwSize, requester );
pNetApiBufferFree (lpBuffer);
}
}
/* Get disk I/O statistics for all the hard drives. 100 is an
arbitrary failsafe limit. */
for (drive_no = 0; drive_no < 100 ; drive_no++)
{
char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8];
char szDevice[50];
/* Check whether we can access this device. */
snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d",
drive_no);
hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
break; /* No more drives. */
/* Note: This only works if you have turned on the disk performance
counters with 'diskperf -y'. These counters are off by default. */
dwSize = sizeof diskPerformance;
if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
&dwSize, NULL))
{
if ( debug_me )
log_debug ("rndw32#slow_gatherer: iostat drive %d\n",
drive_no);
(*add) (diskPerformance, dwSize, requester);
}
else
{
log_info ("NOTE: you should run 'diskperf -y' "
"to enable the disk statistics\n");
}
CloseHandle (hDevice);
}
/* In theory we should be using the Win32 performance query API to obtain
unpredictable data from the system, however this is so unreliable (see
the multiple sets of comments in registryPoll()) that it's too risky
to rely on it except as a fallback in emergencies. Instead, we rely
mostly on the NT native API function NtQuerySystemInformation(), which
has the dual advantages that it doesn't have as many (known) problems
as the Win32 equivalent and that it doesn't access the data indirectly
via pseudo-registry keys, which means that it's much faster. Note
that the Win32 equivalent actually works almost all of the time, the
problem is that on one or two systems it can fail in strange ways that
are never the same and can't be reproduced on any other system, which
is why we use the native API here. Microsoft officially documented
this function in early 2003, so it'll be fairly safe to use. */
if ( !hNTAPI )
{
registry_poll (add, requester);
return;
}
/* Scan the first 64 possible information types (we don't bother with
increasing the buffer size as we do with the Win32 version of the
performance data read, we may miss a few classes but it's no big deal).
This scan typically yields around 20 pieces of data, there's nothing
in the range 65...128 so chances are there won't be anything above
there either. */
buffer = xmalloc (PERFORMANCE_BUFFER_SIZE);
for (dwType = 0; dwType < 64; dwType++)
{
switch (dwType)
{
/* ID 17 = SystemObjectInformation hangs on some win2k systems. */
case 17:
if (system_is_w2000)
continue;
break;
/* Some information types are write-only (the IDs are shared with
a set-information call), we skip these. */
case 26: case 27: case 38: case 46: case 47: case 48: case 52:
continue;
/* ID 53 = SystemSessionProcessInformation reads input from the
output buffer, which has to contain a session ID and pointer
to the actual buffer in which to store the session information.
Because this isn't a standard query, we skip this. */
case 53:
continue;
}
/* Query the info for this ID. Some results (for example for
ID = 6, SystemCallCounts) are only available in checked builds
of the kernel. A smaller subcless of results require that
certain system config flags be set, for example
SystemObjectInformation requires that the
FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags. To avoid
having to special-case all of these, we try reading each one and
only use those for which we get a success status. */
dwResult = pNtQuerySystemInformation (dwType, buffer,
PERFORMANCE_BUFFER_SIZE - 2048,
&ulSize);
if (dwResult != ERROR_SUCCESS)
continue;
/* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24,
SystemDpcInformation) incorrectly return a length of zero, so we
manually adjust the length to the correct value. */
if ( !ulSize )
{
if (dwType == 23)
ulSize = 6 * sizeof (ULONG);
else if (dwType == 24)
ulSize = 5 * sizeof (ULONG);
}
/* If we got some data back, add it to the entropy pool. */
if (ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048)
{
if (debug_me)
log_debug ("rndw32#slow_gatherer: %lu bytes from sysinfo %ld\n",
ulSize, dwType);
(*add) (buffer, ulSize, requester);
no_results++;
}
}
/* Now we would do the same for the process information. This
call would rather ugly in that it requires an exact length
match for the data returned, failing with a
STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if the
length isn't an exact match. It requires a compiler to handle
complex nested structs, alignment issues, and so on, and
without the headers in which the entries are declared it's
almost impossible to do. Thus we don't. */
/* Finally, do the same for the system power status information. There
are only a limited number of useful information types available so we
restrict ourselves to the useful types. In addition since this
function doesn't return length information, we have to hardcode in
length data. */
if (pNtPowerInformation)
{
static const struct { int type; int size; } powerInfo[] = {
{ 0, 128 }, /* SystemPowerPolicyAc */
{ 1, 128 }, /* SystemPowerPolicyDc */
{ 4, 64 }, /* SystemPowerCapabilities */
{ 5, 48 }, /* SystemBatteryState */
{ 11, 48 }, /* ProcessorInformation */
{ 12, 24 }, /* SystemPowerInformation */
{ -1, -1 }
};
int i;
/* The 100 is a failsafe limit. */
for (i = 0; powerInfo[i].type != -1 && i < 100; i++ )
{
/* Query the info for this ID */
dwResult = pNtPowerInformation (powerInfo[i].type, NULL, 0, buffer,
PERFORMANCE_BUFFER_SIZE - 2048);
if (dwResult != ERROR_SUCCESS)
continue;
if (debug_me)
log_debug ("rndw32#slow_gatherer: %u bytes from powerinfo %d\n",
powerInfo[i].size, i);
(*add) (buffer, powerInfo[i].size, requester);
no_results++;
}
gcry_assert (i < 100);
}
xfree (buffer);
/* We couldn't get enough results from the kernel, fall back to the
somewhat troublesome registry poll. */
if (no_results < 15)
registry_poll (add, requester);
}
int
_gcry_rndw32_gather_random (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level )
{
static int is_initialized;
size_t n;
if (!level)
return 0;
/* We don't differentiate between level 1 and 2 here because there
is no internal entropy pool as a scary resource. It may all work
slower, but because our entropy source will never block but
deliver some not easy to measure entropy, we assume level 2. */
if (!is_initialized)
{
OSVERSIONINFO osvi = { sizeof( osvi ) };
const char *s;
if ((s = getenv ("GCRYPT_RNDW32_DBG")) && atoi (s) > 0)
debug_me = 1;
GetVersionEx( &osvi );
if (osvi.dwPlatformId != VER_PLATFORM_WIN32_NT)
log_fatal ("can only run on a Windows NT platform\n" );
system_is_w2000 = (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0);
init_system_rng ();
is_initialized = 1;
}
if (debug_me)
log_debug ("rndw32#gather_random: ori=%d len=%u lvl=%d\n",
origin, (unsigned int)length, level );
slow_gatherer (add, origin);
/* Round requested LENGTH up to full 32 bytes. */
n = _gcry_rndjent_poll (add, origin, ((length + 31) / 32) * 32);
if (debug_me)
log_debug ("rndw32#gather_random: jent contributed extra %u bytes\n",
(unsigned int)n);
return 0;
}
void
_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin)
{
static int addedFixedItems = 0;
if ( debug_me )
log_debug ("rndw32#gather_random_fast: ori=%d\n", origin );
/* Get various basic pieces of system information: Handle of active
window, handle of window with mouse capture, handle of clipboard
owner handle of start of clpboard viewer list, pseudohandle of
current process, current process ID, pseudohandle of current
thread, current thread ID, handle of desktop window, handle of
window with keyboard focus, whether system queue has any events,
cursor position for last message, 1 ms time for last message,
handle of window with clipboard open, handle of process heap,
handle of procs window station, types of events in input queue,
and milliseconds since Windows was started. On 64-bit platform
some of these return values are pointers and thus 64-bit wide.
We discard the upper 32-bit of those values. */
{
- byte buffer[20*sizeof(ulong)], *bufptr;
+ byte buffer[20*sizeof(unsigned long)], *bufptr;
bufptr = buffer;
-#define ADDINT(f) do { ulong along = (ulong)(f); \
+#define ADDINT(f) do { unsigned long along = (unsigned long)(f); \
memcpy (bufptr, &along, sizeof (along) ); \
bufptr += sizeof (along); \
} while (0)
#define ADDPTR(f) do { void *aptr = (f); \
ADDINT((SIZE_T)aptr); \
} while (0)
ADDPTR ( GetActiveWindow ());
ADDPTR ( GetCapture ());
ADDPTR ( GetClipboardOwner ());
ADDPTR ( GetClipboardViewer ());
ADDPTR ( GetCurrentProcess ());
ADDINT ( GetCurrentProcessId ());
ADDPTR ( GetCurrentThread ());
ADDINT ( GetCurrentThreadId ());
ADDPTR ( GetDesktopWindow ());
ADDPTR ( GetFocus ());
ADDINT ( GetInputState ());
ADDINT ( GetMessagePos ());
ADDINT ( GetMessageTime ());
ADDPTR ( GetOpenClipboardWindow ());
ADDPTR ( GetProcessHeap ());
ADDPTR ( GetProcessWindowStation ());
/* Following function in some cases stops returning events, and cannot
be used as an entropy source. */
/*ADDINT ( GetQueueStatus (QS_ALLEVENTS));*/
ADDINT ( GetTickCount ());
gcry_assert ( bufptr-buffer < sizeof (buffer) );
(*add) ( buffer, bufptr-buffer, origin );
#undef ADDINT
#undef ADDPTR
}
/* Get multiword system information: Current caret position, current
mouse cursor position. */
{
POINT point;
GetCaretPos (&point);
(*add) ( &point, sizeof (point), origin );
GetCursorPos (&point);
(*add) ( &point, sizeof (point), origin );
}
/* Get percent of memory in use, bytes of physical memory, bytes of
free physical memory, bytes in paging file, free bytes in paging
file, user bytes of address space, and free user bytes. */
{
MEMORYSTATUS memoryStatus;
memoryStatus.dwLength = sizeof (MEMORYSTATUS);
GlobalMemoryStatus (&memoryStatus);
(*add) ( &memoryStatus, sizeof (memoryStatus), origin );
}
/* Get thread and process creation time, exit time, time in kernel
mode, and time in user mode in 100ns intervals. */
{
HANDLE handle;
FILETIME creationTime, exitTime, kernelTime, userTime;
SIZE_T minimumWorkingSetSize, maximumWorkingSetSize;
handle = GetCurrentThread ();
GetThreadTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), origin );
(*add) ( &exitTime, sizeof (exitTime), origin );
(*add) ( &kernelTime, sizeof (kernelTime), origin );
(*add) ( &userTime, sizeof (userTime), origin );
handle = GetCurrentProcess ();
GetProcessTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), origin );
(*add) ( &exitTime, sizeof (exitTime), origin );
(*add) ( &kernelTime, sizeof (kernelTime), origin );
(*add) ( &userTime, sizeof (userTime), origin );
/* Get the minimum and maximum working set size for the current
process. */
GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
&maximumWorkingSetSize);
/* On 64-bit system, discard the high 32-bits. */
(*add) ( &minimumWorkingSetSize, sizeof (int), origin );
(*add) ( &maximumWorkingSetSize, sizeof (int), origin );
}
/* The following are fixed for the lifetime of the process so we only
* add them once */
if (!addedFixedItems)
{
STARTUPINFO startupInfo;
/* Get name of desktop, console window title, new window
position and size, window flags, and handles for stdin,
stdout, and stderr. */
startupInfo.cb = sizeof (STARTUPINFO);
GetStartupInfo (&startupInfo);
(*add) ( &startupInfo, sizeof (STARTUPINFO), origin );
addedFixedItems = 1;
}
/* The performance of QPC varies depending on the architecture it's
running on and on the OS, the MS documentation is vague about the
details because it varies so much. Under Win9x/ME it reads the
1.193180 MHz PIC timer. Under NT/Win2K/XP it may or may not read the
64-bit TSC depending on the HAL and assorted other circumstances,
generally on machines with a uniprocessor HAL
KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines
with a multiprocessor or APIC HAL it uses the TSC (the exact time
source is controlled by the HalpUse8254 flag in the kernel). That
choice of time sources is somewhat peculiar because on a
multiprocessor machine it's theoretically possible to get completely
different TSC readings depending on which CPU you're currently
running on, while for uniprocessor machines it's not a problem.
However, the kernel appears to synchronise the TSCs across CPUs at
boot time (it resets the TSC as part of its system init), so this
shouldn't really be a problem. Under WinCE it's completely platform-
dependent, if there's no hardware performance counter available, it
uses the 1ms system timer.
Another feature of the TSC (although it doesn't really affect us here)
is that mobile CPUs will turn off the TSC when they idle, Pentiums
will change the rate of the counter when they clock-throttle (to
match the current CPU speed), and hyperthreading Pentiums will turn
it off when both threads are idle (this more or less makes sense,
since the CPU will be in the halted state and not executing any
instructions to count).
To make things unambiguous, we detect a CPU new enough to call RDTSC
directly by checking for CPUID capabilities, and fall back to QPC if
this isn't present.
On AMD64, TSC is always available and intrinsic is provided for accessing
it. */
#ifdef __x86_64__
{
unsigned __int64 aint64;
/* Note: cryptlib does not discard upper 32 bits of TSC on WIN64, but does
* on WIN32. Is this correct? */
aint64 = __rdtsc();
(*add) (&aint64, sizeof(aint64), origin);
}
#else
#ifdef __GNUC__
/* FIXME: We would need to implement the CPU feature tests first. */
/* if (cpu_has_feature_rdtsc) */
/* { */
/* uint32_t lo, hi; */
/* We cannot use "=A", since this would use %rax on x86_64. */
/* __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */
/* Ignore high 32 bits, hwich are >1s res. */
/* (*add) (&lo, 4, origin ); */
/* } */
/* else */
#endif /*!__GNUC__*/
{
LARGE_INTEGER performanceCount;
if (QueryPerformanceCounter (&performanceCount))
{
if ( debug_me )
log_debug ("rndw32#gather_random_fast: perf data\n");
(*add) (&performanceCount, sizeof (performanceCount), origin);
}
else
{
/* Millisecond accuracy at best... */
DWORD aword = GetTickCount ();
(*add) (&aword, sizeof (aword), origin );
}
}
#endif /*__x86_64__*/
}
diff --git a/random/rndw32ce.c b/random/rndw32ce.c
index b485eef2..873e8460 100644
--- a/random/rndw32ce.c
+++ b/random/rndw32ce.c
@@ -1,199 +1,199 @@
/* rndw32ce.c - W32CE entropy gatherer
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* Libgcrypt 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.
*
* Libgcrypt 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 .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "types.h"
#include "g10lib.h"
#include "rand-internal.h"
/* The Microsoft docs say that it is suggested to see the buffer with
some extra random. We do this, despite that it is a questionable
suggestion as the OS as better means of collecting entropy than an
application. */
static size_t filler_used;
static size_t filler_length;
static unsigned char *filler_buffer;
static void
filler (const void *data, size_t datalen, enum random_origins dummy)
{
(void)dummy;
if (filler_used + datalen > filler_length)
datalen = filler_length - filler_used;
memcpy (filler_buffer + filler_used, data, datalen);
filler_used += datalen;
}
static void
fillup_buffer (unsigned char *buffer, size_t length)
{
filler_used = 0;
filler_length = length;
filler_buffer = buffer;
while (filler_used < length)
_gcry_rndw32ce_gather_random_fast (filler, 0);
}
int
_gcry_rndw32ce_gather_random (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin,
size_t length, int level )
{
HCRYPTPROV prov;
unsigned char buffer [256];
DWORD buflen;
if (!level)
return 0;
/* Note that LENGTH is not really important because the caller
checks the returned lengths and calls this function until it
feels that enough entropy has been gathered. */
buflen = sizeof buffer;
if (length+8 < buflen)
buflen = length+8; /* Return a bit more than requested. */
if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
log_debug ("CryptAcquireContext failed: rc=%d\n", (int)GetLastError ());
else
{
fillup_buffer (buffer, buflen);
if (!CryptGenRandom (prov, buflen, buffer))
log_debug ("CryptGenRandom(%d) failed: rc=%d\n",
(int)buflen, (int)GetLastError ());
else
(*add) (buffer, buflen, origin);
CryptReleaseContext (prov, 0);
wipememory (buffer, sizeof buffer);
}
return 0;
}
void
_gcry_rndw32ce_gather_random_fast (void (*add)(const void*, size_t,
enum random_origins),
enum random_origins origin)
{
/* Add word sized values. */
{
# define ADD(t,f) do { \
t along = (f); \
memcpy (bufptr, &along, sizeof (along)); \
bufptr += sizeof (along); \
} while (0)
- unsigned char buffer[20*sizeof(ulong)], *bufptr;
+ unsigned char buffer[20*sizeof(unsigned long)], *bufptr;
bufptr = buffer;
ADD (HWND, GetActiveWindow ());
ADD (HWND, GetCapture ());
ADD (HWND, GetClipboardOwner ());
ADD (HANDLE, GetCurrentProcess ());
ADD (DWORD, GetCurrentProcessId ());
ADD (HANDLE, GetCurrentThread ());
ADD (DWORD, GetCurrentThreadId ());
ADD (HWND, GetDesktopWindow ());
ADD (HWND, GetFocus ());
ADD (DWORD, GetMessagePos ());
ADD (HWND, GetOpenClipboardWindow ());
ADD (HWND, GetProcessHeap ());
ADD (DWORD, GetQueueStatus (QS_ALLEVENTS));
ADD (DWORD, GetTickCount ());
gcry_assert ( bufptr-buffer < sizeof (buffer) );
(*add) ( buffer, bufptr-buffer, origin );
# undef ADD
}
/* Get multiword system information: Current caret position, current
mouse cursor position. */
{
POINT point;
GetCaretPos (&point);
(*add) ( &point, sizeof (point), origin );
GetCursorPos (&point);
(*add) ( &point, sizeof (point), origin );
}
/* Get percent of memory in use, bytes of physical memory, bytes of
free physical memory, bytes in paging file, free bytes in paging
file, user bytes of address space, and free user bytes. */
{
MEMORYSTATUS memoryStatus;
memoryStatus.dwLength = sizeof (MEMORYSTATUS);
GlobalMemoryStatus (&memoryStatus);
(*add) ( &memoryStatus, sizeof (memoryStatus), origin );
}
/* Get thread and process creation time, exit time, time in kernel
mode, and time in user mode in 100ns intervals. */
{
HANDLE handle;
FILETIME creationTime, exitTime, kernelTime, userTime;
handle = GetCurrentThread ();
GetThreadTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), origin );
(*add) ( &exitTime, sizeof (exitTime), origin );
(*add) ( &kernelTime, sizeof (kernelTime), origin );
(*add) ( &userTime, sizeof (userTime), origin );
handle = GetCurrentThread ();
GetThreadTimes (handle, &creationTime, &exitTime,
&kernelTime, &userTime);
(*add) ( &creationTime, sizeof (creationTime), origin );
(*add) ( &exitTime, sizeof (exitTime), origin );
(*add) ( &kernelTime, sizeof (kernelTime), origin );
(*add) ( &userTime, sizeof (userTime), origin );
}
/* In case the OEM provides a high precision timer get this. If
none is available the default implementation returns the
GetTickCount. */
{
LARGE_INTEGER performanceCount;
if (QueryPerformanceCounter (&performanceCount))
(*add) (&performanceCount, sizeof (performanceCount), origin);
}
}
diff --git a/src/mpi.h b/src/mpi.h
index c342ff48..39312fc3 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -1,325 +1,325 @@
/* mpi.h - Multi Precision Integers
* Copyright (C) 1994, 1996, 1998,
* 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt 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.
*
* Libgcrypt 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
*/
#ifndef G10_MPI_H
#define G10_MPI_H
#include
#include
#include
#include "types.h"
#include "../mpi/mpi-asm-defs.h"
#include "g10lib.h"
#ifndef _GCRYPT_IN_LIBGCRYPT
#error this file should only be used inside libgcrypt
#endif
#ifndef BITS_PER_MPI_LIMB
#if BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_INT
typedef unsigned int mpi_limb_t;
typedef signed int mpi_limb_signed_t;
#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG
typedef unsigned long int mpi_limb_t;
typedef signed long int mpi_limb_signed_t;
#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_LONG_LONG
typedef unsigned long long int mpi_limb_t;
typedef signed long long int mpi_limb_signed_t;
#elif BYTES_PER_MPI_LIMB == SIZEOF_UNSIGNED_SHORT
typedef unsigned short int mpi_limb_t;
typedef signed short int mpi_limb_signed_t;
#else
#error BYTES_PER_MPI_LIMB does not match any C type
#endif
#define BITS_PER_MPI_LIMB (8*BYTES_PER_MPI_LIMB)
#endif /*BITS_PER_MPI_LIMB*/
#define DBG_MPI _gcry_get_debug_flag( 2 );
struct gcry_mpi
{
int alloced; /* Array size (# of allocated limbs). */
int nlimbs; /* Number of valid limbs. */
int sign; /* Indicates a negative number and is also used
for opaque MPIs to store the length. */
unsigned int flags; /* Bit 0: Array to be allocated in secure memory space.*/
/* Bit 2: The limb is a pointer to some m_alloced data.*/
/* Bit 4: Immutable MPI - the MPI may not be modified. */
/* Bit 5: Constant MPI - the MPI will not be freed. */
mpi_limb_t *d; /* Array with the limbs */
};
#define MPI_NULL NULL
#define mpi_get_nlimbs(a) ((a)->nlimbs)
#define mpi_has_sign(a) ((a)->sign)
/*-- mpiutil.c --*/
#ifdef M_DEBUG
# define mpi_alloc(n) _gcry_mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) )
# define mpi_alloc_secure(n) _gcry_mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) )
# define mpi_free(a) _gcry_mpi_debug_free((a), M_DBGINFO(__LINE__) )
# define mpi_resize(a,b) _gcry_mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) )
# define mpi_copy(a) _gcry_mpi_debug_copy((a), M_DBGINFO(__LINE__) )
gcry_mpi_t _gcry_mpi_debug_alloc( unsigned nlimbs, const char *info );
gcry_mpi_t _gcry_mpi_debug_alloc_secure( unsigned nlimbs, const char *info );
void _gcry_mpi_debug_free( gcry_mpi_t a, const char *info );
void _gcry_mpi_debug_resize( gcry_mpi_t a, unsigned nlimbs, const char *info );
gcry_mpi_t _gcry_mpi_debug_copy( gcry_mpi_t a, const char *info );
#else
# define mpi_alloc(n) _gcry_mpi_alloc((n) )
# define mpi_alloc_secure(n) _gcry_mpi_alloc_secure((n) )
# define mpi_free(a) _gcry_mpi_free((a) )
# define mpi_resize(a,b) _gcry_mpi_resize((a),(b))
# define mpi_copy(a) _gcry_mpi_copy((a))
gcry_mpi_t _gcry_mpi_alloc( unsigned nlimbs );
gcry_mpi_t _gcry_mpi_alloc_secure( unsigned nlimbs );
void _gcry_mpi_free( gcry_mpi_t a );
void _gcry_mpi_resize( gcry_mpi_t a, unsigned nlimbs );
gcry_mpi_t _gcry_mpi_copy( gcry_mpi_t a );
#endif
void _gcry_mpi_immutable_failed (void);
#define mpi_immutable_failed() _gcry_mpi_immutable_failed ()
#define mpi_is_const(a) ((a)->flags&32)
#define mpi_is_immutable(a) ((a)->flags&16)
#define mpi_is_opaque(a) ((a) && ((a)->flags&4))
#define mpi_is_secure(a) ((a) && ((a)->flags&1))
#define mpi_clear(a) _gcry_mpi_clear ((a))
#define mpi_alloc_like(a) _gcry_mpi_alloc_like((a))
#define mpi_alloc_set_ui(a) _gcry_mpi_alloc_set_ui ((a))
#define mpi_m_check(a) _gcry_mpi_m_check ((a))
#define mpi_const(n) _gcry_mpi_const ((n))
#define mpi_swap_cond(a,b,sw) _gcry_mpi_swap_cond ((a),(b),(sw))
#define mpi_set_cond(w,u,set) _gcry_mpi_set_cond ((w),(u),(set))
void _gcry_mpi_clear( gcry_mpi_t a );
gcry_mpi_t _gcry_mpi_set_cond (gcry_mpi_t w, const gcry_mpi_t u,
unsigned long swap);
gcry_mpi_t _gcry_mpi_alloc_like( gcry_mpi_t a );
gcry_mpi_t _gcry_mpi_alloc_set_ui( unsigned long u);
void _gcry_mpi_m_check( gcry_mpi_t a );
void _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b);
void _gcry_mpi_swap_cond (gcry_mpi_t a, gcry_mpi_t b, unsigned long swap);
gcry_mpi_t _gcry_mpi_new (unsigned int nbits);
gcry_mpi_t _gcry_mpi_snew (unsigned int nbits);
gcry_mpi_t _gcry_mpi_set_opaque_copy (gcry_mpi_t a,
const void *p, unsigned int nbits);
void *_gcry_mpi_get_opaque_copy (gcry_mpi_t a, unsigned int *nbits);
int _gcry_mpi_is_neg (gcry_mpi_t a);
void _gcry_mpi_neg (gcry_mpi_t w, gcry_mpi_t u);
void _gcry_mpi_abs (gcry_mpi_t w);
/* Constants used to return constant MPIs. See _gcry_mpi_init if you
want to add more constants. */
#define MPI_NUMBER_OF_CONSTANTS 6
enum gcry_mpi_constants
{
MPI_C_ZERO,
MPI_C_ONE,
MPI_C_TWO,
MPI_C_THREE,
MPI_C_FOUR,
MPI_C_EIGHT
};
gcry_mpi_t _gcry_mpi_const (enum gcry_mpi_constants no);
/*-- mpicoder.c --*/
void _gcry_log_mpidump( const char *text, gcry_mpi_t a );
u32 _gcry_mpi_get_keyid( gcry_mpi_t a, u32 *keyid );
byte *_gcry_mpi_get_buffer (gcry_mpi_t a, unsigned int fill_le,
unsigned int *r_nbytes, int *sign);
byte *_gcry_mpi_get_buffer_extra (gcry_mpi_t a, unsigned int fill_le,
int extraalloc,
unsigned int *r_nbytes, int *sign);
byte *_gcry_mpi_get_secure_buffer (gcry_mpi_t a, unsigned int fill_le,
unsigned *r_nbytes, int *sign);
void _gcry_mpi_set_buffer ( gcry_mpi_t a, const void *buffer,
unsigned int nbytes, int sign );
gpg_err_code_t _gcry_mpi_to_octet_string (unsigned char **r_frame,
void *space,
gcry_mpi_t value, size_t nbytes);
/*-- mpi-div.c --*/
#define mpi_fdiv_r_ui(a,b,c) _gcry_mpi_fdiv_r_ui((a),(b),(c))
#define mpi_fdiv_r(a,b,c) _gcry_mpi_fdiv_r((a),(b),(c))
#define mpi_fdiv_q(a,b,c) _gcry_mpi_fdiv_q((a),(b),(c))
#define mpi_fdiv_qr(a,b,c,d) _gcry_mpi_fdiv_qr((a),(b),(c),(d))
#define mpi_tdiv_r(a,b,c) _gcry_mpi_tdiv_r((a),(b),(c))
#define mpi_tdiv_qr(a,b,c,d) _gcry_mpi_tdiv_qr((a),(b),(c),(d))
#define mpi_tdiv_q_2exp(a,b,c) _gcry_mpi_tdiv_q_2exp((a),(b),(c))
#define mpi_divisible_ui(a,b) _gcry_mpi_divisible_ui((a),(b))
-ulong _gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor );
+unsigned long _gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, unsigned long divisor );
void _gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor );
void _gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor );
void _gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor );
void _gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den);
void _gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den);
void _gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned count );
-int _gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor );
+int _gcry_mpi_divisible_ui(gcry_mpi_t dividend, unsigned long divisor );
/*-- mpi-mod.c --*/
#define mpi_barrett_init(m,f) _gcry_mpi_barrett_init ((m),(f))
#define mpi_barrett_free(c) _gcry_mpi_barrett_free ((c))
#define mpi_mod_barrett(r,a,c) _gcry_mpi_mod_barrett ((r), (a), (c))
#define mpi_mul_barrett(r,u,v,c) _gcry_mpi_mul_barrett ((r), (u), (v), (c))
/* Context used with Barrett reduction. */
struct barrett_ctx_s;
typedef struct barrett_ctx_s *mpi_barrett_t;
mpi_barrett_t _gcry_mpi_barrett_init (gcry_mpi_t m, int copy);
void _gcry_mpi_barrett_free (mpi_barrett_t ctx);
void _gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx);
void _gcry_mpi_mul_barrett (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v,
mpi_barrett_t ctx);
/*-- mpi-mpow.c --*/
#define mpi_mulpowm(a,b,c,d) _gcry_mpi_mulpowm ((a),(b),(c),(d))
void _gcry_mpi_mulpowm( gcry_mpi_t res, gcry_mpi_t *basearray, gcry_mpi_t *exparray, gcry_mpi_t mod);
/*-- mpi-scan.c --*/
#define mpi_trailing_zeros(a) _gcry_mpi_trailing_zeros ((a))
int _gcry_mpi_getbyte( gcry_mpi_t a, unsigned idx );
void _gcry_mpi_putbyte( gcry_mpi_t a, unsigned idx, int value );
unsigned _gcry_mpi_trailing_zeros( gcry_mpi_t a );
/*-- mpi-bit.c --*/
#define mpi_normalize(a) _gcry_mpi_normalize ((a))
void _gcry_mpi_normalize( gcry_mpi_t a );
/*-- ec.c --*/
/* Object to represent a point in projective coordinates. */
struct gcry_mpi_point
{
gcry_mpi_t x;
gcry_mpi_t y;
gcry_mpi_t z;
};
typedef struct gcry_mpi_point mpi_point_struct;
typedef struct gcry_mpi_point *mpi_point_t;
void _gcry_mpi_point_init (mpi_point_t p);
void _gcry_mpi_point_free_parts (mpi_point_t p);
void _gcry_mpi_get_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
mpi_point_t point);
void _gcry_mpi_snatch_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
mpi_point_t point);
/* Models describing an elliptic curve. */
enum gcry_mpi_ec_models
{
/* The Short Weierstrass equation is
y^2 = x^3 + ax + b
*/
MPI_EC_WEIERSTRASS = 0,
/* The Montgomery equation is
by^2 = x^3 + ax^2 + x
*/
MPI_EC_MONTGOMERY,
/* The Twisted Edwards equation is
ax^2 + y^2 = 1 + bx^2y^2
Note that we use 'b' instead of the commonly used 'd'. */
MPI_EC_EDWARDS
};
/* Dialects used with elliptic curves. It is easier to keep the
definition here than in ecc-common.h. */
enum ecc_dialects
{
ECC_DIALECT_STANDARD = 0,
ECC_DIALECT_ED25519,
ECC_DIALECT_SAFECURVE
};
void _gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx);
#define log_printpnt(a,p,c) _gcry_mpi_point_log ((a), (p), (c))
mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b);
gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b);
void _gcry_mpi_ec_free (mpi_ec_t ctx);
void _gcry_mpi_ec_dup_point (mpi_point_t result,
mpi_point_t point, mpi_ec_t ctx);
void _gcry_mpi_ec_add_points (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx);
void _gcry_mpi_ec_sub_points (mpi_point_t result,
mpi_point_t p1, mpi_point_t p2,
mpi_ec_t ctx);
void _gcry_mpi_ec_mul_point (mpi_point_t result,
gcry_mpi_t scalar, mpi_point_t point,
mpi_ec_t ctx);
int _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx);
int _gcry_mpi_ec_bad_point (gcry_mpi_point_t point, mpi_ec_t ctx);
gcry_mpi_t _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ectx);
gcry_mpi_t _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy);
gcry_mpi_point_t _gcry_mpi_ec_get_point (const char *name,
gcry_ctx_t ctx, int copy);
gpg_err_code_t _gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
gcry_ctx_t ctx);
gpg_err_code_t _gcry_mpi_ec_set_point (const char *name,
gcry_mpi_point_t newvalue,
gcry_ctx_t ctx);
gpg_err_code_t _gcry_mpi_ec_decode_point (mpi_point_t result,
gcry_mpi_t value, mpi_ec_t ec);
/*-- ecc-curves.c --*/
gpg_err_code_t _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
gcry_sexp_t keyparam, const char *curvename);
gpg_err_code_t _gcry_mpi_ec_internal_new (mpi_ec_t *r_ec, int *r_flags,
const char *name_op,
gcry_sexp_t keyparam,
const char *curvename);
#endif /*G10_MPI_H*/
diff --git a/src/types.h b/src/types.h
index 645ddd62..39393be1 100644
--- a/src/types.h
+++ b/src/types.h
@@ -1,142 +1,136 @@
/* types.h - some common typedefs
* Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt 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.
*
* Libgcrypt 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef GCRYPT_TYPES_H
#define GCRYPT_TYPES_H
#ifndef _GCRYPT_CONFIG_H_INCLUDED
# error config.h must be included before types.h
#endif
/* The AC_CHECK_SIZEOF() in configure fails for some machines.
* we provide some fallback values here */
#if !SIZEOF_UNSIGNED_SHORT
# undef SIZEOF_UNSIGNED_SHORT
# define SIZEOF_UNSIGNED_SHORT 2
#endif
#if !SIZEOF_UNSIGNED_INT
# undef SIZEOF_UNSIGNED_INT
# define SIZEOF_UNSIGNED_INT 4
#endif
#if !SIZEOF_UNSIGNED_LONG
# undef SIZEOF_UNSIGNED_LONG
# define SIZEOF_UNSIGNED_LONG 4
#endif
#include
/* Provide uintptr_t */
#ifdef HAVE_STDINT_H
# include /* uintptr_t */
#elif defined(HAVE_INTTYPES_H)
# include
#else
/* In this case, uintptr_t is provided by config.h. */
#endif
#ifndef HAVE_BYTE_TYPEDEF
# undef byte /* In case there is a macro with that name. */
# if !(defined(_WIN32) && defined(cbNDRContext))
/* Windows typedefs byte in the rpc headers. Avoid warning about
double definition. */
typedef unsigned char byte;
# endif
# define HAVE_BYTE_TYPEDEF
#endif
#ifndef HAVE_USHORT_TYPEDEF
# undef ushort /* In case there is a macro with that name. */
typedef unsigned short ushort;
# define HAVE_USHORT_TYPEDEF
#endif
-#ifndef HAVE_ULONG_TYPEDEF
-# undef ulong /* In case there is a macro with that name. */
- typedef unsigned long ulong;
-# define HAVE_ULONG_TYPEDEF
-#endif
-
#ifndef HAVE_U16_TYPEDEF
# undef u16 /* In case there is a macro with that name. */
# if SIZEOF_UNSIGNED_INT == 2
typedef unsigned int u16;
# elif SIZEOF_UNSIGNED_SHORT == 2
typedef unsigned short u16;
# else
# error no typedef for u16
# endif
# define HAVE_U16_TYPEDEF
#endif
#ifndef HAVE_U32_TYPEDEF
# undef u32 /* In case there is a macro with that name. */
# if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int u32;
# elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long u32;
# else
# error no typedef for u32
# endif
# define HAVE_U32_TYPEDEF
#endif
/*
* Warning: Some systems segfault when this u64 typedef and
* the dummy code in cipher/md.c is not available. Examples are
* Solaris and IRIX.
*/
#ifndef HAVE_U64_TYPEDEF
# undef u64 /* In case there is a macro with that name. */
# if SIZEOF_UNSIGNED_INT == 8
typedef unsigned int u64;
# define U64_C(c) (c ## U)
# define HAVE_U64_TYPEDEF
# elif SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long u64;
# define U64_C(c) (c ## UL)
# define HAVE_U64_TYPEDEF
# elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long u64;
# define U64_C(c) (c ## ULL)
# define HAVE_U64_TYPEDEF
# elif SIZEOF_UINT64_T == 8
typedef uint64_t u64;
# define U64_C(c) (UINT64_C(c))
# define HAVE_U64_TYPEDEF
# else
# error No way to declare a 64 bit integer type
# endif
#endif
typedef union
{
int a;
short b;
char c[1];
long d;
u64 e;
float f;
double g;
} PROPERLY_ALIGNED_TYPE;
#endif /*GCRYPT_TYPES_H*/