Go 1.21 / FIPS

364 views
Skip to first unread message

Damien A

unread,
Jul 2, 2024, 11:45:40 AM (6 days ago) Jul 2
to golang-nuts

I have been building Grafana packages previously using Go 1.20.5 on Oracle Enterprise Linux 9 with the following settings:

export IMPORTPATH=%{_builddir}/grafana-%{version}
export BUILDFLAGS="-v -p 4 -x -buildmode=pie -mod=vendor"
export GOPATH=%{_builddir}/go:%{_builddir}/contrib
export GOBIN=/usr/local/go/bin
export GOEXPERIMENT=opensslcrypto
export GOFIPS=1
wire gen -tags 'oss' ./pkg/server ./pkg/cmd/grafana-cli/runner

# see grafana-X.Y.Z/pkg/build/cmd.go
export LDFLAGS="-X main.version=%{version} -X main.buildstamp=${SOURCE_DATE_EPOCH}"
for cmd in grafana grafana-cli grafana-server; do
    %gobuild -o %{_builddir}/bin/${cmd} ./pkg/cmd/${cmd}
done

However, we are now needing to upgrade to Grafana 10.4, which uses the newer Go version 1.21.10, and it appears the instructions around FIPS has changed a bit.


From what I gather, i should use 
GOEXPERIMENT=systemcrypto

and it seems that I shouldn't need to use GOFIPS=1, however if I leave that flag enabled, the compilation fails with:

+ cd /root/rpmbuild/BUILD/grafana-10.2.3
+ export IMPORTPATH=/root/rpmbuild/BUILD/grafana-10.2.3
+ IMPORTPATH=/root/rpmbuild/BUILD/grafana-10.2.3
+ export 'BUILDFLAGS=-v -p 4 -x -buildmode=pie -mod=vendor'
+ BUILDFLAGS='-v -p 4 -x -buildmode=pie -mod=vendor'
+ export GOPATH=/root/rpmbuild/BUILD/go:/root/rpmbuild/BUILD/contrib
+ GOPATH=/root/rpmbuild/BUILD/go:/root/rpmbuild/BUILD/contrib
+ export GOBIN=/usr/local/go/bin
+ GOBIN=/usr/local/go/bin
+ export GOEXPERIMENT=systemcrypto
+ GOEXPERIMENT=systemcrypto
+ export GOOS=linux
+ GOOS=linux
+ export GOFIPS=1
+ GOFIPS=1
+ wire gen -tags oss ./pkg/server ./pkg/cmd/grafana-cli/runner
wire: err: exit status 2: stderr: panic: FIPS mode requested (environment variable GOFIPS=1) but no supported crypto backend is enabled

        goroutine 1 [running]:
        crypto/internal/backend.init.0()
                crypto/internal/backend/common.go:21 +0x65

wire: generate failed
error: Bad exit status from /var/tmp/rpm-tmp.eIFDsO (%build)


RPM build errors:
    Bad exit status from /var/tmp/rpm-tmp.eIFDsO (%build)


Just curious if anyone can assist me here, using GOFIPS=1 worked just fine on Go 1.20.5, however appears not to be the case anymore.

Devin

Michael Oguidan

unread,
Jul 2, 2024, 1:42:06 PM (5 days ago) Jul 2
to golang-nuts
Hi,
Please can we dig the "crypto backend" first to see?

Damien A

unread,
Jul 2, 2024, 7:06:25 PM (5 days ago) Jul 2
to golang-nuts
Michael,

I am not fully sure what you mean? Can you elaborate on what you are asking me? I am not really a Go Developer just a Linux Admin who often gets tasked with trying to build packages.

Michael Oguidan

unread,
Jul 3, 2024, 2:02:46 PM (4 days ago) Jul 3
to golang-nuts
"wire: err: exit status 2: stderr: panic: FIPS mode requested (environment variable GOFIPS=1) but no supported crypto backend is enabled"
The problem could come from the fact that no crypto backend is enabled. So try to solve that first..

dagood

unread,
Jul 3, 2024, 9:45:37 PM (4 days ago) Jul 3
to golang-nuts
Hi Devin,

The FIPS functionality in Go (which, to be clear, is not supported for use outside of Google) is documented here: go/src/crypto/internal/boring/README.md at release-branch.go1.21 · golang/go (github.com), and it's used by setting GOEXPERIMENT=boringcrypto.

The GOEXPERIMENT=systemcrypto is a feature of the Microsoft fork of Go, not official Go. https://github.com/microsoft/go/blob/microsoft/main/eng/doc/fips/README.md is actually hosted in the microsoft/go repository, where that fork is maintained. I work on it, and I'm happy to help. (And, if you have any more questions related to this fork in the future, feel free to file a GitHub issue on microsoft/go directly.)

The issue doesn't seem related to Grafana, but rather because wire was built with the Microsoft fork of Go but without specifying a backend, but with GOFIPS=1. wire isn't able to be compatible with FIPS without a backend, but it sees that FIPS is requested, so it fails safe. It isn't clear what the caller's intent is and failing is an opportunity to catch a mistake. You should either:
  1. not set GOFIPS=1 until after calling wire (if at all!) or
  2. build wire with GOEXPERIMENT=systemcrypto.
I would default to (1). But if you are trying to make a FIPS compliant package build process, (2) would be the step towards that.

Whether or not you need GOFIPS=1 at all depends on the purpose of your script/build process.

> using GOFIPS=1 worked just fine on Go 1.20.5, however appears not to be the case anymore.

Yes, we only added this failsafe as of 1.21 of Microsoft Go. The first bullet in the 1.21 changelog has some details.

Hope that helps!

Michael Oguidan

unread,
Jul 4, 2024, 5:47:05 AM (4 days ago) Jul 4
to golang-nuts
Hi Dagood,
Please can you tell me what FIPS's for? And why we can't use it outside Google.

Ian Lance Taylor

unread,
Jul 4, 2024, 11:01:42 AM (4 days ago) Jul 4
to Michael Oguidan, golang-nuts
On Thu, Jul 4, 2024, 4:47 AM Michael Oguidan <michael...@gmail.com> wrote:
Hi Dagood,
Please can you tell me what FIPS's for? And why we can't use it outside Google.

You can use GOEXPERIMENT=boringcrypto, as described in the README.  However, there is no promise that the Go team will fix any problems you encounter.  It is not supported. 

Ian



--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/64e0eb63-0daa-4d5a-8fac-ad48dcb803dfn%40googlegroups.com.

dagood

unread,
Jul 5, 2024, 1:53:52 PM (2 days ago) Jul 5
to golang-nuts
Hi Michael,

Ian's clarification of "support" matches what I meant. In fact, the FIPS features in microsoft/go rely on many of the boringcrypto code changes. We've found it to be a good foundation for our implementation despite not being supported.

For background information about FIPS, look for info about FIPS 140 compliance. It's a US government security and cryptography standard, not specific to a particular programming language. The goal of these FIPS related features is to allow devs to build Go apps that are FIPS compliant, but it's important to note that even with these features, it's not straightforward. (See the disclaimers in the boringcrypto and microsoft/go readmes.)

Damien A

unread,
Jul 5, 2024, 9:41:11 PM (2 days ago) Jul 5
to golang-nuts
I am using the Microsoft version of Go lang as that is what my work instructed me to use.  My only task was to build Grafana using FIPS (or as close to it as i can get). As i mentioned in Microsoft Go 1.20.5 i was able to build using GOEXPERIMENT=opensslcrypto, and GOFIPS=1, but it appears now that with 1.21 Go that is no longer working using the same exact method. I have tried to use GOEXPERIMENT=systemcrypto, but it fails as well. 

I guess the ultimate question I have is do i even need to set GOFIPS=1 during compile to even make it FIPS compliant? it appears from Microsoft's FIPS page that it doesn't need to be set? https://github.com/microsoft/go/blob/microsoft/main/eng/doc/fips/README.md
So am I correct to think as long as I set GOEXPERIMENT=systemcrypto and compile that I am good on the build side of it? I also have applied a few changes that removes the not so good Ciphers from the SSL that was taken from the Fedora Project page.

What's interesting is if i just try to run: /usr/local/go/bin/go version, that fails if i have GOFIPS=1, and GOEXPERIMENT=systemcrypto, so i can even just simply have it print the version number which is strange. So not sure if when i manually compiled the Microsoft Go if i broke something or not? I am really just trying to understand how critical is it to set GOFIPS=1 during the build process? Is it a required option in order to build the go package?

Kurtis Rader

unread,
Jul 5, 2024, 11:11:39 PM (2 days ago) Jul 5
to Damien A, golang-nuts
GOFIPS doesn't appear anywhere in the official Google Go source, AFAICT. And the document at https://github.com/golang/go/blob/release-branch.go1.21/src/crypto/internal/boring/README.md is reasonably clear that simply setting GOEXPERIMENT=boringcrypto is all that is needed using the official Go implementation. I can't speak to the Microsoft fork of Go. While asking here about the Microsoft fork is a reasonable thing to do you may want to look for any discussion forums dedicated to the Microsoft fork.
--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank
Reply all
Reply to author
Forward
0 new messages