Description
On SUSE Linux Enterprise Server running in FIPS mode, Go binaries built with go1.22
and the openssl/v2
module panic with panic: openssl: OpenSSL version: 0.0.0
. Go binaries built with go1.21
or earlier and the original openssl
module work as expected and dlopen()
the appropriate libcrypto.so
.
It would help with troubleshooting dlopen()
issues if panic(errUnsupportedVersion())
returned additional state information.
Expected Behavior
All examples below are running in FIPS mode:
# sysctl -a | grep fips_enabled
crypto.fips_enabled = 1
Using a toolchain built at tag go1.21.13-1-openssl-fips
(or any earlier tag in the go1.21
series or previous go1.x series
) with module github.com/golang-fips/openssl
, the produced Go application binary runs as expected:
# go build -gcflags="all=-N -l" https-server.go
# ./https-server
Starting server on :4000
Tracing confirms that this binary dlopens
/usr/lib64/libcrypto.so.3 -> libcrypto.so.3.1.4
. On an earlier distro version, dlopen
succeeds with /usr/lib64/libcrypto.so -> /lib64/libcrypto.so.1.0.0
.
Demonstration of Problem Behavior
Using a toolchain built at tag go1.22.5-3-openssl-fips
(or any earlier tag in the go1.22
series) with the new module github.com/golang-fips/openssl/v2
, the produced Go application binary panics with panic: openssl: OpenSSL version: 0.0.0
.
# go build -gcflags="all=-N -l" https-server.go
# ./https-server
panic: openssl: OpenSSL version: 0.0.0
goroutine 1 [running]:
vendor/github.com/golang-fips/openssl/v2.FIPS()
/usr/lib64/go/1.22-openssl/src/vendor/github.com/golang-fips/openssl/v2/openssl.go:110 +0x125
crypto/internal/backend.init.0()
/usr/lib64/go/1.22-openssl/src/crypto/internal/backend/openssl.go:22 +0xf
The code path raising the panic()
during fall-through to the default case:
// FIPS returns true if OpenSSL is running in FIPS mode, else returns false.
func FIPS() bool {
switch vMajor {
case 1:
return C.go_openssl_FIPS_mode() == 1
case 3:
// If FIPS is not enabled via default properties, then we are sure FIPS is not used.
if C.go_openssl_EVP_default_properties_is_fips_enabled(nil) == 0 {
return false
}
// EVP_default_properties_is_fips_enabled can return true even if the FIPS provider isn't loaded,
// it is only based on the default properties.
// We can be sure that the FIPS provider is available if we can fetch an algorithm, e.g., SHA2-256,
// explicitly setting `fips=yes`.
return C.go_openssl_OSSL_PROVIDER_available(nil, providerNameFips) == 1
default:
panic(errUnsupportedVersion())
}
}
It is not yet apparent what is causing the openssl/v2
fall-through to the default case when loading these specific libcrypto.so(s)
. The 0.0.0
designation from the panic leaves open the question of whether any libcrypto.so
is being found in this case. The other possibility is that a libcrypto.so
is found but its signatures are incompatible with certain checks.
I will describe ongoing runtime debug troubleshooting efforts using the delve debugger in subsequent comments.