IFS="$IFS_SAVED"
])
+AC_DEFUN([ACX_TRY_BOTAN1_TOOL], [
+ TOOL=$1
+ TOOL_ARG=$2
+ BOTAN1_TOOL=""
+ ACX_CHECK_PROG_NONCACHE([BOTAN1_TOOL], [${TOOL}])
+ AC_MSG_CHECKING([usability of ${TOOL} ${TOOL_ARG}])
+ if test "$BOTAN1_TOOL" != "" ; then
+ if test -x ${BOTAN1_TOOL}; then
+ CRYPTO_LIBS=`$BOTAN1_TOOL $TOOL_ARG --libs`
+ LIBS_SAVED=${LIBS}
+ LIBS="$LIBS $CRYPTO_LIBS"
+ CRYPTO_INCLUDES=`$BOTAN1_TOOL $TOOL_ARG --cflags`
+ CPPFLAGS_SAVED=${CPPFLAGS}
+ CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS"
+ #AC_MSG_RESULT([found])
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([#include <botan/botan.h>
+ #include <botan/init.h>
+ #include <botan/hash.h>
+ ],
+ [using namespace Botan;
+ LibraryInitializer::initialize();
+ HashFunction *h = get_hash("MD5");
+ ])],
+ [ 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
+ BOTAN1_TOOL=""
+ AC_SUBST(BOTAN1_TOOL)
+ ]
+)
+# End of ACX_TRY_BOTAN1_TOOL
+
AC_DEFUN([ACX_TRY_BOTAN_TOOL], [
TOOL=$1
TOOL_ARG=$2
CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS"
#AC_MSG_RESULT([found])
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([#include <botan/botan.h>
- #include <botan/init.h>
- #include <botan/hash.h>
- ],
+ [AC_LANG_PROGRAM([#include <botan/lookup.h>],
[using namespace Botan;
- LibraryInitializer::initialize();
- HashFunction *h = get_hash("MD5");
+ HashFunction *h = HashFunction::create("MD5").release();
])],
[ AC_MSG_RESULT([ok])
$3
# 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
+# a compilation test (ACX_TRY_BOTAN[1]_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
if test -d "${botan_config}" ; then
AC_MSG_ERROR([${botan_config} is a directory])
else
- BOTAN_CONFIG="${botan_config}"
+ BOTAN1_CONFIG="${botan_config}"
fi
else
AC_MSG_ERROR([--with-botan-config should point to a botan-config program and not a directory (${botan_config})])
fi
+ # determine Botan major version
+ BOTAN_CONFIG="${BOTAN1_CONFIG}"
+ cat > conftest.cpp << EOF
+#include <botan/version.h>
+MAJOR_VERSION=BOTAN_VERSION_MAJOR
+EOF
+ CRYPTO_INCLUDES=`$BOTAN1_CONFIG --cflags`
+ MAJOR_VERSION=`$CXX -E $CXXFLAGS $CRYPTO_INCLUDES conftest.cpp | grep '^MAJOR_VERSION=' | $SED -e 's/MAJOR_VERSION=//' -e 's/[[ ]]//g' -e 's/"//g' 2> /dev/null`
+ if test "x${MAJOR_VERSION}" = "x2"; then
+ BOTAN1_CONFIG=""
+ fi
+ $RM -f conftest.cpp
else
BOTAN_CONFIG=""
+ BOTAN1_CONFIG=""
# first try several possible names of the config script
- # (botan-config-1.8 is there just in case, the official name change
+ # (botan-config-1.9 is there just in case, the official name change
# came later)
- BOTAN_CONFIG_VERSIONS="botan-config-1.10 botan-config-1.9 botan-config-1.8 botan-config"
- for botan_config in $BOTAN_CONFIG_VERSIONS; do
- ACX_TRY_BOTAN_TOOL([$botan_config],,
- [ BOTAN_CONFIG="$botan_config" ]
- )
- if test "$BOTAN_CONFIG" != "" ; then
+ BOTAN1_CONFIG_VERSIONS="botan-config-1.11 botan-config-1.10 botan-config-1.9 botan-config"
+ for botan1_config in $BOTAN1_CONFIG_VERSIONS; do
+ ACX_TRY_BOTAN1_TOOL([$botan1_config],,
+ [ BOTAN1_CONFIG="$botan1_config" ]
+ )
+ if test "$BOTAN1_CONFIG" != "" ; then
+ BOTAN_CONFIG="${BOTAN1_CONFIG}"
break
fi
done
- if test "$BOTAN_CONFIG" = "" ; then
- AC_PATH_PROG([PKG_CONFIG], [pkg-config])
- if test "$PKG_CONFIG" != "" ; then
+ AC_PATH_PROG([PKG_CONFIG], [pkg-config])
+ if test "$PKG_CONFIG" != "" ; then
+ if test "$BOTAN1_CONFIG" = "" ; then
# Ok so no script found, see if pkg-config knows of it.
# Unfortunately, the botan.pc files also have their minor version
# in their name, so we need to try them one by one
- BOTAN_VERSIONS="botan-2 botan-1.11 botan-1.10 botan-1.9 botan-1.8"
+ BOTAN1_VERSIONS="botan-1.11 botan-1.10 botan-1.9 botan-1.8"
+ for version in $BOTAN1_VERSIONS; do
+ ACX_TRY_BOTAN1_TOOL([pkg-config],
+ ["$version --silence-errors"],
+ [ BOTAN1_CONFIG="$PKG_CONFIG $version" ]
+ )
+ if test "$BOTAN1_CONFIG" != "" ; then
+ BOTAN_CONFIG="${BOTAN1_CONFIG}"
+ break
+ fi
+ done
+ fi
+ if test "$BOTAN_CONFIG" = "" ; then
+ # Retry with Botan2
+ 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
+ if test "$BOTAN_CONFIG" != "" ; then
+ break
+ fi
done
fi
fi
fi
-if test "x${BOTAN_CONFIG}" != "x"
+if test "$BOTAN_CONFIG" != ""
then
CRYPTO_LIBS=`${BOTAN_CONFIG} --libs`
CRYPTO_INCLUDES=`${BOTAN_CONFIG} --cflags`
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`
+ 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
# 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],,[
+ HEADER_TO_CHECK=botan/botan.h
+ if test "BOTAN1_CONFIG" = ""; then
+ HEADER_TO_CHECK=botan/lookup.h
+ fi
+ AC_CHECK_HEADERS([${HEADER_TO_CHECK}],,[
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
+ AC_MSG_RESULT([${HEADER_TO_CHECK}
+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
LIBS=$LIBS_SAVED
fi
-if test "x${CRYPTO_LIBS}" != "x"
+if test "x${BOTAN1_CONFIG}" != "x"
then
CPPFLAGS_SAVED=$CPPFLAGS
CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS"
LibraryInitializer::initialize();
HashFunction *h = get_hash("MD5");
])],
+ [AC_MSG_RESULT([checking for Botan1 library... yes])],
+ [AC_MSG_RESULT([checking for Botan1 library... no])
+ CRYPTO_INCLUDES=""
+ CRYPTO_LIBS=""
+ CRYPTO_LDFLAGS=""
+ CRYPTO_RPATH=""
+ AC_MSG_RESULT([Needs Botan library 1.9 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="Botan1"
+ CRYPTO_PACKAGE="botan-1.11"
+elif 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 1.8 or higher. On some systems,
+ 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
)
CPPFLAGS=$CPPFLAGS_SAVED
LIBS=$LIBS_SAVED
+ CRYPTO_NAME="Botan"
+ CRYPTO_PACKAGE="botan-2"
fi
if test "x${CRYPTO_LIBS}" != "x"
then
- CRYPTO_NAME="Botan"
DISABLED_CRYPTO="OpenSSL"
- CRYPTO_PACKAGE="botan-1.8"
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.0.2"
+ CRYPTO_PACKAGE="openssl-1.1.0"
AC_DEFINE_UNQUOTED([WITH_OPENSSL], [], [Compile with OpenSSL crypto])
AC_MSG_CHECKING(for OpenSSL library)
# from bind9
else
CRYPTO_CFLAGS=""
CRYPTO_INCLUDES="-I${use_openssl}/include"
+ OPENSSL_LIBDIR="${use_openssl}/lib"
DISTCHECK_CRYPTO_CONFIGURE_FLAG="--with-openssl=${use_openssl}"
case $host in
*-solaris*)
CPPFLAGS=${CPPFLAGS_SAVED}
fi
+AM_CONDITIONAL(HAVE_BOTAN1, test "$CRYPTO_NAME" = "Botan1")
AM_CONDITIONAL(HAVE_BOTAN, test "$CRYPTO_NAME" = "Botan")
AM_CONDITIONAL(HAVE_OPENSSL, test "$CRYPTO_NAME" = "OpenSSL")
AC_SUBST(CRYPTO_INCLUDES)
AC_SUBST(CRYPTO_PACKAGE)
AC_SUBST(CRYPTO_RPATH)
AC_SUBST(DISTCHECK_CRYPTO_CONFIGURE_FLAG)
+AC_SUBST(OPENSSL_LIBDIR)
]
)
libkea_cryptolink_la_SOURCES = cryptolink.h cryptolink.cc
libkea_cryptolink_la_SOURCES += crypto_hash.h crypto_hash.cc
libkea_cryptolink_la_SOURCES += crypto_hmac.h crypto_hmac.cc
+if HAVE_BOTAN1
+libkea_cryptolink_la_SOURCES += botan1_link.cc
+libkea_cryptolink_la_SOURCES += botan_common.h
+libkea_cryptolink_la_SOURCES += botan1_hash.cc
+libkea_cryptolink_la_SOURCES += botan1_hmac.cc
+endif
if HAVE_BOTAN
libkea_cryptolink_la_SOURCES += botan_link.cc
libkea_cryptolink_la_SOURCES += botan_common.h
crypto_hmac.h \
cryptolink.h
+if HAVE_BOTAN1
+libkea_cryptolink_include_HEADERS += \
+ botan_common.h
+endif
+
if HAVE_BOTAN
libkea_cryptolink_include_HEADERS += \
botan_common.h
--- /dev/null
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cryptolink.h>
+#include <cryptolink/crypto_hash.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <botan/version.h>
+#include <botan/botan.h>
+#include <botan/hash.h>
+#include <botan/types.h>
+
+#include <cryptolink/botan_common.h>
+
+namespace isc {
+namespace cryptolink {
+
+/// @brief Decode the HashAlgorithm enum into a name usable by Botan
+///
+/// @param algorithm algorithm to be converted
+/// @return text representation of the algorithm name
+const std::string
+btn::getHashAlgorithmName(HashAlgorithm algorithm) {
+ switch (algorithm) {
+ case isc::cryptolink::MD5:
+ return ("MD5");
+ case isc::cryptolink::SHA1:
+ return ("SHA-1");
+ case isc::cryptolink::SHA256:
+ return ("SHA-256");
+ case isc::cryptolink::SHA224:
+ return ("SHA-224");
+ case isc::cryptolink::SHA384:
+ return ("SHA-384");
+ case isc::cryptolink::SHA512:
+ return ("SHA-512");
+ case isc::cryptolink::UNKNOWN_HASH:
+ return ("Unknown");
+ }
+ // compiler should have prevented us to reach this, since we have
+ // no default. But we need a return value anyway
+ return ("Unknown");
+}
+
+/// @brief Botan implementation of Hash. Each method is the counterpart
+/// of the Hash corresponding method.
+class HashImpl {
+public:
+
+ /// @brief Constructor for specific hash algorithm
+ ///
+ /// @param hash_algorithm The hash algorithm
+ explicit HashImpl(const HashAlgorithm hash_algorithm)
+ : hash_algorithm_(hash_algorithm), hash_() {
+ Botan::HashFunction* hash;
+ try {
+ const std::string& name =
+ btn::getHashAlgorithmName(hash_algorithm);
+ hash = Botan::get_hash(name);
+ } catch (const Botan::Algorithm_Not_Found&) {
+ isc_throw(isc::cryptolink::UnsupportedAlgorithm,
+ "Unknown hash algorithm: " <<
+ static_cast<int>(hash_algorithm));
+ } catch (const Botan::Exception& exc) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << exc.what());
+ }
+
+ hash_.reset(hash);
+ }
+
+ /// @brief Destructor
+ ~HashImpl() { }
+
+ /// @brief Returns the HashAlgorithm of the object
+ HashAlgorithm getHashAlgorithm() const {
+ return (hash_algorithm_);
+ }
+
+ /// @brief Returns the output size of the digest
+ ///
+ /// @return output size of the digest
+ size_t getOutputLength() const {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
+ return (hash_->output_length());
+#else
+#error "Unsupported Botan version (need 1.9 or higher)"
+ // added to suppress irrelevant compiler errors
+ return 0;
+#endif
+ }
+
+ /// @brief Adds data to the digest
+ ///
+ /// See @ref isc::cryptolink::Hash::update() for details.
+ void update(const void* data, const size_t len) {
+ try {
+ hash_->update(static_cast<const Botan::byte*>(data), len);
+ } catch (const Botan::Exception& exc) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Calculate the final digest
+ ///
+ /// See @ref isc::cryptolink::Hash::final() for details.
+ void final(isc::util::OutputBuffer& result, size_t len) {
+ try {
+ Botan::SecureVector<Botan::byte> b_result(hash_->final());
+
+ if (len > b_result.size()) {
+ len = b_result.size();
+ }
+ result.writeData(&b_result[0], len);
+ } catch (const Botan::Exception& exc) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Calculate the final digest
+ ///
+ /// See @ref isc::cryptolink::Hash::final() for details.
+ void final(void* result, size_t len) {
+ try {
+ Botan::SecureVector<Botan::byte> b_result(hash_->final());
+ size_t output_size = getOutputLength();
+ if (output_size > len) {
+ output_size = len;
+ }
+ std::memcpy(result, &b_result[0], output_size);
+ } catch (const Botan::Exception& exc) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Calculate the final digest
+ ///
+ /// See @ref isc::cryptolink::Hash::final() for details.
+ std::vector<uint8_t> final(size_t len) {
+ try {
+ Botan::SecureVector<Botan::byte> b_result(hash_->final());
+ if (len > b_result.size()) {
+ len = b_result.size();
+ }
+ return (std::vector<uint8_t>(&b_result[0], &b_result[len]));
+ } catch (const Botan::Exception& exc) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << exc.what());
+ }
+ }
+
+private:
+ /// @brief The hash algorithm
+ HashAlgorithm hash_algorithm_;
+
+ /// @brief The protected pointer to the Botan HashFunction object
+ boost::scoped_ptr<Botan::HashFunction> hash_;
+};
+
+Hash::Hash(const HashAlgorithm hash_algorithm)
+{
+ impl_ = new HashImpl(hash_algorithm);
+}
+
+Hash::~Hash() {
+ delete impl_;
+}
+
+HashAlgorithm
+Hash::getHashAlgorithm() const {
+ return (impl_->getHashAlgorithm());
+}
+
+size_t
+Hash::getOutputLength() const {
+ return (impl_->getOutputLength());
+}
+
+void
+Hash::update(const void* data, const size_t len) {
+ impl_->update(data, len);
+}
+
+void
+Hash::final(isc::util::OutputBuffer& result, size_t len) {
+ impl_->final(result, len);
+}
+
+void
+Hash::final(void* result, size_t len) {
+ impl_->final(result, len);
+}
+
+std::vector<uint8_t>
+Hash::final(size_t len) {
+ return impl_->final(len);
+}
+
+} // namespace cryptolink
+} // namespace isc
--- /dev/null
+// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cryptolink.h>
+#include <cryptolink/crypto_hmac.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <botan/version.h>
+#include <botan/botan.h>
+#include <botan/hmac.h>
+#include <botan/hash.h>
+#include <botan/types.h>
+
+#include <cryptolink/botan_common.h>
+
+namespace isc {
+namespace cryptolink {
+
+/// @brief Botan implementation of HMAC. Each method is the counterpart
+/// of the HMAC corresponding method.
+class HMACImpl {
+public:
+ /// @brief Constructor from a secret and a hash algorithm
+ ///
+ /// See constructor of the @ref isc::cryptolink::HMAC class for details.
+ ///
+ /// @param secret The secret to sign with
+ /// @param secret_len The length of the secret
+ /// @param hash_algorithm The hash algorithm
+ explicit HMACImpl(const void* secret, size_t secret_len,
+ const HashAlgorithm hash_algorithm)
+ : hash_algorithm_(hash_algorithm), hmac_() {
+ Botan::HashFunction* hash;
+ try {
+ const std::string& name =
+ btn::getHashAlgorithmName(hash_algorithm);
+ hash = Botan::get_hash(name);
+ } catch (const Botan::Algorithm_Not_Found&) {
+ isc_throw(UnsupportedAlgorithm,
+ "Unknown hash algorithm: " <<
+ static_cast<int>(hash_algorithm));
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+
+ hmac_.reset(new Botan::HMAC(hash));
+
+ // If the key length is larger than the block size, we hash the
+ // key itself first.
+ try {
+ // use a temp var so we don't have blocks spanning
+ // preprocessor directives
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
+ size_t block_length = hash->hash_block_size();
+#else
+#error "Unsupported Botan version (need 1.9 or higher)"
+ // added to suppress irrelevant compiler errors
+ size_t block_length = 0;
+#endif
+ if (secret_len > block_length) {
+ Botan::SecureVector<Botan::byte> hashed_key =
+ hash->process(static_cast<const Botan::byte*>(secret),
+ secret_len);
+ hmac_->set_key(&hashed_key[0], hashed_key.size());
+ } else {
+ // Botan 1.8 considers len 0 a bad key. 1.9 does not,
+ // but we won't accept it anyway, and fail early
+ if (secret_len == 0) {
+ isc_throw(BadKey, "Bad HMAC secret length: 0");
+ }
+ hmac_->set_key(static_cast<const Botan::byte*>(secret),
+ secret_len);
+ }
+ } catch (const Botan::Invalid_Key_Length& ikl) {
+ isc_throw(BadKey, ikl.what());
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Destructor
+ ~HMACImpl() {
+ }
+
+ /// @brief Returns the HashAlgorithm of the object
+ HashAlgorithm getHashAlgorithm() const {
+ return (hash_algorithm_);
+ }
+
+ /// @brief Returns the output size of the digest
+ ///
+ /// @return output size of the digest
+ size_t getOutputLength() const {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
+ return (hmac_->output_length());
+#else
+#error "Unsupported Botan version (need 1.9 or higher)"
+ // added to suppress irrelevant compiler errors
+ return 0;
+#endif
+ }
+
+ /// @brief Add data to digest
+ ///
+ /// See @ref isc::cryptolink::HMAC::update() for details.
+ void update(const void* data, const size_t len) {
+ try {
+ hmac_->update(static_cast<const Botan::byte*>(data), len);
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Calculate the final signature
+ ///
+ /// See @ref isc::cryptolink::HMAC::sign() for details.
+ void sign(isc::util::OutputBuffer& result, size_t len) {
+ try {
+ Botan::SecureVector<Botan::byte> b_result(hmac_->final());
+
+ if (len > b_result.size()) {
+ len = b_result.size();
+ }
+ result.writeData(&b_result[0], len);
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Calculate the final signature
+ ///
+ /// See @ref isc::cryptolink::HMAC::sign() for details.
+ void sign(void* result, size_t len) {
+ try {
+ Botan::SecureVector<Botan::byte> b_result(hmac_->final());
+ size_t output_size = getOutputLength();
+ if (output_size > len) {
+ output_size = len;
+ }
+ std::memcpy(result, &b_result[0], output_size);
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+ }
+
+ /// @brief Calculate the final signature
+ ///
+ /// See @ref isc::cryptolink::HMAC::sign() for details.
+ std::vector<uint8_t> sign(size_t len) {
+ try {
+ Botan::SecureVector<Botan::byte> b_result(hmac_->final());
+ if (len > b_result.size()) {
+ len = b_result.size();
+ }
+ return (std::vector<uint8_t>(&b_result[0], &b_result[len]));
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+ }
+
+
+ /// @brief Verify an existing signature
+ ///
+ /// See @ref isc::cryptolink::HMAC::verify() for details.
+ bool verify(const void* sig, size_t len) {
+ // Botan's verify_mac checks if len matches the output_length,
+ // which causes it to fail for truncated signatures, so we do
+ // the check ourselves
+ try {
+ size_t size = getOutputLength();
+ if (len < 10 || len < size / 2) {
+ return (false);
+ }
+ if (len > size) {
+ len = size;
+ }
+ if (digest_.size() == 0) {
+ digest_ = hmac_->final();
+ }
+ return (Botan::same_mem(&digest_[0],
+ static_cast<const unsigned char*>(sig),
+ len));
+ } catch (const Botan::Exception& exc) {
+ isc_throw(LibraryError, "Botan error: " << exc.what());
+ }
+ }
+
+private:
+ /// @brief The hash algorithm
+ HashAlgorithm hash_algorithm_;
+
+ /// @brief The protected pointer to the Botan HMAC object
+ boost::scoped_ptr<Botan::HMAC> hmac_;
+
+ /// @brief The digest cache for multiple verify
+ Botan::SecureVector<Botan::byte> digest_;
+};
+
+HMAC::HMAC(const void* secret, size_t secret_length,
+ const HashAlgorithm hash_algorithm)
+{
+ impl_ = new HMACImpl(secret, secret_length, hash_algorithm);
+}
+
+HMAC::~HMAC() {
+ delete impl_;
+}
+
+HashAlgorithm
+HMAC::getHashAlgorithm() const {
+ return (impl_->getHashAlgorithm());
+}
+
+size_t
+HMAC::getOutputLength() const {
+ return (impl_->getOutputLength());
+}
+
+void
+HMAC::update(const void* data, const size_t len) {
+ impl_->update(data, len);
+}
+
+void
+HMAC::sign(isc::util::OutputBuffer& result, size_t len) {
+ impl_->sign(result, len);
+}
+
+void
+HMAC::sign(void* result, size_t len) {
+ impl_->sign(result, len);
+}
+
+std::vector<uint8_t>
+HMAC::sign(size_t len) {
+ return impl_->sign(len);
+}
+
+bool
+HMAC::verify(const void* sig, const size_t len) {
+ return (impl_->verify(sig, len));
+}
+
+} // namespace cryptolink
+} // namespace isc
--- /dev/null
+// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cryptolink/cryptolink.h>
+#include <cryptolink/crypto_hash.h>
+#include <cryptolink/crypto_hmac.h>
+
+#include <botan/botan.h>
+#include <botan/init.h>
+
+namespace isc {
+namespace cryptolink {
+
+// For Botan, we use the CryptoLink class object in RAII style
+class CryptoLinkImpl {
+private:
+ Botan::LibraryInitializer botan_init_;
+};
+
+CryptoLink::~CryptoLink() {
+ delete impl_;
+}
+
+void
+CryptoLink::initialize() {
+ CryptoLink& c = getCryptoLinkInternal();
+ if (c.impl_ == NULL) {
+ try {
+ c.impl_ = new CryptoLinkImpl();
+ } catch (const Botan::Exception& ex) {
+ isc_throw(InitializationError, "Botan error: " << ex.what());
+ }
+ }
+}
+
+std::string
+CryptoLink::getVersion() {
+ return (Botan::version_string());
+}
+
+} // namespace cryptolink
+} // namespace isc
+
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <boost/scoped_ptr.hpp>
-#include <botan/version.h>
-#include <botan/botan.h>
-#include <botan/hash.h>
-#include <botan/types.h>
+#include <botan/lookup.h>
#include <cryptolink/botan_common.h>
-#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,0)
-#define secure_vector SecureVector
-#endif
-
namespace isc {
namespace cryptolink {
try {
const std::string& name =
btn::getHashAlgorithmName(hash_algorithm);
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
hash = Botan::HashFunction::create(name).release();
-#else
- hash = Botan::get_hash(name);
-#endif
} catch (const Botan::Algorithm_Not_Found&) {
isc_throw(isc::cryptolink::UnsupportedAlgorithm,
"Unknown hash algorithm: " <<
///
/// @return output size of the digest
size_t getOutputLength() const {
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
return (hash_->output_length());
-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,8,0)
- return (hash_->OUTPUT_LENGTH);
-#else
-#error "Unsupported Botan version (need 1.8 or higher)"
- // added to suppress irrelevant compiler errors
- return 0;
-#endif
}
/// @brief Adds data to the digest
-// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <boost/scoped_ptr.hpp>
-#include <botan/version.h>
-#include <botan/botan.h>
#include <botan/hmac.h>
-#include <botan/hash.h>
-#include <botan/types.h>
+#include <botan/lookup.h>
#include <cryptolink/botan_common.h>
-#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,0)
-#define secure_vector SecureVector
-#endif
-
namespace isc {
namespace cryptolink {
try {
const std::string& name =
btn::getHashAlgorithmName(hash_algorithm);
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
std::unique_ptr<Botan::HashFunction> hash_ptr =
Botan::HashFunction::create(name);
if (hash_ptr) {
} else {
throw Botan::Algorithm_Not_Found(name);
}
-#else
- hash = Botan::get_hash(name);
-#endif
} catch (const Botan::Algorithm_Not_Found&) {
isc_throw(UnsupportedAlgorithm,
"Unknown hash algorithm: " <<
try {
// use a temp var so we don't have blocks spanning
// preprocessor directives
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
size_t block_length = hash->hash_block_size();
-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,8,0)
- size_t block_length = hash->HASH_BLOCK_SIZE;
-#else
-#error "Unsupported Botan version (need 1.8 or higher)"
- // added to suppress irrelevant compiler errors
- size_t block_length = 0;
-#endif
if (secret_len > block_length) {
Botan::secure_vector<Botan::byte> hashed_key =
hash->process(static_cast<const Botan::byte*>(secret),
///
/// @return output size of the digest
size_t getOutputLength() const {
-#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,9,0)
return (hmac_->output_length());
-#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,8,0)
- return (hmac_->OUTPUT_LENGTH);
-#else
-#error "Unsupported Botan version (need 1.8 or higher)"
- // added to suppress irrelevant compiler errors
- return 0;
-#endif
}
/// @brief Add data to digest
-// Copyright (C) 2011-2015,2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <cryptolink/crypto_hash.h>
#include <cryptolink/crypto_hmac.h>
-#define BOTAN_NO_DEPRECATED_WARNINGS
-
-#include <botan/botan.h>
-#include <botan/init.h>
+#include <botan/exceptn.h>
+#include <botan/version.h>
namespace isc {
namespace cryptolink {
// For Botan, we use the CryptoLink class object in RAII style
class CryptoLinkImpl {
-private:
- Botan::LibraryInitializer botan_init_;
+ // empty class
};
CryptoLink::~CryptoLink() {