Skip to content

Use openssl.HashSignECDSA in fips-enabled Go 1.22#8

Closed
nalind wants to merge 1 commit intocontainers:mainfrom
nalind:go1.22
Closed

Use openssl.HashSignECDSA in fips-enabled Go 1.22#8
nalind wants to merge 1 commit intocontainers:mainfrom
nalind:go1.22

Conversation

@nalind
Copy link
Copy Markdown
Member

@nalind nalind commented May 2, 2024

Try to use openssl.HashSignECDSA instead of ecdsa.HashSign in Go 1.22 and later. The main trick is the format of the generated signature being different, but TestECSignVerify() uses the new function to generate signatures and the standard library's function to verify them, so I think it's right.

Try to use openssl.HashSignECDSA instead of ecdsa.HashSign in Go 1.22
and later.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
@mtrmac
Copy link
Copy Markdown

mtrmac commented May 6, 2024

In my testing, after go mod tidy && go mod vendor in a caller, I see build failures:

/_/GOROOT/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c:40: multiple definition of `go_openssl_fips_enabled'; /tmp/go-link-2433825165/000053.o:/…/skopeo/vendor/github.com/golang-fips/openssl/v2/goopenssl.c:40: first defined here

and many others. (Removing the vendor directory entirely doesn’t help, then it complains about $GOROOT/pkg/mod instead.).

Building this package directly, without any users, (in module mode, or with GO111MODULE=off and packages placed into GOPATH) fails similarly.

Am I missing a trick? (I tested this by installing the EL* golang* packages to Fedora 40; so it’s possible it’s all my fault.)


The main trick is the format of the generated signature being different,

At least the version in Go 1.20 was creating ASN.1 (which was immediately decoded in HashSignECDSA), but I can’t get that far.

@nalind
Copy link
Copy Markdown
Member Author

nalind commented May 6, 2024

I was checking this inside of a centos-stream-10-x86_64 mock chroot, so there could well be some mixing of a copies inside of $GOROOT and ./vendor that I wasn't noticing.

@mtrmac
Copy link
Copy Markdown

mtrmac commented May 6, 2024

Let me retry this tomorrow in a proper environment, so make sure it’s not me.

@nalind
Copy link
Copy Markdown
Member Author

nalind commented May 6, 2024

I get similar errors from inside of a container based on quay.io/centos/centos:stream10-development. Perhaps I didn't understand the advice we were being given after all.

@mtrmac
Copy link
Copy Markdown

mtrmac commented May 7, 2024

Testing this:

  • On a RHEL 10 build of some kind, build fails with “multiple definition” per the above
  • On a Fedora 40, it builds after
    package libtrust
    
    import "github.com/golang-fips/openssl/v2"
    
    func init() {
    	if err := openssl.Init("libcrypto.so.3"); err != nil { panic(err)}
    }
    is added. (Without that, tests panic with a nil reference. On RHEL, this function is called from crypto/internal/backend/openssl.go)

That seems consistent with the idea that the golang-fips/openssl package is automatically included in RHEL builds, and is not designed to be included multiple times — i.e. is not currently anticipated to be directly referenced by code outside of the standard library.


But even then the tests fail for me, e.g. ec_key_test.go:…: signature length is 72 octets long, should be 64. The signature produced is ASN.1 and needs to be decoded, e.g. the way crypto/ecdsa/ecdsa_legacy.go does.

@mtrmac
Copy link
Copy Markdown

mtrmac commented May 7, 2024

@derekparker could you help us with this, please?

Previously, around containers/skopeo#2297 (comment), you pointed at github.com/golang-fips/openssl.HashSignECDSA. As detailed above, that seems not to be usable from ordinary Go programs when built with the golang-fips/go-patched Go toolchain.

But, also, contra the motivating (private) https://bugzilla.redhat.com/show_bug.cgi?id=1740920 , where calling ecdsa.Sign used to panic, that method is nowadays, AFAICT, ordinarily available in the FIPS builds. Or, at least, with GOLANG_FIPS=1 OPENSSL_FORCE_FIPS_MODE=1, the call computes the expected signatures.

Is there some other way to build/use the golang-fips/openssl code, then? Or is this all no longer applicable, and can we revert to the standard-library ecdsa.Sign nowadays?

Thanks!

@derekparker
Copy link
Copy Markdown

derekparker commented May 7, 2024

@derekparker could you help us with this, please?

Absolutely!

Previously, around containers/skopeo#2297 (comment), you pointed at github.com/golang-fips/openssl.HashSignECDSA. As detailed above, that seems not to be usable from ordinary Go programs when built with the golang-fips/go-patched Go toolchain.

Sorry for the confusion there. I did not intent to imply that you should be importing that package yourself if you're already using the Go toolchain we provide. You're correct in that it is already provided by our toolchain internally.

But, also, contra the motivating (private) https://bugzilla.redhat.com/show_bug.cgi?id=1740920 , where calling ecdsa.Sign used to panic, that method is nowadays, AFAICT, ordinarily available in the FIPS builds. Or, at least, with GOLANG_FIPS=1 OPENSSL_FORCE_FIPS_MODE=1, the call computes the expected signatures.

I believe this to be a bug in the 1.22 toolchain we ship, where we do not provide these symbols exported publicly. We shipped them initially due to guidance from the crypto teams that hashing and signing should be done in a single-shot API due to FIPS limitations, however in more recent discussions that seems to be more of a "nice to have" feature to ensure that hashing and signing both happen via the certified crypto module.

Is there some other way to build/use the golang-fips/openssl code, then? Or is this all no longer applicable, and can we revert to the standard-library ecdsa.Sign nowadays?

Please do not revert to ecdsa.Sign just yet, it's actually somewhat deprecated anyways: https://cs.opensource.google/go/go/+/refs/tags/go1.22.3:src/crypto/ecdsa/ecdsa_legacy.go;l=58 (note it's now in ecdsa_legacy.go.

Thanks!

Let me sync with the crypto team on this and see if we can remove the HashSign and HashVerify symbols going forward. If not, we will provide those symbols in our next release.

@mtrmac
Copy link
Copy Markdown

mtrmac commented Jun 3, 2024

golang-fips/go#57 has restored the original API, and builds with libtrust_openssl now succeed for me; so I think these changes are no longer necessary.

@nalind
Copy link
Copy Markdown
Member Author

nalind commented Jun 3, 2024

Agreed, closing.

@nalind nalind closed this Jun 3, 2024
@nalind nalind deleted the go1.22 branch June 3, 2024 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants