Skip to content

Commit c5b2bc1

Browse files
committed
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.
1 parent 18b0172 commit c5b2bc1

File tree

2 files changed

+49
-8
lines changed

2 files changed

+49
-8
lines changed

ext/openssl/ossl.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,11 @@ static VALUE
418418
ossl_fips_mode_get(VALUE self)
419419
{
420420

421-
#ifdef OPENSSL_FIPS
421+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
422+
VALUE enabled;
423+
enabled = EVP_default_properties_is_fips_enabled(NULL) ? Qtrue : Qfalse;
424+
return enabled;
425+
#elif OPENSSL_FIPS
422426
VALUE enabled;
423427
enabled = FIPS_mode() ? Qtrue : Qfalse;
424428
return enabled;
@@ -442,8 +446,18 @@ ossl_fips_mode_get(VALUE self)
442446
static VALUE
443447
ossl_fips_mode_set(VALUE self, VALUE enabled)
444448
{
445-
446-
#ifdef OPENSSL_FIPS
449+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
450+
if (RTEST(enabled)) {
451+
if (!EVP_default_properties_enable_fips(NULL, 1)) {
452+
ossl_raise(eOSSLError, "Turning on FIPS mode failed");
453+
}
454+
} else {
455+
if (!EVP_default_properties_enable_fips(NULL, 0)) {
456+
ossl_raise(eOSSLError, "Turning off FIPS mode failed");
457+
}
458+
}
459+
return enabled;
460+
#elif OPENSSL_FIPS
447461
if (RTEST(enabled)) {
448462
int mode = FIPS_mode();
449463
if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
@@ -1198,7 +1212,10 @@ Init_openssl(void)
11981212
* Boolean indicating whether OpenSSL is FIPS-capable or not
11991213
*/
12001214
rb_define_const(mOSSL, "OPENSSL_FIPS",
1201-
#ifdef OPENSSL_FIPS
1215+
/* OpenSSL 3 is FIPS-capable even when it is installed without fips option */
1216+
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
1217+
Qtrue
1218+
#elif OPENSSL_FIPS
12021219
Qtrue
12031220
#else
12041221
Qfalse

test/openssl/test_fips.rb

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,44 @@
44
if defined?(OpenSSL)
55

66
class OpenSSL::TestFIPS < OpenSSL::TestCase
7+
def test_fips_mode_get_is_true_on_fips_mode_enabled
8+
unless ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"]
9+
omit "Only for FIPS mode environment"
10+
end
11+
12+
assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
13+
assert OpenSSL.fips_mode == true, ".fips_mode should return true on FIPS mode enabled"
14+
end;
15+
end
16+
17+
def test_fips_mode_get_is_false_on_fips_mode_disabled
18+
if ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"]
19+
omit "Only for non-FIPS mode environment"
20+
end
21+
22+
assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
23+
message = ".fips_mode should return false on FIPS mode disabled. " \
24+
"If you run the test on FIPS mode, please set " \
25+
"TEST_RUBY_OPENSSL_FIPS_ENABLED=true"
26+
assert OpenSSL.fips_mode == false, message
27+
end;
28+
end
29+
730
def test_fips_mode_is_reentrant
831
OpenSSL.fips_mode = false
932
OpenSSL.fips_mode = false
1033
end
1134

12-
def test_fips_mode_get
13-
return unless OpenSSL::OPENSSL_FIPS
35+
def test_fips_mode_get_with_fips_mode_set
36+
omit('OpenSSL is not FIPS-capable') unless OpenSSL::OPENSSL_FIPS
37+
1438
assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
1539
begin
1640
OpenSSL.fips_mode = true
17-
assert OpenSSL.fips_mode == true, ".fips_mode returns true when .fips_mode=true"
41+
assert OpenSSL.fips_mode == true, ".fips_mode should return true when .fips_mode=true"
1842
1943
OpenSSL.fips_mode = false
20-
assert OpenSSL.fips_mode == false, ".fips_mode returns false when .fips_mode=false"
44+
assert OpenSSL.fips_mode == false, ".fips_mode should return false when .fips_mode=false"
2145
rescue OpenSSL::OpenSSLError
2246
pend "Could not set FIPS mode (OpenSSL::OpenSSLError: \#$!); skipping"
2347
end

0 commit comments

Comments
 (0)