ruby/ruby-3.3.0-openssl-3.2.0-fix-fips-get-set-in-openssl-3.patch
Jun Aruga e696601395 Fix OpenSSL.fips_mode and OpenSSL::PKey.read in OpenSSL 3 FIPS.
This commit was cherry-picked from Fedora rawhide
<1f35109c5e>.

Resolves: RHEL-5590
2023-10-11 19:17:26 +02:00

143 lines
5.3 KiB
Diff

From 29920ec109751459a65c6478525f2e59c644891f Mon Sep 17 00:00:00 2001
From: Jun Aruga <jaruga@redhat.com>
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 <https://github.com/openssl/openssl/blob/master/doc/man7/migration_guide.pod#removed-fips_mode-and-fips_mode_set>
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 6c532aca94..fcf3744c65 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
diff --git a/test/openssl/test_fips.rb b/test/openssl/test_fips.rb
index 8cd474f9a3..56a12a94ce 100644
--- a/test/openssl/test_fips.rb
+++ b/test/openssl/test_fips.rb
@@ -4,22 +4,46 @@
if defined?(OpenSSL)
class OpenSSL::TestFIPS < OpenSSL::TestCase
+ def test_fips_mode_get_is_true_on_fips_mode_enabled
+ unless ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"]
+ omit "Only for FIPS mode environment"
+ end
+
+ assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
+ assert OpenSSL.fips_mode == true, ".fips_mode should return true on FIPS mode enabled"
+ end;
+ end
+
+ def test_fips_mode_get_is_false_on_fips_mode_disabled
+ if ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"]
+ omit "Only for non-FIPS mode environment"
+ end
+
+ assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
+ message = ".fips_mode should return false on FIPS mode disabled. " \
+ "If you run the test on FIPS mode, please set " \
+ "TEST_RUBY_OPENSSL_FIPS_ENABLED=true"
+ assert OpenSSL.fips_mode == false, message
+ end;
+ end
+
def test_fips_mode_is_reentrant
OpenSSL.fips_mode = false
OpenSSL.fips_mode = false
end
- def test_fips_mode_get
- return unless OpenSSL::OPENSSL_FIPS
+ def test_fips_mode_get_with_fips_mode_set
+ omit('OpenSSL is not FIPS-capable') unless OpenSSL::OPENSSL_FIPS
+
assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
require #{__FILE__.dump}
begin
OpenSSL.fips_mode = true
- assert OpenSSL.fips_mode == true, ".fips_mode returns true when .fips_mode=true"
+ assert OpenSSL.fips_mode == true, ".fips_mode should return true when .fips_mode=true"
OpenSSL.fips_mode = false
- assert OpenSSL.fips_mode == false, ".fips_mode returns false when .fips_mode=false"
+ assert OpenSSL.fips_mode == false, ".fips_mode should return false when .fips_mode=false"
rescue OpenSSL::OpenSSLError
pend "Could not set FIPS mode (OpenSSL::OpenSSLError: \#$!); skipping"
end
--
2.41.0