Browse Source

[master] Finished merge of trac3908 (port cryptolink fixes)

Francis Dupont 8 years ago
parent
commit
4c14fdfd41

+ 6 - 1
ChangeLog

@@ -1,6 +1,11 @@
+1189.	[func]		fdupont
+	Owing to API changes, crypto code now requires OpenSSL 1.0.1 or
+	later.
+	(Trac #3908, git ....)
+
 1188.	[doc]		vlegout
 	Fixed several spelling mistakes.
-	(Github #32, d51c005519c4add6fd0c37bcd68b0fbe94941b2d)
+	(Github #32, git d51c005519c4add6fd0c37bcd68b0fbe94941b2d)
 
 1187.	[bug]		marcin
 	DHCPv4 server allows for allocating multiple leases for the

+ 16 - 10
configure.ac

@@ -825,7 +825,7 @@ then
 else
    CRYPTO_NAME="OpenSSL"
    DISABLED_CRYPTO="Botan"
-   CRYPTO_PACKAGE="openssl-1.0.0"
+   CRYPTO_PACKAGE="openssl-1.0.1"
    AC_DEFINE_UNQUOTED([WITH_OPENSSL], [], [Compile with OpenSSL crypto])
    AC_MSG_CHECKING(for OpenSSL library)
    # from bind9
@@ -848,18 +848,10 @@ else
    fi
    AC_MSG_RESULT(yes)
    if test "${use_openssl}" = "/usr" ; then
+      CRYPTO_CFLAGS=""
       CRYPTO_INCLUDES=""
       CRYPTO_LIBS="-lcrypto"
       DISTCHECK_CRYPTO_CONFIGURE_FLAG="--with-openssl"
-      case "$host" in
-          *-apple-darwin*)
-              # Starting with OSX 10.7 (Lion) OpenSSL is deprecated
-              CRYPTO_CFLAGS="-Wno-deprecated-declarations"
-              ;;
-          *)
-              CRYPTO_CFLAGS=""
-              ;;
-      esac
    else
       CRYPTO_CFLAGS=""
       CRYPTO_INCLUDES="-I${use_openssl}/include"
@@ -884,6 +876,8 @@ else
       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>
@@ -914,6 +908,18 @@ EOF
                           ])],
         [AC_MSG_RESULT([yes])],
         [AC_MSG_ERROR([missing EVP entry for SHA-2])])
+    dnl Check HMAC API
+    AC_MSG_CHECKING([HMAC functions returning ints])
+    AC_LINK_IFELSE(
+         [AC_LANG_PROGRAM([#include <openssl/hmac.h>],
+                          [HMAC_CTX ctx, tmp;
+                           int n = HMAC_Init(&ctx, NULL, 0, NULL);
+                           n += HMAC_Update(&ctx, NULL, 0);
+                           n += HMAC_CTX_copy(&tmp, &ctx);
+                           n += HMAC_Final(&tmp, NULL, NULL);
+                           ])],
+         [AC_MSG_RESULT([yes])],
+         [AC_MSG_ERROR([HMAC functions return void: the OpenSSL version should be too old, please change for >= 1.0.1])])
     LIBS=${LIBS_SAVED}
     CPPFLAGS=${CPPFLAGS_SAVED}
 fi

+ 3 - 2
doc/guide/install.xml

@@ -120,9 +120,10 @@
         </para>
         </listitem>
 
-            <listitem>
+          <listitem>
         <para>
-          Botan (version 1.8, 1.9 or 1.10) or OpenSSL (versions 1.0.*).</para>
+          Botan (at least version 1.8) or OpenSSL (at least version 1.0.1).
+        </para>
           </listitem>
 
           <listitem>

+ 6 - 7
doc/guide/intro.xml

@@ -55,13 +55,12 @@
 
         <listitem>
             <simpara>
-        Kea supports two cryptographic libraries: Botan and OpenSSL. Only one of
-        them is required to be installed during compilation. If using Botan, Kea
-        requires the Botan cryptographic library for C++ (<ulink
-        url="http://botan.randombit.net/"/>), version 1.8, 1.9 or 1.10. If
-        OpenSSL is used, (<ulink url="http://www.openssl.org/"/>), then Kea
-        requires the OpenSSL C++ library version 1.0.*. Support for later
-        versions of Botan and OpenSSL will be added in future releases of Kea.
+        Kea supports two crypto libraries: Botan and OpenSSL. Only one of them
+        is required to be installed during compilation. Kea uses the Botan
+        crypto library for C++ (<ulink url="http://botan.randombit.net/"/>),
+        version 1.8 or later. As an alternative to Botan, Kea can use the
+        OpenSSL crypto library (<ulink url="http://www.openssl.org/"/>),
+        version 1.0.1 or later.
             </simpara>
         </listitem>
 

+ 17 - 3
src/lib/cryptolink/botan_hash.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -56,7 +56,8 @@ public:
     /// @brief Constructor for specific hash algorithm
     ///
     /// @param hash_algorithm The hash algorithm
-    explicit HashImpl(const HashAlgorithm hash_algorithm) {
+    explicit HashImpl(const HashAlgorithm hash_algorithm)
+    : hash_algorithm_(hash_algorithm), hash_() {
         Botan::HashFunction* hash;
         try {
             hash = Botan::get_hash(btn::getHashAlgorithmName(hash_algorithm));
@@ -74,6 +75,11 @@ public:
     /// @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
@@ -149,7 +155,10 @@ public:
     }
 
 private:
-    /// \brief The protected pointer to the Botan HashFunction object
+    /// @brief The hash algorithm
+    HashAlgorithm hash_algorithm_;
+
+    /// @brief The protected pointer to the Botan HashFunction object
     boost::scoped_ptr<Botan::HashFunction> hash_;
 };
 
@@ -162,6 +171,11 @@ Hash::~Hash() {
     delete impl_;
 }
 
+HashAlgorithm
+Hash::getHashAlgorithm() const {
+    return (impl_->getHashAlgorithm());
+}
+
 size_t
 Hash::getOutputLength() const {
     return (impl_->getOutputLength());

+ 35 - 16
src/lib/cryptolink/botan_hmac.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 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
@@ -34,16 +34,17 @@ public:
     /// @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) {
+                      const HashAlgorithm hash_algorithm)
+    : hash_algorithm_(hash_algorithm), hmac_() {
         Botan::HashFunction* hash;
         try {
             hash = Botan::get_hash(btn::getHashAlgorithmName(hash_algorithm));
         } catch (const Botan::Algorithm_Not_Found&) {
-            isc_throw(isc::cryptolink::UnsupportedAlgorithm,
+            isc_throw(UnsupportedAlgorithm,
                       "Unknown hash algorithm: " <<
                       static_cast<int>(hash_algorithm));
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
 
         hmac_.reset(new Botan::HMAC(hash));
@@ -79,7 +80,7 @@ public:
         } catch (const Botan::Invalid_Key_Length& ikl) {
             isc_throw(BadKey, ikl.what());
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -87,6 +88,11 @@ public:
     ~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
@@ -109,7 +115,7 @@ public:
         try {
             hmac_->update(static_cast<const Botan::byte*>(data), len);
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -125,7 +131,7 @@ public:
             }
             result.writeData(b_result.begin(), len);
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -141,7 +147,7 @@ public:
             }
             std::memcpy(result, b_result.begin(), output_size);
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -157,7 +163,7 @@ public:
                 return (std::vector<uint8_t>(b_result.begin(), &b_result[len]));
             }
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
@@ -166,11 +172,10 @@ public:
     ///
     /// See @ref isc::cryptolink::HMAC::verify() for details.
     bool verify(const void* sig, size_t len) {
-        /// @todo 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
+        // 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 {
-            Botan::SecureVector<Botan::byte> our_mac = hmac_->final();
             size_t size = getOutputLength();
             if (len < 10 || len < size / 2) {
                 return (false);
@@ -178,17 +183,26 @@ public:
             if (len > size) {
                 len = size;
             }
-            return (Botan::same_mem(&our_mac[0],
+            if (digest_.empty()) {
+                digest_ = hmac_->final();
+            }
+            return (Botan::same_mem(&digest_[0],
                                     static_cast<const unsigned char*>(sig),
                                     len));
         } catch (const Botan::Exception& exc) {
-            isc_throw(isc::cryptolink::LibraryError, exc.what());
+            isc_throw(LibraryError, exc.what());
         }
     }
 
 private:
-    /// \brief The protected pointer to the Botan HMAC object
+    /// @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,
@@ -201,6 +215,11 @@ HMAC::~HMAC() {
     delete impl_;
 }
 
+HashAlgorithm
+HMAC::getHashAlgorithm() const {
+    return (impl_->getHashAlgorithm());
+}
+
 size_t
 HMAC::getOutputLength() const {
     return (impl_->getOutputLength());

+ 6 - 1
src/lib/cryptolink/crypto_hash.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -42,6 +42,11 @@ public:
     /// \brief Destructor
     ~Hash();
 
+    /// \brief Returns the HashAlgorithm of the object
+    ///
+    /// \return hash algorithm
+    HashAlgorithm getHashAlgorithm() const;
+
     /// \brief Returns the output size of the digest
     ///
     /// \return output size of the digest

+ 10 - 3
src/lib/cryptolink/crypto_hmac.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 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
@@ -52,6 +52,11 @@ public:
     /// \brief Destructor
     ~HMAC();
 
+    /// \brief Returns the HashAlgorithm of the object
+    ///
+    /// \return hash algorithm
+    HashAlgorithm getHashAlgorithm() const;
+
     /// \brief Returns the output size of the digest
     ///
     /// \return output size of the digest
@@ -93,7 +98,7 @@ public:
     /// result
     void sign(void* result, size_t len);
 
-    /// \brief Calculate the final signatre
+    /// \brief Calculate the final signature
     ///
     /// The result will be returned as a std::vector<uint8_t>
     ///
@@ -115,7 +120,9 @@ public:
     /// \param sig The signature to verify
     /// \param len The length of the signature. If this is smaller
     ///            than the output length of the algorithm,
-    ///            only len bytes will be checked
+    ///            only len bytes will be checked. If this is
+    ///            larger than the output length of the algorithm,
+    ///            only output size bytes will be checked
     /// \return true if the signature is correct, false otherwise
     ///
     /// \note verify() does not destroy its context so it can be

+ 10 - 11
src/lib/cryptolink/openssl_common.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -26,19 +26,13 @@ public:
 
     typedef typename std::vector<T>::const_iterator const_iterator;
 
-    explicit SecBuf() : vec_(std::vector<T>()) {}
+    explicit SecBuf() : vec_() {}
 
-    explicit SecBuf(size_t n, const T& value = T()) :
-        vec_(std::vector<T>(n, value))
-    {}
+    explicit SecBuf(size_t n, const T& value = T()) : vec_(n, value) {}
 
-    SecBuf(iterator first, iterator last) :
-        vec_(std::vector<T>(first, last))
-    {}
+    SecBuf(iterator first, iterator last) : vec_(first, last) {}
 
-    SecBuf(const_iterator first, const_iterator last) :
-        vec_(std::vector<T>(first, last))
-    {}
+    SecBuf(const_iterator first, const_iterator last) : vec_(first, last) {}
 
     SecBuf(const std::vector<T>& x) : vec_(x) {}
 
@@ -70,6 +64,11 @@ public:
         vec_.resize(sz);
     };
 
+    void clear() {
+        std::memset(&vec_[0], 0, vec_.capacity() * sizeof(T));
+        vec_.clear();
+    }
+
     SecBuf& operator=(const SecBuf& x) {
         if (&x != *this) {
             vec_ = x.vec_;

+ 16 - 2
src/lib/cryptolink/openssl_hash.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -54,7 +54,8 @@ public:
     /// @brief Constructor for specific hash algorithm
     ///
     /// @param hash_algorithm The hash algorithm
-    explicit HashImpl(const HashAlgorithm hash_algorithm) {
+    explicit HashImpl(const HashAlgorithm hash_algorithm)
+    : hash_algorithm_(hash_algorithm), md_() {
         const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
         if (algo == 0) {
             isc_throw(isc::cryptolink::UnsupportedAlgorithm,
@@ -76,6 +77,11 @@ public:
         }
     }
 
+    /// @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
@@ -130,6 +136,9 @@ public:
     }
 
 private:
+    /// @brief The hash algorithm
+    HashAlgorithm hash_algorithm_;
+
     /// @brief The protected pointer to the OpenSSL EVP_MD_CTX structure
     boost::scoped_ptr<EVP_MD_CTX> md_;
 };
@@ -143,6 +152,11 @@ Hash::~Hash() {
     delete impl_;
 }
 
+HashAlgorithm
+Hash::getHashAlgorithm() const {
+    return (impl_->getHashAlgorithm());
+}
+
 size_t
 Hash::getOutputLength() const {
     return (impl_->getOutputLength());

+ 47 - 11
src/lib/cryptolink/openssl_hmac.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -30,7 +30,8 @@ public:
     /// @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) {
+                      const HashAlgorithm hash_algorithm)
+    : hash_algorithm_(hash_algorithm), md_() {
         const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
         if (algo == 0) {
             isc_throw(UnsupportedAlgorithm,
@@ -44,9 +45,11 @@ public:
         md_.reset(new HMAC_CTX);
         HMAC_CTX_init(md_.get());
 
-        HMAC_Init_ex(md_.get(), secret,
-                     static_cast<int>(secret_len),
-                     algo, NULL);
+        if (!HMAC_Init_ex(md_.get(), secret,
+                          static_cast<int>(secret_len),
+                          algo, NULL)) {
+            isc_throw(LibraryError, "HMAC_Init_ex");
+        }
     }
 
     /// @brief Destructor
@@ -56,13 +59,18 @@ public:
         }
     }
 
+    /// @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 {
         int size = HMAC_size(md_.get());
         if (size < 0) {
-            isc_throw(isc::cryptolink::LibraryError, "EVP_MD_CTX_size");
+            isc_throw(LibraryError, "HMAC_size");
         }
         return (static_cast<size_t>(size));
     }
@@ -71,7 +79,11 @@ public:
     ///
     /// See @ref isc::cryptolink::HMAC::update() for details.
     void update(const void* data, const size_t len) {
-        HMAC_Update(md_.get(), static_cast<const unsigned char*>(data), len);
+        if (!HMAC_Update(md_.get(),
+                         static_cast<const unsigned char*>(data),
+                         len)) {
+            isc_throw(LibraryError, "HMAC_Update");
+        }
     }
 
     /// @brief Calculate the final signature
@@ -80,7 +92,9 @@ public:
     void sign(isc::util::OutputBuffer& result, size_t len) {
         size_t size = getOutputLength();
         ossl::SecBuf<unsigned char> digest(size);
-        HMAC_Final(md_.get(), &digest[0], NULL);
+        if (!HMAC_Final(md_.get(), &digest[0], NULL)) {
+            isc_throw(LibraryError, "HMAC_Final");
+        }
         if (len > size) {
             len = size;
         }
@@ -93,7 +107,9 @@ public:
     void sign(void* result, size_t len) {
         size_t size = getOutputLength();
         ossl::SecBuf<unsigned char> digest(size);
-        HMAC_Final(md_.get(), &digest[0], NULL);
+        if (!HMAC_Final(md_.get(), &digest[0], NULL)) {
+            isc_throw(LibraryError, "HMAC_Final");
+        }
         if (len > size) {
             len = size;
         }
@@ -106,7 +122,9 @@ public:
     std::vector<uint8_t> sign(size_t len) {
         size_t size = getOutputLength();
         ossl::SecBuf<unsigned char> digest(size);
-        HMAC_Final(md_.get(), &digest[0], NULL);
+        if (!HMAC_Final(md_.get(), &digest[0], NULL)) {
+            isc_throw(LibraryError, "HMAC_Final");
+        }
         if (len < size) {
             digest.resize(len);
         }
@@ -117,12 +135,23 @@ public:
     ///
     /// See @ref isc::cryptolink::HMAC::verify() for details.
     bool verify(const void* sig, size_t len) {
+        // Check the length
         size_t size = getOutputLength();
         if (len < 10 || len < size / 2) {
             return (false);
         }
+        // Get the digest from a copy of the context
+        HMAC_CTX tmp;
+        HMAC_CTX_init(&tmp);
+        if (!HMAC_CTX_copy(&tmp, md_.get())) {
+            isc_throw(LibraryError, "HMAC_CTX_copy");
+        }
         ossl::SecBuf<unsigned char> digest(size);
-        HMAC_Final(md_.get(), &digest[0], NULL);
+        if (!HMAC_Final(&tmp, &digest[0], NULL)) {
+            HMAC_CTX_cleanup(&tmp);
+            isc_throw(LibraryError, "HMAC_Final");
+        }
+        HMAC_CTX_cleanup(&tmp);
         if (len > size) {
             len = size;
         }
@@ -130,6 +159,8 @@ public:
     }
 
 private:
+    /// @brief The hash algorithm
+    HashAlgorithm hash_algorithm_;
 
     /// @brief The protected pointer to the OpenSSL HMAC_CTX structure
     boost::scoped_ptr<HMAC_CTX> md_;
@@ -145,6 +176,11 @@ HMAC::~HMAC() {
     delete impl_;
 }
 
+HashAlgorithm
+HMAC::getHashAlgorithm() const {
+    return (impl_->getHashAlgorithm());
+}
+
 size_t
 HMAC::getOutputLength() const {
     return (impl_->getOutputLength());

+ 1 - 0
src/lib/cryptolink/tests/Makefile.am

@@ -23,6 +23,7 @@ run_unittests_SOURCES += hmac_unittests.cc
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS =  $(AM_LDFLAGS) $(CRYPTO_LDFLAGS) $(GTEST_LDFLAGS)
 run_unittests_LDADD  = $(top_builddir)/src/lib/cryptolink/libkea-cryptolink.la
+run_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
 run_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
 run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la

+ 23 - 1
src/lib/cryptolink/tests/hash_unittests.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2016 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
@@ -519,6 +519,28 @@ TEST(HashTest, SHA512_RFC6234) {
 }
 
 namespace {
+    /// @brief Get the hash algorithm
+    /// @param alg Hash algorithm enum
+    /// @return Hash algorithm enum
+    HashAlgorithm
+    digestHashAlgorithm(HashAlgorithm alg) {
+        boost::shared_ptr<Hash> hash_digest(
+            CryptoLink::getCryptoLink().createHash(alg),
+            deleteHash);
+        return (hash_digest->getHashAlgorithm());
+    }
+}
+
+TEST(HashTest, HashAlgorithm) {
+    EXPECT_EQ(MD5, digestHashAlgorithm(MD5));
+    EXPECT_EQ(SHA1, digestHashAlgorithm(SHA1));
+    EXPECT_EQ(SHA256, digestHashAlgorithm(SHA256));
+    EXPECT_EQ(SHA224, digestHashAlgorithm(SHA224));
+    EXPECT_EQ(SHA384, digestHashAlgorithm(SHA384));
+    EXPECT_EQ(SHA512, digestHashAlgorithm(SHA512));
+}
+
+namespace {
     /// @brief Compute the vector digest length
     /// @param alg Hash algorithm enum
     /// @param len Wanted length

+ 32 - 1
src/lib/cryptolink/tests/hmac_unittests.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 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
@@ -136,6 +136,12 @@ namespace {
         hmac_sig.writeUint8At(~hmac_sig[0], 0);
         EXPECT_FALSE(hmac_verify->verify(hmac_sig.getData(),
                                          hmac_sig.getLength()));
+
+        // Restore the sig by flipping the first octet, and check
+        // whether verification succeeds then
+        hmac_sig.writeUint8At(~hmac_sig[0], 0);
+        EXPECT_TRUE(hmac_verify->verify(hmac_sig.getData(),
+                                        hmac_sig.getLength()));
     }
 
     /// @brief Sign and verify with vector representation of signature
@@ -200,6 +206,9 @@ namespace {
         sig[0] = ~sig[0];
         EXPECT_FALSE(hmac_verify->verify(sig, hmac_len));
 
+        sig[0] = ~sig[0];
+        EXPECT_TRUE(hmac_verify->verify(sig, hmac_len));
+
         delete[] sig;
     }
 
@@ -596,6 +605,28 @@ TEST(HMACTest, HMAC_SHA256_RFC2202_SIGN_TRUNCATED) {
 }
 
 namespace {
+    /// @brief Get the hash algorithm
+    /// @param alg Hash algorithm enum
+    /// @return Hash algorithm enum
+    HashAlgorithm
+    signHashAlgorithm(HashAlgorithm alg) {
+        boost::shared_ptr<HMAC> hmac_sign(
+            CryptoLink::getCryptoLink().createHMAC("asdf", 4, alg),
+            deleteHMAC);
+        return (hmac_sign->getHashAlgorithm());
+    }
+}
+
+TEST(HMACTest, HashAlgorithm) {
+    EXPECT_EQ(MD5, signHashAlgorithm(MD5));
+    EXPECT_EQ(SHA1, signHashAlgorithm(SHA1));
+    EXPECT_EQ(SHA256, signHashAlgorithm(SHA256));
+    EXPECT_EQ(SHA224, signHashAlgorithm(SHA224));
+    EXPECT_EQ(SHA384, signHashAlgorithm(SHA384));
+    EXPECT_EQ(SHA512, signHashAlgorithm(SHA512));
+}
+
+namespace {
     /// @brief Compute the vector signature length
     /// @param alg Hash algorithm enum
     /// @param len Wanted length

+ 5 - 3
src/lib/cryptolink/tests/run_unittests.cc

@@ -1,15 +1,17 @@
-// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2016 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 <gtest/gtest.h>
+#include <log/logger_support.h>
 #include <util/unittests/run_all.h>
 
+#include <gtest/gtest.h>
+
 int
 main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);
-
+    isc::log::initLogger();
     return (isc::util::unittests::run_all());
 }