diff options
Diffstat (limited to 'm4macros/ax_crypto.m4')
-rw-r--r-- | m4macros/ax_crypto.m4 | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/m4macros/ax_crypto.m4 b/m4macros/ax_crypto.m4 new file mode 100644 index 0000000..c075aba --- /dev/null +++ b/m4macros/ax_crypto.m4 @@ -0,0 +1,460 @@ +# Simplified, non-caching AC_CHECK_PROG +# Searches $PATH for the existence of argument 2, +# and sets the full path to the variable in argument 1. +# if not found, and a third argument is given, the value +# is set to that. If not, the value is untouched. +# Does not take absolute paths into account at this point, +# and also works for single files only (arguments are not +# stripped like in AC_CHECK_PROG) +AC_DEFUN([ACX_CHECK_PROG_NONCACHE], [ + RESULT="" + IFS_SAVED="$IFS" + IFS=${PATH_SEPARATOR} + for cur_path in ${PATH} ; do + if test -e "${cur_path}/$2" ; then + RESULT="${cur_path}/$2" + fi + done + if test "$RESULT" = "" ; then + : + m4_ifvaln([$3], [$1=$3]) + else + $1=$RESULT + fi + IFS="$IFS_SAVED" +]) + +AC_DEFUN([ACX_TRY_BOTAN_TOOL], [ + TOOL=$1 + TOOL_ARG=$2 + BOTAN_TOOL="" + ACX_CHECK_PROG_NONCACHE([BOTAN_TOOL], [${TOOL}]) + AC_MSG_CHECKING([usability of ${TOOL} ${TOOL_ARG}]) + if test "$BOTAN_TOOL" != "" ; then + if test -x ${BOTAN_TOOL}; then + CRYPTO_LIBS=`$BOTAN_TOOL $TOOL_ARG --libs` + LIBS_SAVED=${LIBS} + LIBS="$LIBS $CRYPTO_LIBS" + CRYPTO_INCLUDES=`$BOTAN_TOOL $TOOL_ARG --cflags` + CPPFLAGS_SAVED=${CPPFLAGS} + CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS" + #AC_MSG_RESULT([found]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include <botan/lookup.h>], + [using namespace Botan; + HashFunction *h = HashFunction::create("MD5").release(); + ])], + [ AC_MSG_RESULT([ok]) + $3 + ], + [ AC_MSG_RESULT([not usable]) ] + ) + LIBS=${LIBS_SAVED} + CPPFLAGS=${CPPFLAGS_SAVED} + else + AC_MSG_RESULT([not executable]) + fi + else + AC_MSG_RESULT([not found]) + fi + BOTAN_TOOL="" + AC_SUBST(BOTAN_TOOL) + ] +) +# End of ACX_TRY_BOTAN_TOOL + + +AC_DEFUN([AX_CRYPTO], [ +# Check for Botan +# +# Unless --with-botan-config is given, we first try to find these config +# scripts ourselves. Unfortunately, on some systems, these scripts do not +# provide the correct implementation, so for each script found, we try +# a compilation test (ACX_TRY_BOTAN_TOOL). If none are found, or none of +# them work, we see if pkg-config is available. If so, we try the several +# potential pkg-config .pc files. Again, on some systems, these can return +# incorrect information as well, so the try-compile test is repeated for +# each. +# +# If a working config script or pkgconfig file is found, we then munge its +# output for use in our Makefiles, and to make sure it works, another header +# and compilation test is done (this should also check whether we can compile +# against botan should neither -config scripts nor pkgconfig data exist). +# + +# Avoid checking Botan if OpenSSL is wanted +AC_ARG_WITH([openssl], + [AS_HELP_STRING([--with-openssl[[=PATH]]], [Enables OpenSSL, + location can be specified optionally])], + [use_openssl="$withval"], + [use_openssl="auto"]) + +botan_config="yes" +if test "${use_openssl}" != "auto" -a "${use_openssl}" != "no" ; then + botan_config="no" +fi +AC_ARG_WITH([botan-config], + [AS_HELP_STRING([--with-botan-config=PATH], + [specify the path to the botan-config script])], + [botan_config="$withval"]) +distcheck_botan="--with-botan-config=$botan_config" +if test "${botan_config}" = "no" ; then + if test "${use_openssl}" = "no" ; then + AC_MSG_ERROR([Need Botan or OpenSSL for libcryptolink]) + fi +elif test "${botan_config}" != "yes" ; then + if test -x "${botan_config}" ; then + if test -d "${botan_config}" ; then + AC_MSG_ERROR([${botan_config} is a directory]) + fi + else + AC_MSG_ERROR([--with-botan-config should point to a botan-config program and not a directory (${botan_config})]) + fi +else + BOTAN_CONFIG="" + AC_PATH_PROG([PKG_CONFIG], [pkg-config]) + if test "$PKG_CONFIG" != "" ; then + BOTAN_VERSIONS="botan-2" + for version in $BOTAN_VERSIONS; do + ACX_TRY_BOTAN_TOOL([pkg-config], ["$version --silence-errors"], + [ BOTAN_CONFIG="$PKG_CONFIG $version" ] + ) + if test "$BOTAN_CONFIG" != "" ; then + break + fi + done + fi +fi + +if test "$BOTAN_CONFIG" != "" +then + CRYPTO_LIBS=`${BOTAN_CONFIG} --libs` + CRYPTO_INCLUDES=`${BOTAN_CONFIG} --cflags` + + # We expect botan-config --libs to contain -L<path_to_libbotan>, but + # this is not always the case. As a heuristics workaround we add + # -L`botan-config --prefix/lib` in this case (if not present already). + # Same for CRYPTO_INCLUDES (but using include instead of lib) below. + if [ ${BOTAN_CONFIG} --prefix >/dev/null 2>&1 ] ; then + echo ${CRYPTO_LIBS} | grep -- -L > /dev/null || \ + CRYPTO_LIBS="-L`${BOTAN_CONFIG} --prefix`/lib ${CRYPTO_LIBS}" + echo ${CRYPTO_INCLUDES} | grep -- -I > /dev/null || \ + CRYPTO_INCLUDES="-I`${BOTAN_CONFIG} --prefix`/include ${CRYPTO_INCLUDES}" + fi +fi + +if test "x${CRYPTO_LIBS}" != "x" +then + dnl Determine the Botan version + AC_MSG_CHECKING([Botan version]) + cat > conftest.cpp << EOF +#include <botan/version.h> +AUTOCONF_BOTAN_VERSION=BOTAN_VERSION_MAJOR . BOTAN_VERSION_MINOR . BOTAN_VERSION_PATCH +EOF + + CRYPTO_VERSION=`$CPPP $CPPFLAGS $CRYPTO_INCLUDES conftest.cpp | grep '^AUTOCONF_BOTAN_VERSION=' | $SED -e 's/^AUTOCONF_BOTAN_VERSION=//' -e 's/[[ ]]//g' -e 's/"//g' 2> /dev/null` + if test -z "$CRYPTO_VERSION"; then + CRYPTO_VERSION="unknown" + fi + $RM -f conftest.cpp + AC_MSG_RESULT([$CRYPTO_VERSION]) + + # botan-config script (and the way we call pkg-config) returns -L and -l + # as one string, but we need them in separate values + CRYPTO_LDFLAGS= + for flag in ${CRYPTO_LIBS}; do + CRYPTO_LDFLAGS="${CRYPTO_LDFLAGS} `echo $flag | ${SED} -ne '/^\(\-L\)/p'`" + CRYPTO_LIBS="${CRYPTO_LIBS} `echo $flag | ${SED} -ne '/^\(\-l\)/p'`" + done + + # # check -R, "-Wl,-R" or -rpath + AX_ISC_RPATH + + # See crypto_rpath for some info on why we do this + if test "x$ISC_RPATH_FLAG" != "x"; then + CRYPTO_RPATH= + for flag in ${CRYPTO_LIBS}; do + CRYPTO_RPATH="${CRYPTO_RPATH} `echo $flag | ${SED} -ne "s/^\(\-L\)/${ISC_RPATH_FLAG}/p"`" + done + # According to the libtool manual, it should be sufficient if we + # specify the "-R libdir" in our wrapper library of botan (no other + # programs will need libbotan directly); "libdir" should be added to + # the program's binary image. But we've seen in our build environments + # that (some versions of?) libtool doesn't propagate -R as documented, + # and it caused a linker error at run time. To work around this, we + # also add the rpath to the global LDFLAGS. + LDFLAGS="$CRYPTO_RPATH $LDFLAGS" + fi + + # Even though chances are high we already performed a real compilation check + # in the search for the right (pkg)config data, we try again here, to + # be sure. + CPPFLAGS_SAVED=$CPPFLAGS + CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS" + LIBS_SAVED="$LIBS" + LIBS="$LIBS $CRYPTO_LIBS" + + # ac_header_preproc is an autoconf symbol (undocumented but stable) that + # is set if the pre-processor phase passes. Thus by adding a custom + # failure handler we can detect the difference between a header not existing + # (or not even passing the pre-processor phase) and a header file resulting + # in compilation failures. + AC_CHECK_HEADERS([botan/botan.h],,[ + CRYPTO_INCLUDES="" + CRYPTO_LIBS="" + CRYPTO_LDFLAGS="" + CRYPTO_RPATH="" + if test "x$ac_header_preproc" = "xyes"; then + AC_MSG_RESULT([botan/botan.h +was found but is unusable. The most common cause of this problem +is attempting to use an updated C++ compiler with older C++ libraries, such as +the version of Botan that comes with your distribution. If you have updated +your C++ compiler we highly recommend that you use support libraries such as +Boost and Botan that were compiled with the same compiler version.]) + else + AC_MSG_RESULT([Missing required libcrypto header files]) + fi] + ) + CPPFLAGS=$CPPFLAGS_SAVED + LIBS=$LIBS_SAVED +fi + +if test "x${CRYPTO_LIBS}" != "x" +then + CPPFLAGS_SAVED=$CPPFLAGS + CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS" + LIBS_SAVED="$LIBS" + LIBS="$LIBS $CRYPTO_LIBS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([#include <botan/lookup.h>], + [using namespace Botan; + HashFunction *h = HashFunction::create("MD5") +.release(); + ])], + [AC_MSG_RESULT([checking for Botan library... yes])], + [AC_MSG_RESULT([checking for Botan library... no]) + CRYPTO_INCLUDES="" + CRYPTO_LIBS="" + CRYPTO_LDFLAGS="" + CRYPTO_RPATH="" + AC_MSG_RESULT([Needs Botan library 2.0 or higher. On some systems, + the botan package has a few missing dependencies (libbz2 and + libgmp), if libbotan has been installed and you see this message, + try upgrading to a higher version of botan or installing libbz2 + and libgmp.])] + ) + CPPFLAGS=$CPPFLAGS_SAVED + LIBS=$LIBS_SAVED + CRYPTO_NAME="Botan" + CRYPTO_PACKAGE="botan-2" +fi + +if test "x${CRYPTO_LIBS}" != "x" +then + DISABLED_CRYPTO="OpenSSL" + CRYPTO_CFLAGS="" + DISTCHECK_CRYPTO_CONFIGURE_FLAG="$distcheck_botan" + AC_DEFINE_UNQUOTED([WITH_BOTAN], [], [Compile with Botan crypto]) +else + CRYPTO_NAME="OpenSSL" + DISABLED_CRYPTO="Botan" + CRYPTO_PACKAGE="openssl-1.1.0" + DISTCHECK_CRYPTO_CONFIGURE_FLAG="--with-openssl=${use_openssl}" + AC_DEFINE_UNQUOTED([WITH_OPENSSL], [], [Compile with OpenSSL crypto]) + AC_MSG_CHECKING(for OpenSSL library) + openssl_headers= + openssl_libraries= + + case "${use_openssl}" in + auto) + use_openssl="yes" + ;; + yes) + ;; + *) + # no was already handled + openssl_headers="${use_openssl}/include" + openssl_libraries="${use_openssl}/lib" + ;; + esac + + # Now search for the system OpenSSL library. + if test "${use_openssl}" = "yes" ; then + for d in /usr /usr/local /usr/local/ssl /usr/local/opt/openssl /usr/pkg /usr/sfw; do + if test -f $d/include/openssl/opensslv.h; then + use_openssl="${d}" + openssl_headers="${d}/include" + for l in lib lib64; do + if test -f "${d}/${l}/libssl.so"; then + openssl_libraries="${d}/${l}" + break + fi + done + if test -n "${openssl_headers}" && test -n "${openssl_libraries}"; then + break + fi + fi + done + fi + + if test "${use_openssl}" = "yes" ; then + AC_MSG_ERROR([OpenSSL auto detection failed]) + fi + AC_MSG_RESULT(yes) + + if test "${openssl_headers}" = "/usr/include" ; then + CRYPTO_CFLAGS="" + CRYPTO_INCLUDES="" + CRYPTO_LIBS="-lssl -lcrypto" + else + CRYPTO_CFLAGS="" + CRYPTO_INCLUDES="-I${openssl_headers}" + case $host in + *-solaris*) + CRYPTO_LIBS="-L${openssl_libraries} -R${openssl_libraries} -lssl -lcrypto" + ;; + *-hp-hpux*) + CRYPTO_LIBS="-L${openssl_libraries} -Wl,+b: -lssl -lcrypto" + ;; + *-apple-darwin*) + if test -f "${openssl_libraries}/libcrypto.dylib" ; then + CRYPTO_LIBS="-L${openssl_libraries} -lssl -lcrypto" + else + CRYPTO_LIBS="${openssl_libraries}/libssl.a ${openssl_libraries}/libcrypto.a" + fi + ;; + *) + CRYPTO_LIBS="-L${openssl_libraries} -lssl -lcrypto" + ;; + esac + fi + dnl Determine the OpenSSL version + # Officially we support >= 1.0.1, 0.9.8 should fail the HMAC API, + # 1.0.0 could work but is not recommended. + AC_MSG_CHECKING([OpenSSL version]) + cat > conftest.cpp << EOF +#include <openssl/opensslv.h> +AUTOCONF_OPENSSL_VERSION=OPENSSL_VERSION_TEXT +EOF + + CRYPTO_VERSION=`$CPPP $CPPFLAGS $CRYPTO_INCLUDES conftest.cpp | grep '^AUTOCONF_OPENSSL_VERSION=' | $SED -e 's/^AUTOCONF_OPENSSL_VERSION=//' -e 's/"//g' 2> /dev/null` + if test -z "$CRYPTO_VERSION" ; then + CRYPTO_VERSION="unknown" + fi + $RM -f conftest.cpp + AC_MSG_RESULT([$CRYPTO_VERSION]) + #CRYPTO_LDFLAGS="-ldl" + CRYPTO_LDFLAGS="" + CRYPTO_RPATH="" + AC_MSG_CHECKING([support of SHA-2]) + LIBS_SAVED=${LIBS} + LIBS="$LIBS $CRYPTO_LIBS" + CPPFLAGS_SAVED=${CPPFLAGS} + CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS" + dnl Check availability of legacy hash + AC_CHECK_FUNC([EVP_md5],,[missing EVP entry for MD5]) + AC_CHECK_FUNC([EVP_sha1],,[missing EVP entry for SHA1]) + dnl Check availability of SHA-2 + AC_CHECK_FUNC([EVP_sha224],,[missing EVP entry for SHA224]) + AC_CHECK_FUNC([EVP_sha256],,[missing EVP entry for SHA256]) + AC_CHECK_FUNC([EVP_sha384],,[missing EVP entry for SHA384]) + AC_CHECK_FUNC([EVP_sha512],,[missing EVP entry for SHA512]) + dnl Two generations of EVP_MD_CTX functions + AC_CHECK_FUNCS([EVP_MD_CTX_new EVP_MD_CTX_free],, + [AC_CHECK_FUNCS([EVP_MD_CTX_create EVP_MD_CTX_destroy],, + [AC_MSG_ERROR([missing EVP MD CTX functions])])]) + dnl Same for EVP and HMAC + AC_CHECK_FUNCS([EVP_PKEY_new_raw_private_key],, + [AC_CHECK_FUNCS([EVP_PKEY_new_mac_key],, + [AC_MSG_ERROR([missing EVP PKEY new key function])])]) + LIBS=${LIBS_SAVED} + CPPFLAGS=${CPPFLAGS_SAVED} +fi + +AM_CONDITIONAL(HAVE_BOTAN, test "$CRYPTO_NAME" = "Botan") +AM_CONDITIONAL(HAVE_OPENSSL, test "$CRYPTO_NAME" = "OpenSSL") +AC_SUBST(CRYPTO_INCLUDES) +AC_SUBST(CRYPTO_CFLAGS) +AC_SUBST(CRYPTO_LIBS) +AC_SUBST(CRYPTO_LDFLAGS) +AC_SUBST(CRYPTO_PACKAGE) +AC_SUBST(CRYPTO_RPATH) +AC_SUBST(DISTCHECK_CRYPTO_CONFIGURE_FLAG) +] +) +# End of AX_CRYPTO + +# Test TLS support using both crypto and boost. +AC_DEFUN([AX_TLS], [ +if test "x${CRYPTO_NAME}" = "xBotan" +then + dnl Check Botan boost ASIO TLS + CPPFLAGS_SAVED=$CPPFLAGS + CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS $BOOST_INCLUDES" + BOTAN_BOOST="" + AC_CHECK_HEADERS([botan/asio_stream.h], + [BOTAN_BOOST="maybe" + AC_MSG_CHECKING([Botan boost TLS support]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include <botan/asio_stream.h>], + [#ifndef BOTAN_TLS_SERVER_H_ + #error botan/tls_server.h is not included by botan/asio_stream.h + #endif])], + [AC_MSG_RESULT(yes) + BOTAN_BOOST="yes" + AC_DEFINE([WITH_BOTAN_BOOST], [1], + [Define to 1 if Botan boost TLS is available])], + [AC_MSG_RESULT(no) + BOTAN_BOOST="no" + AC_MSG_WARN([Botan is configured with boost support but is too old: only Botan >= 2.14.0 can be used for TLS support.])])], + [BOTAN_BOOST="no" + AC_MSG_WARN([Botan cannot be used for TLS support, because it was compiled without boost support, so required headers are missing.])]) + CPPFLAGS=${CPPFLAGS_SAVED} +fi +if test "x${CRYPTO_NAME}" = "xOpenSSL" +then + CPPFLAGS_SAVED=$CPPFLAGS + CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS $BOOST_INCLUDES" + dnl Check boost ASIO SSL + AC_CHECK_HEADERS([boost/asio/ssl.hpp],, + [AC_MSG_ERROR([Missing required boost ssl header file])]) + dnl Check if the generic TLS method is available + AC_MSG_CHECKING([Generic TLS method]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include <boost/asio/ssl.hpp>], + [auto ctx(boost::asio::ssl::context::tls);])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_GENERIC_TLS_METHOD], [1], + [Define to 1 if boost::asio::ssl::context::tls is available])], + [AC_MSG_RESULT(no) + AC_MSG_CHECKING([Verifying TLS 1.2 fallback]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include <boost/asio/ssl.hpp>], + [auto ctx(boost::asio::ssl::context::tlsv12);])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_TLS_1_2_METHOD], [1], + [Define to 1 if boost::asio::ssl::context::tlsv12 is available])], + [AC_MSG_RESULT(no) + AC_MSG_WARN([The boost version is very old: TLS support can use insecure features])])]) + dnl Check if the stream_truncated (SSL short read) error is available + AC_MSG_CHECKING([stream_truncated (SSL short read) error]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include <boost/asio/ssl.hpp>], + [const int ec = + boost::asio::ssl::error::stream_truncated;])], + [AC_MSG_RESULT(yes) + AC_DEFINE([HAVE_STREAM_TRUNCATED_ERROR], [1], + [Define to 1 if boost::asio::ssl::error::stream_truncated is available])], + [AC_MSG_RESULT(no) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([#include <boost/asio/ssl.hpp>], + [const int ec = + ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ);])], + [], + [AC_MSG_ERROR([Can not find a definition for stream_truncated (SSL short read) error: sorry, your boost library is too old])])]) + CPPFLAGS=${CPPFLAGS_SAVED} +fi +AM_CONDITIONAL(HAVE_BOTAN_BOOST, + test "$CRYPTO_NAME" = "Botan" && test "$BOTAN_BOOST" = "yes") +]) +# End of AX_TLS |