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*/