golang-fips / go

Repository for FIPS enabled Go using OpenSSL

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Host being in FIPS mode"

johnrichardrinehart opened this issue · comments

This repo's README says that FIPS mode can be enabled through GOLANG_FIPS=1

or by virtue of the host being in FIPS mode.

go/README.md

Line 28 in ebcd504

* FIPS mode (or `boring` mode as the package is named) is enabled either via an environment variable `GOLANG_FIPS=1` or by virtue of the host being in FIPS mode.

Question 1: Can

return os.Getenv("GOLANG_FIPS") == "1" ||
C._goboringcrypto_FIPS_mode() == fipsOn
return true with an appropriately-configured OpenSSL whose version is <3 (a version which supports FIPS, obviously) without requiring GOLANG_FIPS=1 (so, one where fipsConfigured == true)?

Question 2: If the answer to Question 1 is that "host mode" is supported then what exactly is required to enable it? Setting OPENSSL_FIPS=1? Only changing the openssl.cnf such that the openssl binary is in FIPS mode, by default, is insufficient.

Question 1: Can

return os.Getenv("GOLANG_FIPS") == "1" ||
C._goboringcrypto_FIPS_mode() == fipsOn

return true with an appropriately-configured OpenSSL whose version is <3 (a version which supports FIPS, obviously) without requiring GOLANG_FIPS=1 (so, one where fipsConfigured == true)?

Yes, if you set fips_mode = on in the EVP Configuration Module section of the openssl.cnf file, see https://github.com/openssl/openssl/blob/OpenSSL_1_1_1-stable/doc/man5/config.pod#evp-configuration-module.

Specifically, something like

openssl_conf = openssl_init

[openssl_init]
alg_section = evp_properties

[evp_properties]
fips_mode = on

should do this. For OpenSSL 3, the same applies but the option needs to be default_properties = "fips=yes" instead of fips_mode = on.

Some Distributions change this to instead query a system-wide setting, e.g. on RHEL, FIPS mode is enabled using fips-mode-setup(8).

Question 2: If the answer to Question 1 is that "host mode" is supported then what exactly is required to enable it? Setting OPENSSL_FIPS=1? Only changing the openssl.cnf such that the openssl binary is in FIPS mode, by default, is insufficient.

See above, but this may depend on your distribution. Check with your distribution vendor for the detailed process.

Thanks for your response. It's interesting that you linked to the OpenSSL 1.1.1 documentation when only OpenSSL 1.0.1, 1.0.2, and 3.0+ support FIPS.

And, I've tested the above configuration file and can confirm that this does change the behavior of the openssl binary. But, it doesn't seem to affect go/C applications which link against OpenSSL (libcrypto and the FOM). They need to explicitly call FIPS_mode_set(1) in order to enable FIPS mode which isn't done by only linking against the library. In fact, the implicit call in boring.go to OPENSSL_init() does not read this configuration file or call FIPS_mode_set(1).

There does seem to be some evidence that calling OPENSSL_config() would do this but I don't see that being done anywhere.

Have you tested to confirm that the above is true?

Thanks for your response. It's interesting that you linked to the OpenSSL 1.1.1 documentation when only OpenSSL 1.0.1, 1.0.2, and 3.0+ support FIPS.

OpenSSL 1.1 has a FIPS mode, but may never have been certified by OpenSSL upstream. It certainly was certified according to FIPS 140-2 by other vendors ([1], [2], [3], [4] and many more).

Those vendors may have made further changes to the way FIPS mode is enabled. If you're interested in a specific implementation, you should contact the vendor of your FIPS-certified module.

And, I've tested the above configuration file and can confirm that this does change the behavior of the openssl binary. But, it doesn't seem to affect go/C applications which link against OpenSSL (libcrypto and the FOM). They need to explicitly call FIPS_mode_set(1) in order to enable FIPS mode which isn't done by only linking against the library. In fact, the implicit call in boring.go to OPENSSL_init() does not read this configuration file or call FIPS_mode_set(1).

I have tested this on RHEL 8, but RHEL 8's copy of OpenSSL adds a patch to read /proc/sys/crypto/fips_enabled in an __attribute__((constructor)) function and calls FIPS_mode_set(), so these results do not apply to OpenSSL upstream. It is certainly possible that this code would need to additionally call some other initialization function on a different platform.

There does seem to be some evidence that calling OPENSSL_config() would do this but I don't see that being done anywhere.

Have you tested to confirm that the above is true?

No.

@neverpanic You're right that OpenSSL 1.1 supports configuring (openssl.cnf) in FIPS mode and has the logic stubbed out. Better for me not to have said "only X, Y, and Z support FIPS" and, instead, "does not have an OpenSSL FIPS object module available". Thanks, also, for linking to 3rd-party vendors who sought and received validation/certification. Yeah, Oracle Linux has similar functionality which makes sense.

Thanks for interacting with me on this. I understand, now, that OpenSSL <3 (and not its forks) does not support "system" mode by default when linking against it, but that various operating systems and 3rd-party packages may provide some system-level support. Regardless, these forks are likely calling FIPS_mode_set(1) as a part of this system-level support.