This is an automated email from the ASF dual-hosted git repository. joemcdonnell pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/impala.git
commit c5ec833aec58425d203fbc452058ea837ad2ae75 Author: Joe McDonnell <joemcdonn...@cloudera.com> AuthorDate: Tue Jun 13 21:38:35 2023 -0700 IMPALA-12211: Adapt FIPS detection to handle OpenSSL 3 Various pieces of our code detect FIPS and enable/disable code and tests accordingly (e.g. old hashing algorithms like MD5 are not allowed). The detection logic currently uses FIPS_mode(), but FIPS_mode() was removed in OpenSSL 3. The OpenSSL 3 equivalent is EVP_default_properties_is_fips_enabled(). This adds a new IsFIPSMode() function in util/openssl-util.h that uses OPENSSL_VERSION_NUMBER to dispatch to either FIPS_mode() or EVP_default_properties_is_fips_enabled(). This also pulls in the Kudu changes to handle this for KRPC. The original upstream Kudu commits were: c24629083e : Follow-up on OpenSSL 3 FIPS_mode removal acac73ecda : Fix OpenSSL3 FIPS_mode() issue on RHEL9.1 Testing: - Built on Ubuntu 22 / Redhat 9 with OpenSSL 3 Change-Id: I78571c8086bea06bf7b355cfe86a16f190cde067 Reviewed-on: http://gerrit.cloudera.org:8080/20072 Reviewed-by: Michael Smith <michael.sm...@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenk...@cloudera.com> Reviewed-by: Wenzhe Zhou <wz...@cloudera.com> --- be/src/exprs/expr-test.cc | 10 +++++----- be/src/exprs/mask-functions-ir.cc | 4 ++-- be/src/exprs/utility-functions-ir.cc | 9 ++++----- be/src/kudu/util/openssl_util.cc | 6 +++++- be/src/kudu/util/openssl_util.h | 4 ++++ be/src/util/openssl-util.h | 16 ++++++++++++---- be/src/util/webserver-test.cc | 6 +++--- be/src/util/webserver.cc | 3 ++- 8 files changed, 37 insertions(+), 21 deletions(-) diff --git a/be/src/exprs/expr-test.cc b/be/src/exprs/expr-test.cc index a0be31492..5edd34e65 100644 --- a/be/src/exprs/expr-test.cc +++ b/be/src/exprs/expr-test.cc @@ -29,7 +29,6 @@ #include <boost/scoped_ptr.hpp> #include <boost/unordered_map.hpp> -#include <openssl/crypto.h> #include <openssl/sha.h> #include "codegen/llvm-codegen.h" @@ -71,6 +70,7 @@ #include "util/debug-util.h" #include "util/decimal-util.h" #include "util/metrics.h" +#include "util/openssl-util.h" #include "util/string-parser.h" #include "util/string-util.h" #include "util/test-info.h" @@ -5706,7 +5706,7 @@ TEST_P(ExprTest, SHAFunctions) { unsigned char sha384[SHA384_DIGEST_LENGTH]; unsigned char sha512[SHA512_DIGEST_LENGTH]; - if (FIPS_mode()) { + if (IsFIPSMode()) { TestError(sha1fn); TestError(sha2fn + ", 224)"); TestError(sha2fn + ", 256)"); @@ -5733,7 +5733,7 @@ TEST_P(ExprTest, SHAFunctions) { TestStringValue(sha2fn + ", 512)", expected); // Test empty strings. Empty string is valid input and produces hash. - if (!FIPS_mode()) { + if (!IsFIPSMode()) { SHA1(input, 0, sha1); expected = ToHex(sha1, SHA_DIGEST_LENGTH); TestStringValue("sha1('')", expected); @@ -5764,7 +5764,7 @@ TEST_P(ExprTest, SHAFunctions) { } TEST_P(ExprTest, MD5Function) { - if (FIPS_mode()) { + if (IsFIPSMode()) { TestError("md5('foo')"); } else { std::string expected("1fdf956bdad98101171512d18eec3bcf"); @@ -10787,7 +10787,7 @@ TEST_P(ExprTest, MaskTest) { } TEST_P(ExprTest, MaskHashTest) { - if (FIPS_mode()) { + if (IsFIPSMode()) { TestStringValue("mask_hash('TestString-123')", "f3a58111be6ecec11449ac44654e72376b7759883ea11723b6e51354d50436de" "645bd061cb5c2b07b68e15b7a7c342cac41f69b9c4efe19e810bbd7abf639a1c"); diff --git a/be/src/exprs/mask-functions-ir.cc b/be/src/exprs/mask-functions-ir.cc index c96be187d..b6725ea5c 100644 --- a/be/src/exprs/mask-functions-ir.cc +++ b/be/src/exprs/mask-functions-ir.cc @@ -20,13 +20,13 @@ #include <boost/locale/generator.hpp> #include <boost/locale/utf8_codecvt.hpp> #include <gutil/strings/substitute.h> -#include <openssl/crypto.h> #include <openssl/err.h> #include <openssl/sha.h> #include "exprs/anyval-util.h" #include "exprs/math-functions.h" #include "exprs/string-functions.h" +#include "util/openssl-util.h" #include "util/ubsan.h" #include "common/names.h" @@ -943,7 +943,7 @@ TimestampVal MaskFunctions::Mask(FunctionContext* ctx, const TimestampVal& val, StringVal MaskFunctions::MaskHash(FunctionContext* ctx, const StringVal& val) { // Hive hash the value by sha256 and encoding it into a lower case hex string in // non FIPS mode. In FIPS enabled mode, it's required to use sha512 for mask hash. - if (FIPS_mode()) { + if (IsFIPSMode()) { StringVal sha512_hash(ctx, SHA512_DIGEST_LENGTH); if (UNLIKELY(sha512_hash.is_null)) return StringVal::null(); discard_result(SHA512(val.ptr, val.len, sha512_hash.ptr)); diff --git a/be/src/exprs/utility-functions-ir.cc b/be/src/exprs/utility-functions-ir.cc index ce2925350..2d6ecfaec 100644 --- a/be/src/exprs/utility-functions-ir.cc +++ b/be/src/exprs/utility-functions-ir.cc @@ -22,13 +22,12 @@ #include "exprs/math-functions.h" #include "exprs/string-functions.h" -#include <openssl/crypto.h> -#include <openssl/evp.h> #include <openssl/md5.h> #include <openssl/sha.h> #include "runtime/runtime-state.h" #include "udf/udf-internal.h" #include "util/debug-util.h" +#include "util/openssl-util.h" #include "util/time.h" #include "common/names.h" @@ -247,7 +246,7 @@ StringVal UtilityFunctions::Sha1(FunctionContext* ctx, const StringVal& input_st } // SHA-1 is not supported for FIPS. - if (FIPS_mode()) { + if (IsFIPSMode()) { ctx->SetError("sha1 is not supported in FIPS mode."); return StringVal::null(); } else { @@ -266,7 +265,7 @@ StringVal UtilityFunctions::Sha2(FunctionContext* ctx, const StringVal& input_st } // SHA-224 and SHA-256 are deprecated for FIPS mode. - if (FIPS_mode() && (bit_len.val == 224 || bit_len.val == 256)) { + if (IsFIPSMode() && (bit_len.val == 224 || bit_len.val == 256)) { ctx->SetError("Only bit lengths 384 and 512 are supported in FIPS mode."); return StringVal::null(); } @@ -308,7 +307,7 @@ StringVal UtilityFunctions::Md5(FunctionContext* ctx, const StringVal& input_str if (input_str.is_null) { return StringVal::null(); } - if (UNLIKELY(FIPS_mode())) { + if (UNLIKELY(IsFIPSMode())) { ctx->SetError("MD5 is not supported in FIPS mode."); return StringVal::null(); } else { diff --git a/be/src/kudu/util/openssl_util.cc b/be/src/kudu/util/openssl_util.cc index b210f3d66..33e985b62 100644 --- a/be/src/kudu/util/openssl_util.cc +++ b/be/src/kudu/util/openssl_util.cc @@ -95,7 +95,11 @@ void ThreadIdCB(CRYPTO_THREADID* tid) { #endif void CheckFIPSMode() { - auto fips_mode = FIPS_mode(); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + int fips_mode = FIPS_mode(); +#else + int fips_mode = EVP_default_properties_is_fips_enabled(NULL); +#endif // If the environment variable KUDU_REQUIRE_FIPS_MODE is set to "1", we // check if FIPS approved mode is enabled. If not, we crash the process. // As this is used in clients as well, we can't use gflags to set this. diff --git a/be/src/kudu/util/openssl_util.h b/be/src/kudu/util/openssl_util.h index d1e4b16a3..b62eca59a 100644 --- a/be/src/kudu/util/openssl_util.h +++ b/be/src/kudu/util/openssl_util.h @@ -17,9 +17,13 @@ #pragma once +#include <openssl/crypto.h> #include <openssl/err.h> #include <openssl/pem.h> #include <openssl/ssl.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/types.h> +#endif #include <openssl/x509.h> #include <functional> diff --git a/be/src/util/openssl-util.h b/be/src/util/openssl-util.h index c7a30e400..0864e5fb6 100644 --- a/be/src/util/openssl-util.h +++ b/be/src/util/openssl-util.h @@ -15,10 +15,10 @@ // specific language governing permissions and limitations // under the License. -#ifndef IMPALA_UTIL_OPENSSL_UTIL_H -#define IMPALA_UTIL_OPENSSL_UTIL_H +#pragma once #include <openssl/aes.h> +#include <openssl/crypto.h> #include <openssl/evp.h> #include <openssl/sha.h> #include <openssl/ssl.h> @@ -59,6 +59,16 @@ bool IsExternalTlsConfigured(); /// and again periodically to add new entropy. void SeedOpenSSLRNG(); +/// Returns true if OpenSSL's FIPS mode is enabled. This calculation varies by the OpenSSL +/// version, so it is useful to have a shared function. +inline bool IsFIPSMode() { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + return FIPS_mode() > 0; +#else + return EVP_default_properties_is_fips_enabled(nullptr) > 0; +#endif +}; + enum AES_CIPHER_MODE { AES_256_CFB, AES_256_CTR, @@ -200,5 +210,3 @@ class EncryptionKey { }; } - -#endif diff --git a/be/src/util/webserver-test.cc b/be/src/util/webserver-test.cc index 29256cbea..2ed6d567f 100644 --- a/be/src/util/webserver-test.cc +++ b/be/src/util/webserver-test.cc @@ -24,7 +24,6 @@ #include <boost/lexical_cast.hpp> #include <gutil/strings/substitute.h> #include <map> -#include <openssl/crypto.h> #include <openssl/ssl.h> #include <regex> @@ -35,6 +34,7 @@ #include "util/default-path-handlers.h" #include "util/kudu-status-util.h" #include "util/metrics.h" +#include "util/openssl-util.h" #include "util/os-util.h" #include "util/webserver.h" @@ -662,7 +662,7 @@ TEST(Webserver, StartWithPasswordFileTest) { MetricGroup metrics("webserver-test"); Webserver webserver("", FLAGS_webserver_port, &metrics); - if (FIPS_mode()) { + if (IsFIPSMode()) { ASSERT_FALSE(webserver.Start().ok()); } else { ASSERT_OK(webserver.Start()); @@ -701,7 +701,7 @@ TEST(Webserver, StartWithPasswordFileTest) { } TEST(Webserver, StartWithMissingPasswordFileTest) { - if (FIPS_mode()) return; + if (IsFIPSMode()) return; stringstream password_file; password_file << getenv("IMPALA_HOME") << "/be/src/testutil/doesntexist"; auto password = diff --git a/be/src/util/webserver.cc b/be/src/util/webserver.cc index d5a754911..a4436f6f8 100644 --- a/be/src/util/webserver.cc +++ b/be/src/util/webserver.cc @@ -55,6 +55,7 @@ #include "util/jwt-util.h" #include "util/mem-info.h" #include "util/metrics.h" +#include "util/openssl-util.h" #include "util/os-info.h" #include "util/os-util.h" #include "util/pretty-printer.h" @@ -450,7 +451,7 @@ Status Webserver::Start() { } if (!FLAGS_webserver_password_file.empty()) { - if (FIPS_mode()) { + if (IsFIPSMode()) { return Status("HTTP digest authorization is not supported in FIPS approved mode."); } else { // Squeasel doesn't log anything if it can't stat the password file (but will if it