Skip to content

openssl/v2 module panic: openssl: OpenSSL version: 0.0.0 with formerly working libcrypto.so version #176

Closed
@jfkw

Description

@jfkw

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.sois 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions