Undocumented dependency on specific OpenSSL version
Opened this issue · 3 comments
golang-fips/openssl
is flexible in its support for OpenSSL versions; the version available at runtime does not have to match the version available at build time (https://github.com/golang-fips/openssl#portable-openssl). golang-fips/go
does not have this property; _goboringcrypto_DLOPEN_OPENSSL
loads only the version of the library that was available at build time (
go/patches/001-initial-openssl-for-fips.patch
Line 3470 in 7f64529
Is it possible for this repo to use the same tricks as golang-fips/openssl
to be version-agnostic? If not, could the failure to load the expected openssl version be a panic instead of silently falling back to the wrong crypto implementations? At the very least this hidden dependency should be documented.
FYI I ran into this moving a binary between Red Hat's ubi9
(which uses OpenSSL 3.0) and ubi8
(which uses OpenSSL 1.1).
Ah, I think I see that the version-agnostic behavior is new in v2 of the openssl package and that there are open PRs to update to that version. So it looks like that will get better soon but in the meantime some docs would be nice.
Hey, that's right, currently golang-fips/go
is still targeting the legacy branches of golang-fips/openssl
, where the dependency version is hard-coded in the preprocessor. Though it's not totally clear yet if or how the portable openssl selection mechanism in the v2 backend will translate into the golang-fips/go
fork. The bindings depend on dlopen, meaning glibc environment compatibility must also be preserved between build and deployment target. I've seen Go projects get around similar object compatibility issues by disabling CGO and linking statically but with golang-fips
we can't do this without losing the ability to call into openssl. Likewise static linking with CGO enabled is also not possible because of the caveats of moving around static binaries that make use of dlopen. So copying between different base images has basically been out of scope for the golang-fips/go fork in the past, and it's still a bit of an open question going forward at this point.
That said, there is a compile time switch that will produce a panic like you mentioned. GOEXPERIMENT=strictfipsruntime
, implemented in 002-strict-fips-runtime-detection.patch, will force a panic if boring.Enabled() == true
and the openssl object can't be loaded.
And +1 to documentation, it's becoming clear the need for project docs in general. I can open a new issue for docs tomorrow and link this as a sub task. Feel free to leave this open until it's complete if you like!
The bindings depend on dlopen, meaning glibc environment compatibility must also be preserved between build and deployment target.
True, but glibc has a pretty good compatibility story with symbol versioning. Personally I'm OK with the glibc requirement - we don't care about portability to non-glibc distributions and already have other dependencies on dlopen. But this is a good reminder that I'm not sure we've tested this issue recently.
That said, there is a compile time switch that will produce a panic like you mentioned. GOEXPERIMENT=strictfipsruntime, implemented in 002-strict-fips-runtime-detection.patch, will force a panic if boring.Enabled() == true and the openssl object can't be loaded.
Thanks, that's helpful (if a bit confusingly named - there's also GOLANG_STRICT_FIPS
which activates more strictness in a different way). FWIW I'd like something that goes a little further, and also fails if you build with this toolchain but don't set /proc/sys/crypto/fips_enabled
. The way I'm thinking about it is "download this build instead of the standard one, and then you'll never fall back to Go crypto" (that's how boringcrypto does it, right?). I see that you're intending this toolchain to be something you could use for a single release binary that could be FIPS or not based on the runtime configuration, which makes sense but I'm not sure we're ready to commit to using golang-fips for all our releases.