You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2022/06/15 23:49:24 UTC
[trafficserver] branch master updated: Move HKDF to OpenSSL 3 interfaces (#8909)
This is an automated email from the ASF dual-hosted git repository.
maskit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 8ca74ee27 Move HKDF to OpenSSL 3 interfaces (#8909)
8ca74ee27 is described below
commit 8ca74ee27cc14f27a1480a88fc453fbabc954e4e
Author: Jered Floyd <je...@redhat.com>
AuthorDate: Wed Jun 15 19:49:19 2022 -0400
Move HKDF to OpenSSL 3 interfaces (#8909)
* Move HKDF and HMACs to openssl 3 interfaces
* clang-format changed files
* Revert HMAC change, move EVP_KDF to separate implementation file, add missing QUIC changes
* switch back to OPENSSL_IS_OPENSSL3 symbol due to conflict with API_COMPAT symbol
* Get digest size from name
* Remove extraneous HKDF member variable '_digest'
---
build/crypto.m4 | 2 +-
configure.ac | 1 +
include/tscore/HKDF.h | 15 +++-
iocore/net/quic/QUICHKDF.h | 2 +-
iocore/net/quic/QUICKeyGenerator.cc | 6 +-
iocore/net/quic/QUICTLS.h | 2 +-
iocore/net/quic/QUICTLS_boringssl.cc | 6 +-
iocore/net/quic/QUICTLS_openssl.cc | 6 +-
.../access_control/unit_tests/test_utils.cc | 8 ++
src/tscore/HKDF_boringssl.cc | 10 ++-
src/tscore/HKDF_openssl.cc | 7 +-
src/tscore/HKDF_openssl3.cc | 85 ++++++++++++++++++++++
src/tscore/Makefile.am | 4 +
src/tscore/unit_tests/test_HKDF.cc | 14 ++--
14 files changed, 140 insertions(+), 28 deletions(-)
diff --git a/build/crypto.m4 b/build/crypto.m4
index a5d68af31..ce91ea60e 100644
--- a/build/crypto.m4
+++ b/build/crypto.m4
@@ -74,7 +74,7 @@ int main() {
return 1;
}
])],
- [AC_MSG_RESULT(yes) TS_ADDTO(CPPFLAGS, -DOPENSSL_API_COMPAT=10002)], [AC_MSG_RESULT(no)]
+ [AC_MSG_RESULT(yes) TS_ADDTO(CPPFLAGS, -DOPENSSL_API_COMPAT=10002 -DOPENSSL_IS_OPENSSL3) openssl_is_openssl3=1], [AC_MSG_RESULT(no)]
)
])
diff --git a/configure.ac b/configure.ac
index 1ffcc3196..dd5cb62d3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1253,6 +1253,7 @@ TS_CHECK_CRYPTO_VERSION
# Check for OpenSSL Version 3 and add compatiblity define if needed
TS_CHECK_OPENSSL3
+AM_CONDITIONAL([OPENSSL_IS_OPENSSL3], [test -n "$openssl_is_openssl3"])
# Check for openssl ASYNC jobs
TS_CHECK_CRYPTO_ASYNC
diff --git a/include/tscore/HKDF.h b/include/tscore/HKDF.h
index 78ad0f2e7..f405b6164 100644
--- a/include/tscore/HKDF.h
+++ b/include/tscore/HKDF.h
@@ -30,16 +30,25 @@
#include <openssl/evp.h>
#endif
+#ifdef OPENSSL_IS_OPENSSL3
+#include <openssl/core.h>
+#endif
+
class HKDF
{
public:
- HKDF(const EVP_MD *digest);
+ HKDF(const char *digest);
~HKDF();
int extract(uint8_t *dst, size_t *dst_len, const uint8_t *salt, size_t salt_len, const uint8_t *ikm, size_t ikm_len);
int expand(uint8_t *dst, size_t *dst_len, const uint8_t *prk, size_t prk_len, const uint8_t *info, size_t info_len,
uint16_t length);
protected:
- const EVP_MD *_digest = nullptr;
- EVP_PKEY_CTX *_pctx = nullptr;
+#ifdef OPENSSL_IS_OPENSSL3
+ EVP_KDF_CTX *_kctx = nullptr;
+ OSSL_PARAM params[5];
+#else
+ EVP_PKEY_CTX *_pctx = nullptr;
+ const EVP_MD *_digest_md = nullptr;
+#endif
};
diff --git a/iocore/net/quic/QUICHKDF.h b/iocore/net/quic/QUICHKDF.h
index 4bb0ffb00..6b7a31637 100644
--- a/iocore/net/quic/QUICHKDF.h
+++ b/iocore/net/quic/QUICHKDF.h
@@ -28,7 +28,7 @@
class QUICHKDF : public HKDF
{
public:
- QUICHKDF(const EVP_MD *digest) : HKDF(digest) {}
+ QUICHKDF(const char *digest) : HKDF(digest) {}
int expand(uint8_t *dst, size_t *dst_len, const uint8_t *secret, size_t secret_len, const char *label, size_t label_len,
uint16_t length);
};
diff --git a/iocore/net/quic/QUICKeyGenerator.cc b/iocore/net/quic/QUICKeyGenerator.cc
index 7ac32baf6..09ed9eda3 100644
--- a/iocore/net/quic/QUICKeyGenerator.cc
+++ b/iocore/net/quic/QUICKeyGenerator.cc
@@ -49,7 +49,7 @@ void
QUICKeyGenerator::generate(QUICVersion version, uint8_t *hp_key, uint8_t *pp_key, uint8_t *iv, size_t *iv_len, QUICConnectionId cid)
{
const EVP_CIPHER *cipher = this->_get_cipher_for_initial();
- const EVP_MD *md = EVP_sha256();
+ const char *md = "SHA256";
uint8_t secret[512];
size_t secret_len = sizeof(secret);
QUICHKDF hkdf(md);
@@ -57,7 +57,7 @@ QUICKeyGenerator::generate(QUICVersion version, uint8_t *hp_key, uint8_t *pp_key
switch (this->_ctx) {
case Context::CLIENT:
this->_generate_initial_secret(version, secret, &secret_len, hkdf, cid, LABEL_FOR_CLIENT_INITIAL_SECRET.data(),
- LABEL_FOR_CLIENT_INITIAL_SECRET.length(), EVP_MD_size(md));
+ LABEL_FOR_CLIENT_INITIAL_SECRET.length(), EVP_MD_size(EVP_get_digestbyname(md)));
if (is_debug_tag_set("vv_quic_crypto")) {
uint8_t print_buf[1024 + 1];
QUICDebug::to_hex(print_buf, secret, secret_len);
@@ -67,7 +67,7 @@ QUICKeyGenerator::generate(QUICVersion version, uint8_t *hp_key, uint8_t *pp_key
break;
case Context::SERVER:
this->_generate_initial_secret(version, secret, &secret_len, hkdf, cid, LABEL_FOR_SERVER_INITIAL_SECRET.data(),
- LABEL_FOR_SERVER_INITIAL_SECRET.length(), EVP_MD_size(md));
+ LABEL_FOR_SERVER_INITIAL_SECRET.length(), EVP_MD_size(EVP_get_digestbyname(md)));
if (is_debug_tag_set("vv_quic_crypto")) {
uint8_t print_buf[1024 + 1];
QUICDebug::to_hex(print_buf, secret, secret_len);
diff --git a/iocore/net/quic/QUICTLS.h b/iocore/net/quic/QUICTLS.h
index 9a488c4ff..a1ca8bc68 100644
--- a/iocore/net/quic/QUICTLS.h
+++ b/iocore/net/quic/QUICTLS.h
@@ -89,7 +89,7 @@ public:
private:
QUICKeyGenerator _keygen_for_client = QUICKeyGenerator(QUICKeyGenerator::Context::CLIENT);
QUICKeyGenerator _keygen_for_server = QUICKeyGenerator(QUICKeyGenerator::Context::SERVER);
- const EVP_MD *_get_handshake_digest() const;
+ const char *_get_handshake_digest() const;
int _read_early_data();
int _write_early_data();
diff --git a/iocore/net/quic/QUICTLS_boringssl.cc b/iocore/net/quic/QUICTLS_boringssl.cc
index 091b186e0..dbd808f66 100644
--- a/iocore/net/quic/QUICTLS_boringssl.cc
+++ b/iocore/net/quic/QUICTLS_boringssl.cc
@@ -348,15 +348,15 @@ QUICTLS::_pass_quic_data_to_ssl_impl(const QUICHandshakeMsgs &in)
}
}
-const EVP_MD *
+const char *
QUICTLS::_get_handshake_digest() const
{
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(this->_ssl))) {
case TLS1_CK_AES_128_GCM_SHA256:
case TLS1_CK_CHACHA20_POLY1305_SHA256:
- return EVP_sha256();
+ return "SHA256";
case TLS1_CK_AES_256_GCM_SHA384:
- return EVP_sha384();
+ return "SHA384";
default:
ink_assert(false);
return nullptr;
diff --git a/iocore/net/quic/QUICTLS_openssl.cc b/iocore/net/quic/QUICTLS_openssl.cc
index 5a5d3a9da..23bcfcc10 100644
--- a/iocore/net/quic/QUICTLS_openssl.cc
+++ b/iocore/net/quic/QUICTLS_openssl.cc
@@ -312,7 +312,7 @@ QUICTLS::_pass_quic_data_to_ssl_impl(const QUICHandshakeMsgs &in)
}
}
-const EVP_MD *
+const char *
QUICTLS::_get_handshake_digest() const
{
switch (SSL_CIPHER_get_id(SSL_get_current_cipher(this->_ssl))) {
@@ -320,9 +320,9 @@ QUICTLS::_get_handshake_digest() const
case TLS1_3_CK_CHACHA20_POLY1305_SHA256:
case TLS1_3_CK_AES_128_CCM_SHA256:
case TLS1_3_CK_AES_128_CCM_8_SHA256:
- return EVP_sha256();
+ return "SHA256";
case TLS1_3_CK_AES_256_GCM_SHA384:
- return EVP_sha384();
+ return "SHA384";
default:
ink_assert(false);
return nullptr;
diff --git a/plugins/experimental/access_control/unit_tests/test_utils.cc b/plugins/experimental/access_control/unit_tests/test_utils.cc
index 5040964aa..228f526dc 100644
--- a/plugins/experimental/access_control/unit_tests/test_utils.cc
+++ b/plugins/experimental/access_control/unit_tests/test_utils.cc
@@ -21,6 +21,7 @@
* @brief Unit tests for functions used in utils.cc
*/
+#include <openssl/opensslv.h>
#include <catch.hpp> /* catch unit-test framework */
#include "../utils.h"
#include "../common.h"
@@ -253,6 +254,13 @@ TEST_CASE("HMAC Digest: test various supported/unsupported types", "[MAC][access
digests.push_back("ccf3230972bcf229fb3b16741495c74a72bbdd14");
#endif
+#ifdef OPENSSL_IS_OPENSSL3 // MD4, RIPEMD160 are deprecated in OpenSSL 3
+ types.pop_front();
+ digests.pop_front();
+ types.pop_back();
+ digests.pop_back();
+#endif
+
StringList::iterator digestIter = digests.begin();
for (String digestType : types) {
size_t outLen = cryptoMessageDigestGet(digestType.c_str(), data.c_str(), data.length(), key.c_str(), key.length(), out,
diff --git a/src/tscore/HKDF_boringssl.cc b/src/tscore/HKDF_boringssl.cc
index 9fa84cdbd..7df0bc322 100644
--- a/src/tscore/HKDF_boringssl.cc
+++ b/src/tscore/HKDF_boringssl.cc
@@ -22,14 +22,18 @@
*/
#include "tscore/HKDF.h"
#include <openssl/hkdf.h>
+#include <openssl/digest.h>
-HKDF::HKDF(const EVP_MD *digest) : _digest(digest) {}
+HKDF::HKDF(const char *digest)
+{
+ this->_digest_md = EVP_get_digestbyname(digest);
+}
HKDF::~HKDF() {}
int
HKDF::extract(uint8_t *dst, size_t *dst_len, const uint8_t *salt, size_t salt_len, const uint8_t *ikm, size_t ikm_len)
{
- return HKDF_extract(dst, dst_len, this->_digest, ikm, ikm_len, salt, salt_len);
+ return HKDF_extract(dst, dst_len, this->_digest_md, ikm, ikm_len, salt, salt_len);
}
int
@@ -37,5 +41,5 @@ HKDF::expand(uint8_t *dst, size_t *dst_len, const uint8_t *prk, size_t prk_len,
uint16_t length)
{
*dst_len = length;
- return HKDF_expand(dst, length, this->_digest, prk, prk_len, info, info_len);
+ return HKDF_expand(dst, length, this->_digest_md, prk, prk_len, info, info_len);
}
diff --git a/src/tscore/HKDF_openssl.cc b/src/tscore/HKDF_openssl.cc
index ac8d69051..9c18cb07f 100644
--- a/src/tscore/HKDF_openssl.cc
+++ b/src/tscore/HKDF_openssl.cc
@@ -23,8 +23,9 @@
#include "tscore/HKDF.h"
#include <openssl/kdf.h>
-HKDF::HKDF(const EVP_MD *digest) : _digest(digest)
+HKDF::HKDF(const char *digest)
{
+ this->_digest_md = EVP_get_digestbyname(digest);
// XXX We cannot reuse pctx now due to a bug in OpenSSL
// this->_pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
}
@@ -51,7 +52,7 @@ HKDF::extract(uint8_t *dst, size_t *dst_len, const uint8_t *salt, size_t salt_le
if (EVP_PKEY_CTX_hkdf_mode(this->_pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) != 1) {
return -2;
}
- if (EVP_PKEY_CTX_set_hkdf_md(this->_pctx, this->_digest) != 1) {
+ if (EVP_PKEY_CTX_set_hkdf_md(this->_pctx, this->_digest_md) != 1) {
return -3;
}
if (EVP_PKEY_CTX_set1_hkdf_salt(this->_pctx, salt, salt_len) != 1) {
@@ -84,7 +85,7 @@ HKDF::expand(uint8_t *dst, size_t *dst_len, const uint8_t *prk, size_t prk_len,
if (EVP_PKEY_CTX_hkdf_mode(this->_pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) != 1) {
return -2;
}
- if (EVP_PKEY_CTX_set_hkdf_md(this->_pctx, this->_digest) != 1) {
+ if (EVP_PKEY_CTX_set_hkdf_md(this->_pctx, this->_digest_md) != 1) {
return -3;
}
if (EVP_PKEY_CTX_set1_hkdf_key(this->_pctx, prk, prk_len) != 1) {
diff --git a/src/tscore/HKDF_openssl3.cc b/src/tscore/HKDF_openssl3.cc
new file mode 100644
index 000000000..30c190dc8
--- /dev/null
+++ b/src/tscore/HKDF_openssl3.cc
@@ -0,0 +1,85 @@
+/** @file
+ *
+ * HKDF utility (OpenSSL version)
+ *
+ * @section license License
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "tscore/HKDF.h"
+#include <openssl/kdf.h>
+#include <cstring>
+#include <openssl/core_names.h>
+
+HKDF::HKDF(const char *digest)
+{
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "HKDF", NULL);
+ this->_kctx = EVP_KDF_CTX_new(kdf);
+ EVP_KDF_free(kdf);
+ *params = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (char *)digest, strlen(digest));
+}
+
+HKDF::~HKDF()
+{
+ EVP_KDF_CTX_free(this->_kctx);
+ this->_kctx = nullptr;
+}
+
+int
+HKDF::extract(uint8_t *dst, size_t *dst_len, const uint8_t *salt, size_t salt_len, const uint8_t *ikm, size_t ikm_len)
+{
+ size_t keysize;
+ int mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
+ OSSL_PARAM *p = params + 1;
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (uint8_t *)ikm, ikm_len);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, (uint8_t *)salt, salt_len);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
+ *p = OSSL_PARAM_construct_end();
+
+ EVP_KDF_CTX_set_params(_kctx, params);
+ keysize = EVP_KDF_CTX_get_kdf_size(this->_kctx);
+ if (*dst_len < keysize) {
+ return -1;
+ }
+ if (EVP_KDF_derive(_kctx, dst, keysize, params) <= 0) {
+ EVP_KDF_CTX_reset(this->_kctx);
+ return -2;
+ }
+ *dst_len = keysize;
+ EVP_KDF_CTX_reset(this->_kctx);
+
+ return 1;
+}
+
+int
+HKDF::expand(uint8_t *dst, size_t *dst_len, const uint8_t *prk, size_t prk_len, const uint8_t *info, size_t info_len,
+ uint16_t length)
+{
+ int mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
+ OSSL_PARAM *p = params + 1;
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (uint8_t *)prk, prk_len);
+ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, (uint8_t *)info, info_len);
+ *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
+ *p = OSSL_PARAM_construct_end();
+ if (EVP_KDF_derive(_kctx, dst, length, params) <= 0) {
+ return -1;
+ }
+ *dst_len = length;
+ EVP_KDF_CTX_reset(this->_kctx);
+
+ return 1;
+}
diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am
index 80fbb8f77..e96104f7f 100644
--- a/src/tscore/Makefile.am
+++ b/src/tscore/Makefile.am
@@ -130,8 +130,12 @@ if HAS_HKDF
if OPENSSL_IS_BORINGSSL
HKDF_impl = HKDF_boringssl.cc
else
+if OPENSSL_IS_OPENSSL3
+HKDF_impl = HKDF_openssl3.cc
+else
HKDF_impl = HKDF_openssl.cc
endif
+endif
libtscore_la_SOURCES += \
$(HKDF_impl)
endif
diff --git a/src/tscore/unit_tests/test_HKDF.cc b/src/tscore/unit_tests/test_HKDF.cc
index 59d2a3540..2c6404b57 100644
--- a/src/tscore/unit_tests/test_HKDF.cc
+++ b/src/tscore/unit_tests/test_HKDF.cc
@@ -54,7 +54,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha256());
+ HKDF hkdf("SHA256");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);
@@ -104,7 +104,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha256());
+ HKDF hkdf("SHA256");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);
@@ -140,7 +140,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha256());
+ HKDF hkdf("SHA256");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);
@@ -178,7 +178,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha1());
+ HKDF hkdf("SHA1");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);
@@ -226,7 +226,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha1());
+ HKDF hkdf("SHA1");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);
@@ -261,7 +261,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha1());
+ HKDF hkdf("SHA1");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);
@@ -296,7 +296,7 @@ TEST_CASE("HKDF tests", "[hkdf]")
uint8_t okm[256] = {0};
size_t okm_len = sizeof(okm);
- HKDF hkdf(EVP_sha1());
+ HKDF hkdf("SHA1");
// Extract
CHECK(hkdf.extract(prk, &prk_len, salt, sizeof(salt), ikm, sizeof(ikm)) == 1);