From 87102b16eaa004161c7a7406f3b3609e016cd215 Mon Sep 17 00:00:00 2001 From: Michael Hashizume Date: Thu, 14 Mar 2024 15:27:43 -0700 Subject: [PATCH] Apply Ruby patch to enable FIPS with OpenSSL 3 Prior to this commit, attempting to enable fips_mode in Ruby 3.2.3's OpenSSL gem would cause the error "This version of OpenSSL does not support FIPS mode (OpenSSL::OpenSSLError)". This was due to OpenSSL removing the FIPS_mode() function in OpenSSL 3, which Ruby previously relied on to detect if FIPS was enabled. Upstream has fixed this incompatibility with OpenSSL 3 in Ruby 3.3. The contributor has indicated that the fix should be backported to Rubies 3.0-3.2 in the future. This commit applies Ruby's fix as a patch. See also: - ruby/ruby@678d41bc51fe31834eec0b653ba0e47de5420aa0 - https://bugs.ruby-lang.org/issues/20000 --- configs/components/ruby-3.2.3.rb | 6 ++ resources/patches/ruby_32/openssl3_fips.patch | 84 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 resources/patches/ruby_32/openssl3_fips.patch diff --git a/configs/components/ruby-3.2.3.rb b/configs/components/ruby-3.2.3.rb index 762407c0c..b67387213 100644 --- a/configs/components/ruby-3.2.3.rb +++ b/configs/components/ruby-3.2.3.rb @@ -55,6 +55,12 @@ pkg.apply_patch "#{base}/revert_ruby_utf8_default_encoding.patch" end + if platform.is_fips? + # This is needed on Ruby < 3.3 until the fix is backported (if ever) + # See: https://bugs.ruby-lang.org/issues/20000 + pkg.apply_patch "#{base}/openssl3_fips.patch" + end + #################### # ENVIRONMENT, FLAGS #################### diff --git a/resources/patches/ruby_32/openssl3_fips.patch b/resources/patches/ruby_32/openssl3_fips.patch new file mode 100644 index 000000000..2f3632354 --- /dev/null +++ b/resources/patches/ruby_32/openssl3_fips.patch @@ -0,0 +1,84 @@ +From 678d41bc51fe31834eec0b653ba0e47de5420aa0 Mon Sep 17 00:00:00 2001 +From: Jun Aruga +Date: Thu, 16 Mar 2023 21:36:43 +0100 +Subject: [PATCH] [ruby/openssl] Implement FIPS functions on OpenSSL 3. + +This commit is to implement the `OpenSSL::OPENSSL_FIPS`, `ossl_fips_mode_get` +and `ossl_fips_mode_set` to pass the test `test/openssl/test_fips.rb`. + +It seems that the `OPENSSL_FIPS` macro is not used on the FIPS mode case any +more, and some FIPS related APIs also were removed in OpenSSL 3. + +See the document +the section OPENSSL 3.0 > Main Changes from OpenSSL 1.1.1 > +Other notable deprecations and changes - Removed FIPS_mode() and FIPS_mode_set() . + +The `OpenSSL::OPENSSL_FIPS` returns always true in OpenSSL 3 because the used +functions `EVP_default_properties_enable_fips` and `EVP_default_properties_is_fips_enabled` +works with the OpenSSL installed without FIPS option. + +The `TEST_RUBY_OPENSSL_FIPS_ENABLED` is set on the FIPS mode case on the CI. +Because I want to test that the `OpenSSL.fips_mode` returns the `true` or +'false' surely in the CI. You can test the FIPS mode case by setting +`TEST_RUBY_OPENSSL_FIPS_ENABLED` on local too. Right now I don't find a better +way to get the status of the FIPS mode enabled or disabled for this purpose. I +am afraid of the possibility that the FIPS test case is unintentionally skipped. + +I also replaced the ambiguous "returns" with "should return" in the tests. + +https://github.com/ruby/openssl/commit/c5b2bc1268 +--- + ext/openssl/ossl.c | 25 +++++++++++++++++++++---- + test/openssl/test_fips.rb | 32 ++++++++++++++++++++++++++++---- + 2 files changed, 49 insertions(+), 8 deletions(-) + +diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c +index 71ddcb9f02..be97b97a1a 100644 +--- a/ext/openssl/ossl.c ++++ b/ext/openssl/ossl.c +@@ -418,7 +418,11 @@ static VALUE + ossl_fips_mode_get(VALUE self) + { + +-#ifdef OPENSSL_FIPS ++#if OSSL_OPENSSL_PREREQ(3, 0, 0) ++ VALUE enabled; ++ enabled = EVP_default_properties_is_fips_enabled(NULL) ? Qtrue : Qfalse; ++ return enabled; ++#elif OPENSSL_FIPS + VALUE enabled; + enabled = FIPS_mode() ? Qtrue : Qfalse; + return enabled; +@@ -442,8 +446,18 @@ ossl_fips_mode_get(VALUE self) + static VALUE + ossl_fips_mode_set(VALUE self, VALUE enabled) + { +- +-#ifdef OPENSSL_FIPS ++#if OSSL_OPENSSL_PREREQ(3, 0, 0) ++ if (RTEST(enabled)) { ++ if (!EVP_default_properties_enable_fips(NULL, 1)) { ++ ossl_raise(eOSSLError, "Turning on FIPS mode failed"); ++ } ++ } else { ++ if (!EVP_default_properties_enable_fips(NULL, 0)) { ++ ossl_raise(eOSSLError, "Turning off FIPS mode failed"); ++ } ++ } ++ return enabled; ++#elif OPENSSL_FIPS + if (RTEST(enabled)) { + int mode = FIPS_mode(); + if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */ +@@ -1198,7 +1212,10 @@ Init_openssl(void) + * Boolean indicating whether OpenSSL is FIPS-capable or not + */ + rb_define_const(mOSSL, "OPENSSL_FIPS", +-#ifdef OPENSSL_FIPS ++/* OpenSSL 3 is FIPS-capable even when it is installed without fips option */ ++#if OSSL_OPENSSL_PREREQ(3, 0, 0) ++ Qtrue ++#elif OPENSSL_FIPS + Qtrue + #else + Qfalse