#CRYPTO_LDFLAGS="-ldl"
CRYPTO_LDFLAGS=""
CRYPTO_RPATH=""
- dnl Check availability of SHA-2
AC_MSG_CHECKING([support of SHA-2])
LIBS_SAVED=${LIBS}
LIBS="$LIBS $CRYPTO_LIBS"
CPPFLAGS_SAVED=${CPPFLAGS}
CPPFLAGS="$CRYPTO_INCLUDES $CPPFLAGS"
- AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([#include <openssl/evp.h>],
- [const EVP_MD* h224 = EVP_sha224();
- const EVP_MD* h256 = EVP_sha256();
- const EVP_MD* h384 = EVP_sha384();
- const EVP_MD* h512 = EVP_sha512();
- ])],
- [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/opensslv.h>
- #include <openssl/hmac.h>],
- [#if OPENSSL_VERSION_NUMBER < 0x10100000L
- 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);
- #endif
- ])],
- [AC_MSG_RESULT([yes])],
- [AC_MSG_ERROR([HMAC functions return void: please use OpenSSL version 1.0.1 or later])])
+ 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
// 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 <openssl/opensslv.h>
-
-#if (defined(LIBRESSL_VERSION_NUMBER) && \
- (LIBRESSL_VERSION_NUMBER < 0x3050200fL)) || \
- (OPENSSL_VERSION_NUMBER < 0x10100000L)
-
// This file is included by hash and hmac codes so KEA_H* macros
// avoid to define unused inlines.
#ifdef KEA_HASH
-// EVP_MD_CTX_new() is EVP_MD_CTX_create() in OpenSSL < 1.1
+#ifndef HAVE_EVP_MD_CTX_NEW
+#ifdef HAVE_EVP_MD_CTX_CREATE
+
+// EVP_MD_CTX_new() is EVP_MD_CTX_create() in old OpenSSL
inline EVP_MD_CTX* EVP_MD_CTX_new() {
return (EVP_MD_CTX_create());
}
-// EVP_MD_CTX_free(ctx) is EVP_MD_CTX_destroy(ctx) in OpenSSL < 1.1
+#else
+#error have no EVP_MD_CTX_new() nor EVP_MD_CTX_create()
+#endif
+#endif
+
+#ifndef HAVE_EVP_MD_CTX_FREE
+#ifdef HAVE_EVP_MD_CTX_DESTROY
+
+// EVP_MD_CTX_free(ctx) is EVP_MD_CTX_destroy(ctx) in old OpenSSL
inline void EVP_MD_CTX_free(EVP_MD_CTX* ctx) {
EVP_MD_CTX_destroy(ctx);
}
+#else
+#error have no EVP_MD_CTX_free() nor EVP_MD_CTX_destroy()
+#endif
#endif
-#ifdef KEA_HMAC
+#endif
-// HMAC_CTX_new() implementation for OpenSSL < 1.1
+#ifdef KEA_HMAC
-inline HMAC_CTX* HMAC_CTX_new() {
- HMAC_CTX* ctx = static_cast<HMAC_CTX*>(OPENSSL_malloc(sizeof(HMAC_CTX)));
- if (ctx != 0) {
- HMAC_CTX_init(ctx);
- }
- return (ctx);
-}
+#ifndef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
+#ifdef HAVE_EVP_PKEY_NEW_MAC_KEY
-// HMAC_CTX_free() implementation for OpenSSL < 1.1
+// EVP_PKEY_new_raw_private_key(type, e, key, keylen) is
+// EVP_PKEY_new_mac_key(type, e, key, (int)keylen) in old OpenSSL
-inline void HMAC_CTX_free(HMAC_CTX* ctx) {
- if (ctx != 0) {
- HMAC_CTX_cleanup(ctx);
- OPENSSL_free(ctx);
- }
+inline EVP_PKEY* EVP_PKEY_new_raw_private_key(int type, ENGINE* e,
+ const unsigned char *key,
+ size_t keylen) {
+ return (EVP_PKEY_new_mac_key(type, e, key, static_cast<int>(keylen)));
}
+#else
+#error have no EVP_PKEY_new_raw_private_key() nor EVP_PKEY_new_mac_key()
+#endif
#endif
#endif
-// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2022 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 <openssl/hmac.h>
+#include <openssl/evp.h>
#include <cryptolink/openssl_common.h>
+#define KEA_HASH
#define KEA_HMAC
#include <cryptolink/openssl_compat.h>
/// @param hash_algorithm The hash algorithm
explicit HMACImpl(const void* secret, size_t secret_len,
const HashAlgorithm hash_algorithm)
- : hash_algorithm_(hash_algorithm), md_() {
+ : hash_algorithm_(hash_algorithm), md_() {
const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
if (algo == 0) {
isc_throw(UnsupportedAlgorithm,
isc_throw(BadKey, "Bad HMAC secret length: 0");
}
- md_ = HMAC_CTX_new();
+ md_ = EVP_MD_CTX_new();
if (md_ == 0) {
- isc_throw(LibraryError, "OpenSSL HMAC_CTX_new() failed");
+ isc_throw(LibraryError, "OpenSSL EVP_MD_CTX_new() failed");
}
- if (!HMAC_Init_ex(md_, secret,
- static_cast<int>(secret_len),
- algo, NULL)) {
- isc_throw(LibraryError, "OpenSSL HMAC_Init_ex() failed");
+ EVP_PKEY* pkey =
+ EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
+ reinterpret_cast<const unsigned char*>(secret),
+ secret_len);
+
+ if (pkey == 0) {
+ isc_throw(LibraryError,
+ "OpenSSL EVP_PKEY_new_raw_private_key() failed");
+ }
+
+ if (!EVP_DigestSignInit(md_, NULL, algo, NULL, pkey)) {
+ EVP_PKEY_free(pkey);
+ isc_throw(LibraryError, "OpenSSL EVP_DigestSignInit() failed");
}
+
+ EVP_PKEY_free(pkey);
}
/// @brief Destructor
~HMACImpl() {
if (md_) {
- HMAC_CTX_free(md_);
+ EVP_MD_CTX_free(md_);
}
md_ = 0;
}
///
/// @return output size of the digest
size_t getOutputLength() const {
- int size = HMAC_size(md_);
- if (size < 0) {
- isc_throw(LibraryError, "OpenSSL HMAC_size() failed");
- }
- return (static_cast<size_t>(size));
+ return (EVP_MD_CTX_size(md_));
}
/// @brief Add data to digest
///
/// See @ref isc::cryptolink::HMAC::update() for details.
void update(const void* data, const size_t len) {
- if (!HMAC_Update(md_,
- static_cast<const unsigned char*>(data),
- len)) {
- isc_throw(LibraryError, "OpenSSLHMAC_Update() failed");
+ if (len == 0) {
+ return;
+ }
+
+ if (!EVP_DigestSignUpdate(md_, data, len)) {
+ isc_throw(LibraryError, "OpenSSL EVP_DigestSignUpdate() failed");
}
}
void sign(isc::util::OutputBuffer& result, size_t len) {
size_t size = getOutputLength();
ossl::SecBuf<unsigned char> digest(size);
- if (!HMAC_Final(md_, &digest[0], NULL)) {
- isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
+ size_t digest_len = size;
+ if (!EVP_DigestSignFinal(md_, &digest[0], &digest_len)) {
+ isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
+ }
+ if (digest_len != size) {
+ isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
}
if (len > size) {
len = size;
void sign(void* result, size_t len) {
size_t size = getOutputLength();
ossl::SecBuf<unsigned char> digest(size);
- if (!HMAC_Final(md_, &digest[0], NULL)) {
- isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
+ size_t digest_len = size;
+ if (!EVP_DigestSignFinal(md_, &digest[0], &digest_len)) {
+ isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
+ }
+ if (digest_len != size) {
+ isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
}
if (len > size) {
len = size;
std::vector<uint8_t> sign(size_t len) {
size_t size = getOutputLength();
ossl::SecBuf<unsigned char> digest(size);
- if (!HMAC_Final(md_, &digest[0], NULL)) {
- isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
+ size_t digest_len = size;
+ if (!EVP_DigestSignFinal(md_, &digest[0], &digest_len)) {
+ isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
+ }
+ if (digest_len != size) {
+ isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
}
if (len < size) {
digest.resize(len);
return (false);
}
// Get the digest from a copy of the context
- HMAC_CTX* tmp = HMAC_CTX_new();
+ EVP_MD_CTX* tmp = EVP_MD_CTX_new();
if (tmp == 0) {
- isc_throw(LibraryError, "OpenSSL HMAC_CTX_new() failed");
+ isc_throw(LibraryError, "OpenSSL EVP_MD_CTX_new() failed");
}
- if (!HMAC_CTX_copy(tmp, md_)) {
- HMAC_CTX_free(tmp);
- isc_throw(LibraryError, "OpenSSL HMAC_CTX_copy() failed");
+ if (!EVP_MD_CTX_copy(tmp, md_)) {
+ EVP_MD_CTX_free(tmp);
+ isc_throw(LibraryError, "OpenSSL EVP_MD_CTX_copy() failed");
}
ossl::SecBuf<unsigned char> digest(size);
- if (!HMAC_Final(tmp, &digest[0], NULL)) {
- HMAC_CTX_free(tmp);
- isc_throw(LibraryError, "OpenSSL HMAC_Final() failed");
+ size_t digest_len = size;
+ if (!EVP_DigestSignFinal(tmp, &digest[0], &digest_len)) {
+ EVP_MD_CTX_free(tmp);
+ isc_throw(LibraryError, "OpenSSL EVP_DigestSignFinal() failed");
+ }
+ if (digest_len != size) {
+ EVP_MD_CTX_free(tmp);
+ isc_throw(LibraryError, "OpenSSL partial EVP_DigestSignFinal()");
}
- HMAC_CTX_free(tmp);
+ EVP_MD_CTX_free(tmp);
if (len > size) {
len = size;
}
/// @brief The hash algorithm
HashAlgorithm hash_algorithm_;
- /// @brief The protected pointer to the OpenSSL HMAC_CTX structure
- HMAC_CTX* md_;
+ /// @brief The protected pointer to the OpenSSL EVP_MD_CTX structure
+ EVP_MD_CTX* md_;
};
HMAC::HMAC(const void* secret, size_t secret_length,